Overview
Getting started with Weave.js Azure Web PubSub store API
The Azure Web PubSub Store is a store for Weave.js that uses the Azure Web PubSub cloud infrastructure as the transport layer to enable real-time collaboration over the internet.
This store includes:
- A class named WeaveAzureWebPubsubServer that helps setup the backend on top of an Express service.
- A class named WeaveStoreAzureWebPubsub which is the client used on the frontend side to connect to the store backend and provide all the support for the real-time management of the shared-state.
Backend-side usage
Setup the frontend is easy, you just need to follow this steps on your Express-based backend:
Install the WebSocket Store backend dependencies
First lets install the necessary dependencies on the backend-side:
npm install canvas @azure/web-pubsub @azure/web-pubsub-express y-protocols yjs @inditextech/weave-store-azure-web-pubsub
Setup the server
Then setup your server as needed, here you have an example of a simple server, where the persistence is handled on the file system:
import { fileURLToPath } from "url";
import path from "path";
import fs from "fs/promises";
import cors from "cors";
import express, { Router } from "express";
import { WeaveAzureWebPubsubServer } from "@inditextech/weave-store-azure-web-pubsub/server"; // (1)
// eslint-disable-next-line @typescript-eslint/naming-convention
const __filename = fileURLToPath(import.meta.url);
// eslint-disable-next-line @typescript-eslint/naming-convention
const __dirname = path.dirname(__filename);
const host = process.env.WEAVE_AZURE_WEB_PUBSUB_HOST || "localhost";
const port = parseInt(process.env.WEAVE_AZURE_WEB_PUBSUB_PORT || "1234");
const endpoint = process.env.WEAVE_AZURE_WEB_PUBSUB_ENDPOINT; // (2)
const key = process.env.WEAVE_AZURE_WEB_PUBSUB_KEY; // (2)
const hubName = process.env.WEAVE_AZURE_WEB_PUBSUB_HUB_NAME; // (2)
if (!endpoint || !key || !hubName) {
throw new Error("Missing required environment variables");
}
// prettier-ignore
const azureWebPubsubServer = new WeaveAzureWebPubsubServer({ // (3)
pubsubConfig: {
endpoint,
key,
hubName,
}, // (4)
fetchRoom: async (docName: string) => {
try {
const roomsFolder = path.join(__dirname, "rooms");
const roomsFile = path.join(roomsFolder, docName);
return await fs.readFile(roomsFile);
} catch (e) {
return null;
}
}, // (5)
persistRoom: async (
docName: string,
actualState: Uint8Array<ArrayBufferLike>
) => {
try {
const roomsFolder = path.join(__dirname, "rooms");
let folderExists = false;
try {
await fs.access(roomsFolder);
folderExists = true;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
folderExists = false;
}
if (!folderExists) {
await fs.mkdir(roomsFolder, { recursive: true });
}
const roomsFile = path.join(roomsFolder, docName);
await fs.writeFile(roomsFile, actualState);
} catch (ex) {
console.error(ex);
}
}, // (6)
});
const app = express();
const corsOptions = {
origin: true,
};
app.use(cors(corsOptions));
const router = Router();
router.use(azureWebPubsubServer.getMiddleware()); // (7)
router.get(`/rooms/:roomId/connect`, async (req, res) => {
const roomId = req.params.roomId;
const url = await azureWebPubsubServer.clientConnect(roomId);
res.json({ url });
}); // (8)
app.use(`/api/v1/${hubName}`, router); // (9)
app.listen(port, host, (err: Error | undefined) => {
// (10)
if (err) throw err;
// eslint-disable-next-line no-console
console.log(`Server started @ http://${host}:${port}\n`);
// eslint-disable-next-line no-console
console.log(`Connection endpoint: /api/v1/${hubName}/{roomId}/connect`);
});
File explanation:
(1)
: Import the Weave.js server dependencies.(2)
: Define the endpoint, key and hubName of the Azure Web PubSub instance where we will connect.(3)
: Instantiate theWeaveAzureWebPubsubServer
class. Which returns the server utilities to handle Azure Web PubSub connections.(4)
: Define the Azure Web Pubsub properties.(5)
: Define thefetchRoom
function that handles theget
part of the persistence, in this case we fetch a binary file with the shared-state from the file system if exists.(6)
: Define thepersistRoom
function that handles theset
part of the persistence, in this case we save to a file on the file system the shared-state.(7)
: Setup the middleware that handles the Azure Web PubSub connections.(8)
: Setup a route that is responsible to call theclientConnect
method of the server in order to obtain a secure connection URL to the Azure Web PubSub Hub.(9)
: Setup the server routes.(10)
: Start the server.
When an user tries to join a room, it calls the defined route with the room Id where he
want to join, then the WeaveAzureWebPubsubServer
using the clientConnect
function, call the Azure Web PubSub
Hub to extract a secure connection and this URL is passed as response to the client. Then the client connects to
this URL and the server does the rest: persistence, handling the messages sent over the connection, etc.
Frontend-side usage
Setup the frontend is easy, you just need to follow this steps:
Install the WebSocket Store frontend dependency
First lets install the necessary dependencies for the frontend client:
npm install @inditextech/weave-store-azure-web-pubsub
Setup the client on the Weave instance
Then you need to add the Azure Web PubSub store client to the Weave instance in order to handle the connection when the user tries to join a room. This is done:
import { WeaveStoreAzureWebPubsub } from "@inditextech/weave-store-azure-web-pubsub/client"; // (1)
const roomId = "MyRoom"; // (2)
const store = new WeaveStoreAzureWebPubsub( // (3)
{
getUser, // (4)
undoManagerOptions: {
captureTimeout: 500,
}, // (5)
},
{
roomId, // (6)
url: http://localhost:1234/api/v1/rooms/${roomId}/connect`, // (7)
}
);
const instance = new Weave(
{
...
store, // (8)
},
...
);
Explanation:
(1)
: Import the Weave.js client dependencies.(2)
: Define the room Id to connect to.(3)
: Instantiate theWeaveStoreAzureWebPubsub
class. Which returns the Azure Web PubSub store client.(4)
: Define thegetUser
function that return the metadata of the user that wants to connect.(5)
: We customize thecaptureTimeout
of the Undo-Redo manager of the store, to capture changes every 500ms.(6)
: We set the room Id where we want to connect to.(7)
: Define url where we want to connect and fetch the connection URL to the Azure Web PubSub.(8)
: Set the instantiated store to the Weave instance.