Mugetsu
Mugetsu
TtRPC
Created by Mugetsu on 1/22/2024 in #❓-help
Controller is already closed crash
@JLN hi. No. I still experience these errors but simply ignore them atm. They happen from time to time
7 replies
TtRPC
Created by Mugetsu on 2/14/2024 in #❓-help
onError callback type
This seems to work but not sure if this is any better approach.

export type DownloadTriggerOnError =
| TRPCClientErrorLike<AppRouter>
| Error
| undefined;

export type DownloadTriggerOnError =
| TRPCClientErrorLike<AppRouter>
| Error
| undefined;
6 replies
TtRPC
Created by Mugetsu on 2/14/2024 in #❓-help
onError callback type
It doesnt satisfiy the constrain TS2344: Type  unknown  does not satisfy the constraint  ErrorInferrable
6 replies
TtRPC
Created by Mugetsu on 2/10/2024 in #❓-help
How to extract mutation type
I thought I had a problem with payload: RouterInputs['batch']['triggerDownload'], but after restarting TS its working. So all good now 🙂
11 replies
TtRPC
Created by Mugetsu on 2/10/2024 in #❓-help
How to extract mutation type
RouterInputs are these.
/**
* Inference helper for inputs.
* @example type HelloInput = RouterInputs['example']['hello']
*/
export type RouterInputs = inferRouterInputs<AppRouter>;

/**
* Inference helper for outputs.
* @example type HelloOutput = RouterOutputs['example']['hello']
*/
export type RouterOutputs = inferRouterOutputs<AppRouter>;

export type ReactQueryOptions = inferReactQueryProcedureOptions<AppRouter>;
/**
* Inference helper for inputs.
* @example type HelloInput = RouterInputs['example']['hello']
*/
export type RouterInputs = inferRouterInputs<AppRouter>;

/**
* Inference helper for outputs.
* @example type HelloOutput = RouterOutputs['example']['hello']
*/
export type RouterOutputs = inferRouterOutputs<AppRouter>;

export type ReactQueryOptions = inferReactQueryProcedureOptions<AppRouter>;
11 replies
TtRPC
Created by Mugetsu on 2/10/2024 in #❓-help
How to extract mutation type
Thanks guys. Altough I cant seem to get it working with InferReactQueryOptions I managed to take te routerinputs and seems working like that
export type MutateTrigger = (
payload: RouterInputs['batch']['triggerDownload'],
) => void;
export type MutateTrigger = (
payload: RouterInputs['batch']['triggerDownload'],
) => void;
11 replies
TtRPC
Created by Mugetsu on 1/22/2024 in #❓-help
Controller is already closed crash
So after some digging I found that the fetch request inside the tRPC procedure is causing this error to happen. It's not clear to me why this happens but when I have such procedure
export const appRouter = createTRPCRouter({
getSchemas: procedure.query(async ({ ctx }) => {
try {
const response = await fetch(
`${serverEnv.LOCATION_SERVICE_URL}/v4/schemas`,
{
headers: {
Authorization: `Bearer ${ctx.sessionIdToken}`,
},
},
);
const apiSchemas = await response.json();
const currentSchemaId = cookies().get(SCHEMA_COOKIE_KEY)?.value;
const locationsSchema = new LocationSchema(
apiSchemas.locationSchemas,
currentSchemaId,
);

return locationsSchema.toJSON();
} catch (e) {
trpcLogger.error(e, 'Error getting schema');

return undefined;
}
}),

post: postRouter,
});
export const appRouter = createTRPCRouter({
getSchemas: procedure.query(async ({ ctx }) => {
try {
const response = await fetch(
`${serverEnv.LOCATION_SERVICE_URL}/v4/schemas`,
{
headers: {
Authorization: `Bearer ${ctx.sessionIdToken}`,
},
},
);
const apiSchemas = await response.json();
const currentSchemaId = cookies().get(SCHEMA_COOKIE_KEY)?.value;
const locationsSchema = new LocationSchema(
apiSchemas.locationSchemas,
currentSchemaId,
);

return locationsSchema.toJSON();
} catch (e) {
trpcLogger.error(e, 'Error getting schema');

return undefined;
}
}),

post: postRouter,
});
And I do manually refresh my app (browser refresh) fast enough multiple times in a row the query errors and then it throws Invalid state: Controller is already closed and crash the app. When I just remove the fetch call it never throws that controller error but I still can see enigmatic error for the query in the console.
7 replies
TtRPC
Created by Mugetsu on 1/22/2024 in #❓-help
Controller is already closed crash
this is really bothering me and I cant find the problem with this. This error completely crashes my app
7 replies
TtRPC
Created by Mugetsu on 1/9/2024 in #❓-help
LoggerLink logging only via server logger in prod
Is it fine like this??
loggerLink({
logger: (op) => {
if (op.direction === 'down' && op.result instanceof Error) {
trpcLogger.error(op.result);
trpcLogger.error(
op.result.cause?.cause,
'Aggregated trpc error cause',
);
}
},
enabled: (op) =>
process.env.NODE_ENV === 'development' ||
(op.direction === 'down' && op.result instanceof Error),
}),
loggerLink({
logger: (op) => {
if (op.direction === 'down' && op.result instanceof Error) {
trpcLogger.error(op.result);
trpcLogger.error(
op.result.cause?.cause,
'Aggregated trpc error cause',
);
}
},
enabled: (op) =>
process.env.NODE_ENV === 'development' ||
(op.direction === 'down' && op.result instanceof Error),
}),
3 replies
TtRPC
Created by GamerZero on 9/12/2023 in #❓-help
Cannot set headers in procedures with fetch adapter
@GamerZero did you find anything related to your issue?
6 replies
TtRPC
Created by joe_and_duke on 5/15/2023 in #❓-help
tRPC onError
OnError handler should be setup with your Fastify adapter for tRPC. https://trpc.io/docs/server/adapters/fastify#create-fastify-server
...

server.register(fastifyTRPCPlugin, {
prefix: '/trpc',
trpcOptions: {
router: appRouter,
createContext.
onError <------ HERE
},
});

...
...

server.register(fastifyTRPCPlugin, {
prefix: '/trpc',
trpcOptions: {
router: appRouter,
createContext.
onError <------ HERE
},
});

...
4 replies
TtRPC
Created by Mugetsu on 5/11/2023 in #❓-help
Stack trace in Client?
I've checked and NODE_ENV is production. I've also double checked this with the https://github.com/t3-oss/create-t3-app and trpc integration and its the same. The stack is displayed with loggerLink although I believe that this stack trace is related to client stack and should not be a big concern ???
6 replies
TtRPC
Created by Mugetsu on 5/11/2023 in #❓-help
Sequential batch mutation
Yeah doing this on backend is giving me a headache coz of external API error responses. I managed to do the queue with mutateAsyc calls tho I lose batching but thats not a big deal and it works
4 replies
TtRPC
Created by Mugetsu on 5/11/2023 in #❓-help
Stack trace in Client?
I will double check on prod. But looking at this locally and playing with isDev for initTRPC it doesn't seem to work. On the other siide - Does LoggerLink is being affected by the initTRPC isDev option?
6 replies
TtRPC
Created by Mugetsu on 5/11/2023 in #❓-help
Stack trace in Client?
6 replies
TtRPC
Created by ippo on 4/29/2023 in #❓-help
express-session for tRPC
You need an adapter with next-auth. I see u use redis with express. Then either use up-stash adapter for redis or you need to roll out your own adapter for redis. There is custom adapter for redis on next-auth issues or discussions as I was in need for one too. You have to look for it https://next-auth.js.org/adapters https://authjs.dev/reference/adapter/upstash-redis https://authjs.dev/guides/adapters/using-a-database-adapter https://authjs.dev/concepts/faq#databases https://authjs.dev/reference/adapters
9 replies
TtRPC
Created by ippo on 4/29/2023 in #❓-help
express-session for tRPC
You can use express session as normal with trpc No magic Here. You dont need anything specilal just for trpc. Trpc is based on the req/res from express so you have access to the req.session within trpc routes.
9 replies
TtRPC
Created by Mugetsu on 4/3/2023 in #❓-help
'req' of undefined in onError of express middleware
Yeah it will be hard to reproduce. No matter how hard I try I can't reproduce it locally. Happening only on Prod. I will try add a bit more logging maybe that will help me track down the problem.
15 replies
TtRPC
Created by Mugetsu on 4/3/2023 in #❓-help
'req' of undefined in onError of express middleware
const t = initTRPC
.context<typeof createTRPCContext>()
.meta<MetaOptions>()
.create({
transformer: superjson,
errorFormatter({ shape, ctx }) {
const { data, ...rest } = shape

return {
...rest,
data: {
...data,
traceId: ctx?.req?.traceId,
schemaId: ctx?.req?.schemaId,
},
}
},
defaultMeta: { allowedRoles: [] },
})

export const createTRPCRouter = t.router

const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
if (!ctx.req?.authorisation?.authorised) {
cleanAuthorisation(ctx.req)

throw new TRPCError({
code: 'UNAUTHORIZED',
message: 'User not authorised',
})
}

return next({
ctx: {
req: ctx.req,
res: ctx.res,
},
})
})

const enforceUserRoles = enforceUserIsAuthed.unstable_pipe(
({ ctx, meta, next }) => {
const currentRoles = ctx.req?.authorisation?.userSecurityGroups ?? []
const allowedRoles = meta?.allowedRoles ?? []

if (!currentRoles.length) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'User roles are missing',
})
}

if (
allowedRoles.length &&
!allowedRoles.some((role) => currentRoles.includes(role))
) {
throw new TRPCError({
code: 'FORBIDDEN',
message: 'User role not allowed',
})
}

return next({ ctx })
},
)

const enforceValidSchema = enforceUserRoles.unstable_pipe(({ ctx, next }) => {
const { schemaId } = ctx.req

if (schemaId && !Object.values(SchemaType).includes(schemaId)) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: `SchemaId not supported: (${schemaId})`,
})
}

return next({ ctx })
})

export const publicProcedure = t.procedure
export const procedure = t.procedure.use(enforceValidSchema)
const t = initTRPC
.context<typeof createTRPCContext>()
.meta<MetaOptions>()
.create({
transformer: superjson,
errorFormatter({ shape, ctx }) {
const { data, ...rest } = shape

return {
...rest,
data: {
...data,
traceId: ctx?.req?.traceId,
schemaId: ctx?.req?.schemaId,
},
}
},
defaultMeta: { allowedRoles: [] },
})

export const createTRPCRouter = t.router

const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
if (!ctx.req?.authorisation?.authorised) {
cleanAuthorisation(ctx.req)

throw new TRPCError({
code: 'UNAUTHORIZED',
message: 'User not authorised',
})
}

return next({
ctx: {
req: ctx.req,
res: ctx.res,
},
})
})

const enforceUserRoles = enforceUserIsAuthed.unstable_pipe(
({ ctx, meta, next }) => {
const currentRoles = ctx.req?.authorisation?.userSecurityGroups ?? []
const allowedRoles = meta?.allowedRoles ?? []

if (!currentRoles.length) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'User roles are missing',
})
}

if (
allowedRoles.length &&
!allowedRoles.some((role) => currentRoles.includes(role))
) {
throw new TRPCError({
code: 'FORBIDDEN',
message: 'User role not allowed',
})
}

return next({ ctx })
},
)

const enforceValidSchema = enforceUserRoles.unstable_pipe(({ ctx, next }) => {
const { schemaId } = ctx.req

if (schemaId && !Object.values(SchemaType).includes(schemaId)) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: `SchemaId not supported: (${schemaId})`,
})
}

return next({ ctx })
})

export const publicProcedure = t.procedure
export const procedure = t.procedure.use(enforceValidSchema)
15 replies
TtRPC
Created by Mugetsu on 4/3/2023 in #❓-help
'req' of undefined in onError of express middleware
import { TRPCError, initTRPC } from '@trpc/server'
import superjson from 'superjson'
import * as trpcExpress from '@trpc/server/adapters/express'
import express from 'express'

import { cleanAuthorisation } from '../middleware/auth-middleware'
import {
SchemaType,
UserRoles,
} from '../../universal/components/utils/constants'

type CreateContextOptions = {
req: express.Request
res: express.Response
currentSchema: any
}

type MetaOptions = {
allowedRoles: UserRoles[]
}

export const createInnerTRPCContext = async (opts: CreateContextOptions) => ({
req: opts.req,
res: opts.res,
currentSchema: opts.currentSchema,
})

const getCurrentSchema = (req: express.Request) => {
const { schemaId, locationSchemas } = req

return (
locationSchemas.find(({ id }) => id === schemaId) ||
locationSchemas.find(({ canWrite }) => canWrite) ||
locationSchemas[0]
)
}

export const createTRPCContext = async (
opts: trpcExpress.CreateExpressContextOptions,
) => {
const { req, res } = opts
const currentSchema = getCurrentSchema(req)

return createInnerTRPCContext({
req,
res,
currentSchema,
})
}
import { TRPCError, initTRPC } from '@trpc/server'
import superjson from 'superjson'
import * as trpcExpress from '@trpc/server/adapters/express'
import express from 'express'

import { cleanAuthorisation } from '../middleware/auth-middleware'
import {
SchemaType,
UserRoles,
} from '../../universal/components/utils/constants'

type CreateContextOptions = {
req: express.Request
res: express.Response
currentSchema: any
}

type MetaOptions = {
allowedRoles: UserRoles[]
}

export const createInnerTRPCContext = async (opts: CreateContextOptions) => ({
req: opts.req,
res: opts.res,
currentSchema: opts.currentSchema,
})

const getCurrentSchema = (req: express.Request) => {
const { schemaId, locationSchemas } = req

return (
locationSchemas.find(({ id }) => id === schemaId) ||
locationSchemas.find(({ canWrite }) => canWrite) ||
locationSchemas[0]
)
}

export const createTRPCContext = async (
opts: trpcExpress.CreateExpressContextOptions,
) => {
const { req, res } = opts
const currentSchema = getCurrentSchema(req)

return createInnerTRPCContext({
req,
res,
currentSchema,
})
}
15 replies