Skip to main content

BFF-WS-EXT

General​

This extension provides ability to consume messages from BE via WebSockets. On server connection provided over RabbitMQ in future probably another MQ will be added.

Backend part​

Installation​

$ npm install @invent/bff-ws-ext

Configuration​

On first place you have to describe configuration params.

import { ExtInitConfig } from '@invent/bff-ws-ext';

export const bffWsExt: ExtInitConfig = {
messages: [],
extHost: `${process.env.MY_HOST}:443`,
qOptions: {
qName: 'my-tenant-prefix',
qHost: process.env.RMQ_HOST
}
};

type ExtInitConfig = {
pathOverride?: {
root: string;
schema: string;
channel: string;
};
messages: SchemaMessagesT<unknown>[];
qOptions: QOptionsT;
};

Path override​

  • this is optional config key
  • this key provides ability to override endpoints for this extension
pathOverride?: {
root: string;
schema: string;
channel: string;
};

Default values are:

/ext/ws/schema
/ext/ws/channel

QOptions​

  • for now implemented support only for rabbitMq
  • this is mandatory config key
  • if port not setted up default rabbitmq port will be used
type QOptionsT = {
qName: string;
qPort?: number;
qHost: string;
}

Example:

{
qName: 'wlabel',
qPort: '101107',
qHost: 'amqp://0.0.0.0'
}

Messages​

TO BE IMPLEMENTED

Connection mapping​

  • all connections of user will be binded to user ID provided in JWT (the sub claim).
  • messages from rabbitMq will be sent to all user connections in all browser tabs.

Init & expose​

import { bffWsExt } from './src/extentions/ws-extention';
import { initBffWsExt } from '@invent/bff-ws-ext';

....
app.use(
validateRequestTokenMiddlewareFabric([
'/images',
'/templates/assets/fonts',
'/theme',
'/theme/my-default-theme',
'/tenent',
'/ext/ws/channel/.websocket'
])
);
overrideRoutes();
let extentions = [];
extensions = await initBffWsExt(app, bffWsExt, extentions);
exposeExtensions(extentions);
endpointConfig.forEach((domain) => hydrate(app, domain));

Exposed extensions in this example​

[
{
"author":"Nameless invent developer",
"name":"@invent/bff-ws-ext",
"version":"1.0.12",
"module":"./BffWssCompanion",
"scope":"companion_bff_ws_ext",
"extHost":"https://fe-be.dev.clic.apptrium.cloud:443",
"companion":"https://inventwidgetextensions.z19.web.core.windows.net/271/remoteEntry.js",
"pathList":[
{
"method":"get",
"path":"/ext/ws/schema"
},
{
"method":"ws",
"path":"/ext/ws/channel"
}
]
}
]
  • The order of function calls is important
  • extensions is list of mounted extenstions. In case you use more then one installed extension, pass this var to another iniAnotherExt function.
  • The part /ext/ws/channel/.websocket exposes connection. Also please keep in mind that .websocket is mandatory.
  • exposeExtnsions used to expose list of installed extensions. If you want to add customization or override some params, you can do it on extenstions before pass to exposeExtensions function.

Companion​

Subscribe​

In place where you whan to subscribe on WebSocket.

// In case you are in host application area
import { getExtension, getExtensionsList } from '@/lib/module-federation/use-extensions';

// In case you are accessing websocket extension in widget
const { getExtension, getExtensionsList } = props;

// mySubscriptionId should be placed outside the component
const mySubscriptionId = v4();

useEffect(() => {
const wss = getExtension('@invent/bff-ws-ext');
if (wss && wss.subscribe) {
// (entity: string, id: string, callback: (message: unknown) => void) => void
wss.subscribe('Notification', mySubscriptionId, (message: unknown) => console.log(message));
/*
`entity` refers to `headers.entity` in websocket message.
So you subscribing to specific entity events.

`id` is unique string id.

`callback` is handler function.
*/
}
}, [getExtension('@invent/bff-ws-ext')]);
  • you can wrap handler with React-Query or another wrapper.

Unsubscribe​

import { getExtencion } from '@/lib/module-federation/use-extensions';
import { useUnmount } from 'react-use';

useUnmount(() => {
const wss = getExtencion('@invent/bff-ws-ext');
if (wss) {
// mySubscriptionId same value as in subscribe
wss.unsubscribe('Notification', mySubscriptionId);
}
});

Common websocket messages shape​

{
"message": {
"downloadId":"cbe1894e44984b74b9f829f8ddeb9c50",
"userId":"00000",
"type":1,
"name":"contacts-grid_08-21-2021_19-23",
"uri":"https://clicqacudata.blob.core.windows.net/files/downloads/cbe1894e44984b74b9f829f8ddeb9c50?sv=2020-08-04&se=2021-09-21T13%3A23%3A19Z&sr=b&sp=r&rscd=attachment%3B+filename%3Dcontacts-grid_08-21-2021_19-23&sig=2tNFPCOMJR1rkyGgBLuP5MIlV4IetsC6afMjSXUuBb0%3D",
"status":2,
"expiresAt":"2021-09-21T13:23:16.516Z",
"createdAt":"2021-09-21T12:23:19.0470019Z",
"scope":3
},
"headers": {
"x-datadog-trace-id":"7247253089438860160",
"x-datadog-parent-id":"7380314150188049681",
"x-datadog-sampling-priority":"1",
"CausationId":"541750d3-1c93-4656-a40b-237c8c3da2c0",
"CausedBy":"DCore.FinTech.Messages.Downloads.Commands+V1+SetDownloadAvailable",
"CorrelationId":"25df0318-ab3a-5087-b345-681753ee5ed5",
"TenantId":"CIR",
"entity":"Download",
"recipientId":"00000",
"deliveryMethod":"Direct"
}
}