question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add a way to access the `ctx` in the `input` parsers

See original GitHub issue

I want to transform a slug or id before passing it to the resolve function. Currently you cannot access the router ctx inside the input function which has the downside that you have to do transformations inside the resolve function (if the transformation requires the ctx object).

For example: You have a user profile page (profile/{userId}) that uses trpc to get the profile data of a user. You pass this userId to trpc and want to convert the userId into a user object by utilizing some kind of UserRepository that is available on your ctx object. The UserRepository is an instance of a service, and cannot be accessed without the ctx object as you do not allow singletons.

By allowing the input to access the ctx we can utilize Zod’s transform to convert a slug or id before it is passed to the resolve function. This way we can keep our resolve functions as clean as possible and keep any sort of input validation & transformation inside our input function.

According to the docs we can currently pass a Zod, Yup or superstruct object as input. I am not aware how this type is checked internally but if they all provide an object instead of a function we could allow a function as input with the ctx as an argument.

The end-result could look like:

.query('profile', {
  input: ({ ctx }) => 
      yup.object({
          user: yup.number().required(),
      })
      .transform((userId) => ctx.userRepository.findById(userId))
      .refine((user) => !!user, {
           message: 'User could not be found.',
       }),
      
  resolve({ input }) {
    return {
      username: input.user.username,
    };
  },
});

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:6
  • Comments:14 (8 by maintainers)

github_iconTop GitHub Comments

5reactions
KATTcommented, Jul 24, 2022

Alternatively, if the input parser is called “late” (i.e. inside any middleware callback), potentially there could just be a recipe involving async_hooks and people could just do […]

It actually is part of the middleware chain, so this could work but seems very hard with the inference of the type being correct.

Bumped into the same use case where I find returning localised validation error from each procedure is much more cleaner. Otherwise, I would have to come up with lots of switch cases in error handling to localise the ZodError which is what I’m currently doing.

Thanks for providing the use-case & does seem very valid.


Unsure what an API would look like to support this. We’ll try to address it somehow within the next month or so.

3reactions
mmkalcommented, Jul 17, 2022

Could this be a rare case where a second arg would be helpful?

const router = t.router({
  hello: t.procedure.input(z.string()).query(() => '...'),
  identicalHello: t.procedure
    .input(rawInput, ({ ctx }) => z.string().parse(rawInput))
    .query(() => '...'),
});

Alternatively, if the input parser is called “late” (i.e. inside any middleware callback), potentially there could just be a recipe involving async_hooks and people could just do

const router = t.router({
  hello: t.procedure.input(z.string()).query(() => '...'),
  identicalHello: t.procedure
    .input(rawInput => {
      const ctx = summonCtxMagicallyFromAsyncLocalStorage()
      return ctx.whatever ? z.string().parse(rawInput) : z.number().parse(rawInput)
    })
    .query(() => '...'),
});
Read more comments on GitHub >

github_iconTop Results From Across the Web

Context
The Ctx struct represents the Context which hold the HTTP request and response. It has methods for the request query string, parameters, body,...
Read more >
antlr - ctx in ANTLR4 javascript visitor
So, in short: this listener accepts the entire parse tree of your input, but only "listens" when we enter the print parser rule....
Read more >
Controller - Egg
Simply speaking, a Controller is used for parsing user's input and send ... ctx.queries object to parse Query String and put duplicated data ......
Read more >
ParserRuleContext (ANTLR 4 Runtime 4.11.1 API)
A rule invocation record for parsing. Contains all of the information about the current rule not stored in the RuleContext. It handles parse...
Read more >
Listeners And Visitors - Strumenta
In fact, traditionally, people have put actions directly into the grammar because it was the easiest way to access the parse tree.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found