In this guide, you will learn how to create clients and how to use them in your implementations.

Before you start

So, what to do with clients? You create them, extending some base code. IO Node Services already ship with some default clients, mostly to our internal services, that you may use right away. Check them here.

Before talking about how we create clients, let's recap how we use them. If you are familiar with IO services, you already know that your implementation exports functions that receive a context object. These functions can be a resolver function to a GraphQL field, a middleware to an HTTP server or an event handler, and, in all of them, you receive a ctx(or however you wanna call it) object of type Context, and it is inside of ctx.clients where you'll find each client.

export const authorize = async (ctx: Context) {
    const { clients: { licenseManager } } = ctx
    ...
    const data = await licenseManager.canAccessResource(/*...*/)
}

Creating clients

  1. The @vtex/api SDK provides a structured way to create clients, and the first thing to do is identify the type of communication you want to implement. As of now, we support these out of the box:
TypeUse case
AppClientCommunication with other IO Services via plain-old HTTP calls
AppGraphQLClientCommunication with other IO GraphQL services
ExternalClientCommunication with external API's
JanusClientCommunication with VTEX Core Commerce API's through Janus Router
InfraClientCommunication with VTEX IO Infra services

When using clients, do not forget to add the appropriate policies on your manifest.json. Incorrect policies may result in request blocking.

  1. After finding the base client you are looking for, you need to implement a Typescript class that extends the type of this base client. You may place them wherever you want, but we advise you to put them on node/clients.

Let's take a look on the anatomy of an ExternalClient to the Github API:

node/clients/github.ts
Github API Client exampleGithub API Client example

Reference
1 - Look, it's one of the types from the table above.

2 - Take a look here to check everything you can configure.

3 - Read more about app's pricing here.

4 - There are a lot of other methods available, you can check them on [HttpClient].(https://github.com/vtex/node-vtex-api/blob/master/src/HttpClient/HttpClient.ts)

You're free to add data handling logic inside your client's methods (i.e: mapping fields, or filtering data), but be careful to not lose track of the client's responsabilities.

Using clients on implementations

After you've learned how to create great clients, it's time to ship them, so you may use it on your implementations. It's easy as well!

If you want to jump to an example, check how the StatusClient is setup on service-example.

Let's suppose you've created the Github client we've described above!

  1. Make sure you've exported the client from its module. (Either default or named export)
  2. Create a node/clients/index.ts file.
  3. Paste the following snippet on it. (If you've used named export on Step 2, change the import clause)
import { IOClients } from '@vtex/api'
import GithubClient from './github.ts'

export class Clients extends IOClients {
  public get status() {
    return this.getOrSet('github', GithubClient)
  }
}
  1. Now, import the Clients class on node/index.ts (the service entrypoint).
  2. Create or edit a clients object of type ClientsConfig<Clients> (from @vtex/api) like so:
    const clients: ClientsConfig<Clients> = {
      implementation: Clients,
      options: {
        default: {
          retries: 2,
          timeout: 2000,
        },
      },
    }
  1. Use the clients variable on the Service exported:
export default new Service<Clients, State>({
  clients,
  routes: {
    ...
  },
})
  1. Optional: Place this type declaration on the same node/index.ts file. It helps you type the implementation functions.
declare global {
  type Context = ServiceContext<Clients, State>
}
  1. That's it :sparkles:! Now you can, on your functions, access your client from the ctx.
export const authorize = async (ctx: Context) {
    const { clients: { github } } = ctx
    ...
    const data = await github.getUser(/*...*/)
}

Want to dive deeper?

If you didn't find what you were looking for here, try learning by example. We are already doing some advanced thing on our default clients, like file upload, use of disk cache and more:


Did this page help you?