handsaway
handsaway12mo ago

Can I alter the context in a procedure?

Is there a proper way to do this? Mutating the opts.ctx directly seems wrong
2 Replies
NeoBean
NeoBean12mo ago
I think middlewares are meant for things like this? You define your initial context types when instantiating trpc. Then you use a middleware that appends variables to the context. You can opts.next({ user: user }) and next middlewares/queries/mutations will the ctx.user typed. Is this what you're looking for?
handsaway
handsaway12mo ago
I need to keep track of a session id across the lifespan of a websocket connection to correlate messages to users, the client also keeps this in local storage to handle re-connection flows
registerSession: publicProcedure
.input(z.object({ sid: z.nullable(z.string()) }))
.mutation(async (opts) => {
logger.info('registerSession');
// Already an sid attached to this websocket
if (opts.ctx.sid !== undefined) {
logger.info(
'registerSession called with existing sessionId on websocket'
);
return opts.ctx.sid;
}

if (opts.input.sid === undefined) {
logger.info('Generating new sessionId');
} else {
logger.info('Using sessionId supplied by client', {
sessionId: opts.input.sid,
});
}

const sid = opts.input.sid ?? uuidV4();

// Not positive that this is the best place to keep the sid,
// but it's available in the context this way
opts.ctx.ws['sid'] = sid;
return sid;
}),
registerSession: publicProcedure
.input(z.object({ sid: z.nullable(z.string()) }))
.mutation(async (opts) => {
logger.info('registerSession');
// Already an sid attached to this websocket
if (opts.ctx.sid !== undefined) {
logger.info(
'registerSession called with existing sessionId on websocket'
);
return opts.ctx.sid;
}

if (opts.input.sid === undefined) {
logger.info('Generating new sessionId');
} else {
logger.info('Using sessionId supplied by client', {
sessionId: opts.input.sid,
});
}

const sid = opts.input.sid ?? uuidV4();

// Not positive that this is the best place to keep the sid,
// but it's available in the context this way
opts.ctx.ws['sid'] = sid;
return sid;
}),
I have this where I'm kind of shoving the uuid onto the websocket object then
export const createWSContext = async (opts: CreateWSSContextFnOptions) => {
const sid: string = opts.res['sid'];
logger.debug('createWSContext', { sid });
return { sid, ws: opts.res };
};
export const createWSContext = async (opts: CreateWSSContextFnOptions) => {
const sid: string = opts.res['sid'];
logger.debug('createWSContext', { sid });
return { sid, ws: opts.res };
};
But this doesn't seem like the best way to do this like I'm just hijacking the websocket object, but I guess i need something in memory to mutate to retrieve a session id in teh create context