Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass in contract information within implementation function #298

Open
jvcmanke opened this issue Jul 5, 2023 · 5 comments
Open

Pass in contract information within implementation function #298

jvcmanke opened this issue Jul 5, 2023 · 5 comments
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@jvcmanke
Copy link

jvcmanke commented Jul 5, 2023

I think it would be very useful to be able to access the contract metadata and possibly other contract information directly inside the implementation function without manually pathing from the contract.

As an example using the @ts-rest/next package, but it would be analogous in the other ones.
Currently I can do this:

export const postsRouter = createNextRoute(apiContract.posts, {
  createPost: async (args) => {
    const metadata = apiContract.posts.createPost.metadata

    //...do stuff
  }
})

Which works fine, but would be much more intuitive and expandable (IMO) to be able access contract information like this:

export const postsRouter = createNextRoute(apiContract.posts, {
  createPost: async (args) => {
    const metadata = args.metadata

    //...do stuff
  }
})

or

export const postsRouter = createNextRoute(apiContract.posts, {
  createPost: async (args, route) => {
    const metadata = route.metadata

    //...do stuff
  }
})

or some similar way.

This is not really issue or anything, just convenience, but it would be very useful for creating some standard (custom) functionality, like middleware, based on metadata or other contract information, like this for example:

export function checkScopes<
  Args extends { headers: IncomingHttpHeaders, metadata?: Record<string, unknown> },
  Return
>(route: (args: Args) => Promise<Return>) {
  return async (args: Args) => {
    const metadata = metadataSchema.parse(args.metadata);

    const authResponse = authenticate(args.headers, metadata.scopes);
    if (authResponse.type === "error") {
      return authResponse.error;
    }

    return await route(args);
  };
}

and then use it like this, basically in any route:

export const postsRouter = createNextRoute(apiContract.posts, {
  createPost: checkScopes(async (args) => {
    //...do stuff
  })
})
@Gabrola Gabrola added enhancement New feature or request good first issue Good for newcomers labels Jul 6, 2023
@jvcmanke
Copy link
Author

jvcmanke commented Jul 6, 2023

@Gabrola I can submit a PR if I have the time, in particular for the @ts-rest/next side of things, I'm not that familiar with the other integrations.

Any preference on how would you pass in the infromation?
Within the args or as a separate parameter of the implementation function?

I've messed around a bit with the express integration, and I think it already has something like this within the middlware, which put this kind of information in the request parameter, but I'm not a big fan of that.

Just let me know and I'll get the PR ready.

@Gabrola
Copy link
Member

Gabrola commented Jul 6, 2023

Yeah feel free to to submit a PR, it's fine if it's just for the nextjs lib. The approach taken in the express lib is to able to have access to the endpoint schema in middleware since they only take the req, res, next params, so it must be passed through req. In your case, I think it's best to just add it to the args object.

@oliverbutler
Copy link
Collaborator

This is a nice enchantment, anybody looking into it? I could investigate the nest side.

@jvcmanke
Copy link
Author

@oliverbutler Sadly, I didn't have enough time to start working on anything yet, even though I think it would be a really small change.

I was planning on working strictly on the nextjs lib so we probably wouldn't have much conflict anyway. 😄

@dmstoykov
Copy link
Contributor

@Gabrola I just created a PR for the fastify side. #591

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

4 participants