Skip to content
This repository has been archived by the owner on Dec 19, 2022. It is now read-only.

Chapter 2) The Resolver API + middlewares #25

Closed
KATT opened this issue Feb 1, 2022 · 1 comment · Fixed by #33
Closed

Chapter 2) The Resolver API + middlewares #25

KATT opened this issue Feb 1, 2022 · 1 comment · Fixed by #33
Assignees
Labels
❕ RFC Request for comments - please comment!

Comments

@KATT
Copy link
Member

KATT commented Feb 1, 2022

The Resolver API and middlewares

Problems with the current implementation

  • Middlewares are hard to reuse
  • I find them quite fiddly to write - counting brackets etc.

Suggestion A) Pipes

Standalone route

// single resolver
const myProcedure = trpc.resolver(
  trpc.zod( z.object({ id: z.string }) ),
  ({ ctx, input }) => {
    return 'my data goes here'
  }
)```

### In a router
```ts
export const appRouter = trpc.router({
  queries: {
    // procedure with input validation called `greeting`
    greeting: trpc.resolver(
      trpc.zod(
        z.object({
          hello: z.string(),
        }),
      ),
      (params) => {
        return {
          data: {
            greeting: 'hello ' + params.ctx.user?.id ?? params.input.hello,
          },
        };
      },
    ),
  }
)

Inferring errors

const isAuthed = trpc.newContext((params) => {
  if (!params.ctx.user) {
    return {
      error: {
        code: 'UNAUTHORIZED',
      },
    };
  }
  return {
    ctx: {
      ...params.ctx,
      user: params.ctx.user,
    },
  };
});

Reusable middleware

// with re-usable middleware
const isAuthed = trpc.newContext((params) => {
  if (!params.ctx.user) {
    return {
      error: {
        code: 'UNAUTHORIZED',
      },
    };
  }
  return {
    ctx: {
      ...params.ctx,
      user: params.ctx.user,
    },
  };
});

export const appRouter = trpc.router({
  queries: {
    // procedure with input validation called `greeting`
    postCreate: trpc.resolver(
       isAuthed,
      (params) => {
        return {
           // ...
        };
      },
    ),
  }
)

Suggestion B) Closures & Chains

Standalone route

// single resolver
const myProcedure = trpc.route(route => route
  .input(z.object({hello: z.string}))
  .resolve(req => {
    return req.input.hello;
  })
);

In a router

export const appRouter = trpc.router({
  queries: {
    // procedure with input validation called `greeting`
    greeting: route => route
      .input(
        z.object({
          hello: z.string(),
        })
      )
      .resolve(req => {
        return {
          data: {
            greeting: 'hello ' + params.ctx.user?.id ?? params.input.hello,
          },
        };
      }),
  },
});

Reusable middleware

// with re-usable middleware
const isAuthed = trpc.middleware(params => {
  if (!params.ctx.user) {
    return trpc.error({
        code: 'UNAUTHORIZED',
    });
  }
  return {
    ctx: {
      ...params.ctx,
      user: params.ctx.user,
    },
  };
});


export const appRouter = trpc.router({
  queries: {
    // procedure with input validation called `greeting`
    postCreate: route => route
      .use(isAuthed)
      .resolve(params => {
        return {
          // ...
        };
      }),
  },
});
@KATT KATT added the ❕ RFC Request for comments - please comment! label Feb 1, 2022
@KATT KATT pinned this issue Feb 1, 2022
@KATT
Copy link
Member Author

KATT commented Feb 1, 2022

@colinhacks on Option B

If you can show to me that two independent trpc.middleware()s can mutate the context in different ways without the second overriding the first, I might be with you on this

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
❕ RFC Request for comments - please comment!
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

1 participant