im having trouble setting up trpc w/ websockets on latest t3...

... and i cant find a recent enough example at all! TLDR: has anyone made it work on the most recent version of create-t3? if so, how? could i be linked a repo to see how it's done? these are the two examples i found: - one from the trpc doc https://github.com/trpc/examples-next-prisma-websockets-starter/blob/main/src/server/wssDevServer.ts - this one i cant remember where i found it: https://github.com/fimbres/t3-live-chat/blob/main/package.json my understanding of the steps that are supposed to work: - you setup the wsslink in src/server/utils/api.ts - you make a wsServer.tsx file that: - defines a ws.Server - applies a wssAdapter to the approuter defined in src/server/api/root - is a standalone server independendent from the next server - you start the next server - you start the websocket server (i tried with the commands in the package.json of both of the repos i linked above) - the trpc on the frontend of next is going to point to the websocket server - magic your trpc calls are now passed through websocket instead of HTTP but this is what i get instead: (link: picture) im gonna stop pulling my hair and take a break, and then i'll make a public repo with a 1:1 recreation of the steps i took on the private project im working on.
GitHub
examples-next-prisma-websockets-starter/src/server/wssDevServer.ts ...
🏓 tRPC Next.js WebSocket Starter. Contribute to trpc/examples-next-prisma-websockets-starter development by creating an account on GitHub.
GitHub
t3-live-chat/package.json at main · fimbres/t3-live-chat
This is a project about a chat with real time functionality, implementing private and public rooms, developed with the T3 Stack for full-stack typescript development and websockets. - fimbres/t3-l...
No description
37 Replies
OtterSwims996
OtterSwims996•11mo ago
any luck on this? i'm trying to get websockets to work with my t3 app as well I noticed others have had similar questions in the discord related to websockets: https://discord.com/channels/966627436387266600/1140257505516195890/1140263582513254530 I'm trying to figure out how i can do the same thing where i run two servers to make this work this thread also yields some information: https://discord.com/channels/966627436387266600/1101996942906630254/1101996942906630254
cidit
ciditOP•11mo ago
Got it to work Im unavailable rn, ping me in 2-3hrs if ur available But it turns out, like all things, the tldr really isnt that complicated Basically, create a wss.ts in src/server (assuming your sources folder is called src, ofc) and fill it with the following:
import {WebSocketServer} from "ws"
import { applyWSSHandler } from "@trpc/server/adapters/ws"
import {appRouter} from "src/server/api/root"
import { createTRPCContext } from "src/server/api/trpc"

const wss = new WebSocketServer({
port: 3005
})

const handler = applyWSSHandler({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
wss, router: appRouter, createContext: createTRPCContext as any
})

wss.on("connection", (ws) => {
const fakeClientId = Math.floor(Math.random() * 1000)
console.info(`client_connected ${fakeClientId}`)
ws.once("close", () => {
console.info(`cliend_close ${fakeClientId}`)
})
})


console.info("wss enabled")

process.on('SIGTERM', () => {
console.log('SIGTERM');
handler.broadcastReconnectNotification();
wss.close();
});
import {WebSocketServer} from "ws"
import { applyWSSHandler } from "@trpc/server/adapters/ws"
import {appRouter} from "src/server/api/root"
import { createTRPCContext } from "src/server/api/trpc"

const wss = new WebSocketServer({
port: 3005
})

const handler = applyWSSHandler({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
wss, router: appRouter, createContext: createTRPCContext as any
})

wss.on("connection", (ws) => {
const fakeClientId = Math.floor(Math.random() * 1000)
console.info(`client_connected ${fakeClientId}`)
ws.once("close", () => {
console.info(`cliend_close ${fakeClientId}`)
})
})


console.info("wss enabled")

process.on('SIGTERM', () => {
console.log('SIGTERM');
handler.broadcastReconnectNotification();
wss.close();
});
then, add the websockets ending link in src/utils/api.ts:
import { createWSClient, wsLink } from "@trpc/client";
import { createTRPCNext } from "@trpc/next";

const wssLink = wsLink<AppRouter>({
client: createWSClient({
url: "ws://localhost:3005",
onOpen: () => console.info("ws con established"),
onClose: () => console.info("ws con closed"),
}),
});

export const api = createTRPCNext<AppRouter>({
config({ ctx: _ctx }) {
return {
// ...
links: [
// ...
wssLink
],
};
},
import { createWSClient, wsLink } from "@trpc/client";
import { createTRPCNext } from "@trpc/next";

const wssLink = wsLink<AppRouter>({
client: createWSClient({
url: "ws://localhost:3005",
onOpen: () => console.info("ws con established"),
onClose: () => console.info("ws con closed"),
}),
});

export const api = createTRPCNext<AppRouter>({
config({ ctx: _ctx }) {
return {
// ...
links: [
// ...
wssLink
],
};
},
alot of ppl do a getEndingLink function instead that fallbacks to a httpBatchLink if window is undefined. i omitted it for simplicity, but you should do that too.
OtterSwims996
OtterSwims996•11mo ago
so will this run both the websocket server along side the main node server? meaning both ports 3005 and 3000 will run when running the application?
cidit
ciditOP•11mo ago
heres the catch: you launch them separately
OtterSwims996
OtterSwims996•11mo ago
okay so the startup commands have to be configured to do that like in the prisma app
cidit
ciditOP•11mo ago
yea
OtterSwims996
OtterSwims996•11mo ago
GitHub
examples-next-prisma-websockets-starter/package.json at 077367508a7...
🏓 tRPC Next.js WebSocket Starter. Contribute to trpc/examples-next-prisma-websockets-starter development by creating an account on GitHub.
OtterSwims996
OtterSwims996•11mo ago
sorry this is a newbie question, but how does the client side code know whether to query port 3000 or 3005?
cidit
ciditOP•11mo ago
i added a script in my package.json for that like this:
"dev:wss": "cross-env PORT=3005 tsx watch src/server/wss.ts --tsconfig tsconfig.server.json",
"dev:wss": "cross-env PORT=3005 tsx watch src/server/wss.ts --tsconfig tsconfig.server.json",
that way, when i run
pnpm dev:wss
pnpm dev:wss
it launches the wss server, and then i do
pnpm dev
pnpm dev
which starts the next server
OtterSwims996
OtterSwims996•11mo ago
yea i see that the prisma example project does something similar
cidit
ciditOP•11mo ago
from what i understand, the frontend "trpc hook" (src/pages/api/trpc/[trpc].ts) looks for what it needs in src/utils/api.ts
OtterSwims996
OtterSwims996•11mo ago
oh interesting i see and whenever it queries even the websocket server, it automatically knows to go to the right code for the websocket subscription even if its located next to non websocket code
cidit
ciditOP•11mo ago
in theory, do those steps and subscriptions should work correctly and u can just look at the docs to find what to do next yes, if i understand correctly all of your trafic goes thru websocket now because of the ending link not being http
OtterSwims996
OtterSwims996•11mo ago
what about non websocket code? like in the example project some transactions shouldn't need a websocket subscription they use query and mutate, which shouldn't need a persistent connection they are located right next to the subscription code
cidit
ciditOP•11mo ago
i think the reasoning is that since websockets are more efficient, you might as well use websockets instead of http if you already have a connection
OtterSwims996
OtterSwims996•11mo ago
oh ok, interesting
cidit
ciditOP•11mo ago
i think i might be completely wrong
OtterSwims996
OtterSwims996•11mo ago
its a bit hard to understand the set up haha
cidit
ciditOP•11mo ago
for my use case i only need websockets for client-server interactions so i didnt bother looking up more
OtterSwims996
OtterSwims996•11mo ago
i will try your implementation and hopefully it will just work gotcha
cidit
ciditOP•11mo ago
definetly
OtterSwims996
OtterSwims996•11mo ago
would you happen to have a github link so i can see your use cases?
cidit
ciditOP•11mo ago
ayt lmk if u have issues. cant guarantee a timely response, but there will be one
OtterSwims996
OtterSwims996•11mo ago
sure thing
cidit
ciditOP•11mo ago
unfortunately its propriatery, so i cant show u
OtterSwims996
OtterSwims996•11mo ago
okay no problem
cidit
ciditOP•11mo ago
but i can share with you the relevant snippets, which are basically just the ones above
OtterSwims996
OtterSwims996•11mo ago
okay sure i will try what i can for now
cidit
ciditOP•11mo ago
đź‘Ť ttyl
OtterSwims996
OtterSwims996•11mo ago
thanks for sharing your code snippets and solutions
cidit
ciditOP•11mo ago
np np @OtterSwims checking in that it does indeed work
OtterSwims996
OtterSwims996•11mo ago
Hey thanks for checking in, i think i was able to successfully get my websocket set up and running, since i see a "ws con established" log message on my client, but i dont seem to be able to trigger events on my backend to send information to the front end :/
OtterSwims996
OtterSwims996•11mo ago
this is what i see
No description
OtterSwims996
OtterSwims996•11mo ago
GitHub
ttt/tic-tac-toe/src/pages/index.tsx at bb0474b64cd463a3aaa6a2230598...
Contribute to sumanthneerumalla/ttt development by creating an account on GitHub.
GitHub
ttt/tic-tac-toe/src/server/api/routers/post.ts at bb0474b64cd463a3a...
Contribute to sumanthneerumalla/ttt development by creating an account on GitHub.
Louis
Louis•11mo ago
I've made a similar post asking for help but didn't get much response, it's great to see responses on this post! Regarding your project, are you using pages or app router? If it's app router with T3, are you using next auth in your context? I've been trying to figure out how to get the websocket server to run because of an issue caused by next auth since the session is called via context.
OtterSwims996
OtterSwims996•11mo ago
I believe i'm using page router only, i'm not sure how to check though I'm not using next auth just yet, but i was going to implement it later. I have been thinking that maybe i should just start from someone elses existing base project like here and just use that: https://github.com/Lada496/my-t3-twitter-lite it seems to already be using prisma and next auth along with sockets. I found it on this medium post here: https://medium.com/@lada496/trpc-102-subscription-web-socket-d81b8962a010
GitHub
GitHub - Lada496/my-t3-twitter-lite
Contribute to Lada496/my-t3-twitter-lite development by creating an account on GitHub.
Medium
tRPC 102: Subscription/Web Socket
This is my memo when I implemented a subscription with tRPC along with the official documents. I also referred to the code example provided…
Want results from more Discord servers?
Add your server