Skip to content

Async scalars with access to context and info? #2663

Closed
@borekb

Description

@borekb

In our resolver map, we have two quite different things:

  1. Resolvers, which are functions called by graphql-js with useful objects like info or context, and they are usually async.
  2. Custom scalars, which are objects, don't have access to info or context (or anything request-related) and their functions like serialize aren't async.

I wonder if scalars could be more resolver-like?!

Concrete example

Our use case is price rounding. In our case, GraphQL server code doesn't know how to round – it needs to ask a backend API for rounding rules – but it is GraphQL code's responsibility to ensure that values are rounded.

Most prices in our schema are represented by a Money type that looks like this:

type Money {
  amount: MonetaryAmount! # custom scalar
  currencyCode: String!
}

We can then do something like this, which works well:

const resolvers = {
  Query: {
    Money: {
      amount: async (money, _, { dataSources: { backendApi } }) =>
        round(money.amount, money.currencyCode, backendApi),
    },
  }
};

async function round(amount, currency, backendApi) {
  const roundingInfo = await backendApi.getRoundingInfo(...);
  // etc.
}

Some parts of our schema, however, use the scalar directly, skipping the Money type. For example:

type GoogleEcommerceDataLayerActionField {
  id: String!
  revenue: MonetaryAmount
  tax: MonetaryAmount
}

I'd love to be able to write resolver-like code for it, like this:

// pseudocode!

const resolvers = {
  __customScalars: {
    MonetaryAmount: async (value, { config, dataSources: { backendApi } }) =>
      round(value, config.currencyCode, backendApi),
  },
};

Currently, we need to solve this on the specific field level, for example, if there's a field like:

type GoogleEcommercePurchaseDataLayer {
  actionField: GoogleEcommerceDataLayerActionField
}

we can hook into actionField and process the rounding there. But it would be safer and easier if we could solve it at the type level.

What do you think? Has this been considered before? I didn't find much but maybe my search skills have failed me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions