Gadget websocket support ?

Does gadget support websockets ? Couldn’t find it in the docs
10 Replies
Chocci_Milk
Chocci_Milk7mo ago
Hello, Yes we do. Let me share some examples
Tanmay
TanmayOP7mo ago
Is it somewhere in docs ?
Chocci_Milk
Chocci_Milk7mo ago
No, I've made an application take hooks into the Discord API (websocket).
// in api/boot/discord.js

import { Server, logger } from "gadget-server";
import { registerEvents, discordGatewayClient } from "../../utilities";

/**
* Server boot plugin
*
* @param { Server } server - server instance to customize
*
* @see {@link https://www.fastify.dev/docs/latest/Reference/Server}
*/
export default async function (server) {
// This function needs the connections object
registerEvents({ client: discordGatewayClient });

await discordGatewayClient.login(process.env.DISCORD_BOT_TOKEN);

logger.info("registered discord events");

setInterval(async () => {
// Check if connected, if NOT, then reconnect
if (discordGatewayClient.ws.status === 5) {
await discordGatewayClient.destroy();

// Relog into client
logger.info("Reconnecting to Discord");
await discordGatewayClient.login(process.env.DISCORD_BOT_TOKEN);
}
}, 1000).unref();

server.addHook("onClose", async () => {
// when server shuts down run this function
await discordGatewayClient.destroy();
});
}
// in api/boot/discord.js

import { Server, logger } from "gadget-server";
import { registerEvents, discordGatewayClient } from "../../utilities";

/**
* Server boot plugin
*
* @param { Server } server - server instance to customize
*
* @see {@link https://www.fastify.dev/docs/latest/Reference/Server}
*/
export default async function (server) {
// This function needs the connections object
registerEvents({ client: discordGatewayClient });

await discordGatewayClient.login(process.env.DISCORD_BOT_TOKEN);

logger.info("registered discord events");

setInterval(async () => {
// Check if connected, if NOT, then reconnect
if (discordGatewayClient.ws.status === 5) {
await discordGatewayClient.destroy();

// Relog into client
logger.info("Reconnecting to Discord");
await discordGatewayClient.login(process.env.DISCORD_BOT_TOKEN);
}
}, 1000).unref();

server.addHook("onClose", async () => {
// when server shuts down run this function
await discordGatewayClient.destroy();
});
}
Chocci_Milk
Chocci_Milk7mo ago
utilities/clients/discord/helpers/registerEvents.js
Tanmay
TanmayOP7mo ago
How would the cost work for websockets ? Also does it support SSE ?
airhorns
airhorns7mo ago
do you mean outgoing websockets or incoming websockets Tanmay? like connecting to someone else's websocket, or listening to websockets from the browser connecting to your app? gadget supports outgoing websockets just fine, but it can definitely get expensive if you need to be listening all the time. we can work out custom pricing if its going to be really big. and then gadget also supports incoming websockets just fine, as well as SSE. we use websockets for vite HMR and SSE for AI apps often you can also avoid the need to create your own websockets or SSE systems with live queries which are all wired up and ready to go and don't have any of the same billing concerns
Tanmay
TanmayOP7mo ago
Just for more context this is what I am trying to do https://discord.com/channels/836317518595096598/1336906030784843786 Thanks for the example @Chocci_Milk What endpoint would I be able to access this websocket on ? ws:://app-url/ ? Is SSE stuff documented anywhere ? I tried to set that up in routes but didnt work so kinda confused where to put that code and what endpoint to access it from
Chocci_Milk
Chocci_Milk7mo ago
The way that I set it up was by making a route just for the Discord webscoket. Here's the code that I had:
// in api/routes/discord/POST.js
import { RouteContext } from "gadget-server";
import { verifyKey } from "discord-interactions";

/**
* Route handler for POST discord
*
* @param { RouteContext } route context - see: https://docs.gadget.dev/guides/http-routes/route-configuration#route-context
*
*/
export default async function route({
request,
reply,
api,
logger,
connections,
headers,
}) {
const {
body,
headers: {
"x-signature-ed25519": signature,
"x-signature-timestamp": timestamp,
},
rawBody,
} = request;

const verified = verifyKey(
rawBody,
signature,
timestamp,
process.env.DISCORD_PUBLIC_KEY
);

if (!verified) {
return await reply.code(401).send();
}

await reply.code(200).send({ type: body.type });
}
// in api/routes/discord/POST.js
import { RouteContext } from "gadget-server";
import { verifyKey } from "discord-interactions";

/**
* Route handler for POST discord
*
* @param { RouteContext } route context - see: https://docs.gadget.dev/guides/http-routes/route-configuration#route-context
*
*/
export default async function route({
request,
reply,
api,
logger,
connections,
headers,
}) {
const {
body,
headers: {
"x-signature-ed25519": signature,
"x-signature-timestamp": timestamp,
},
rawBody,
} = request;

const verified = verifyKey(
rawBody,
signature,
timestamp,
process.env.DISCORD_PUBLIC_KEY
);

if (!verified) {
return await reply.code(401).send();
}

await reply.code(200).send({ type: body.type });
}
Tanmay
TanmayOP7mo ago
Thanks for this what would be the ws endpoint if I am connecting to it from the frontend ?
Chocci_Milk
Chocci_Milk7mo ago
We've discussed this on a call and what was decided was a rework of the feature to use bulkOperations and make logs about product update batches rather than each individual product

Did you find this page helpful?