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

Using resolve to modify field #125

Closed
avocadowastaken opened this issue Apr 26, 2019 · 2 comments
Closed

Using resolve to modify field #125

avocadowastaken opened this issue Apr 26, 2019 · 2 comments

Comments

@avocadowastaken
Copy link

avocadowastaken commented Apr 26, 2019

Sorry for bad issue title, not sure how to properly name it.

While rewriting app to nexus I found problem with resolvers that modify. For example:

export const ProductType = objectType({
  name: "Product",
  definition(type) {
    type.id("id");
    type.string("title");
    type.float("price");
  }
});

Both title and price stored in database, but during request I want to modify them based on request details:

export const ProductType = objectType({
  name: "Product",
  definition(type) {
    type.id("id");
    type.string("title", {
      async resolve({ id, title }, _, { language, loaders }) {
        const i18n = await loaders.productI18n.load({
          language,
          productId: id
        });

        return !i18n ? title : i18n.title;
      }
    });

    type.float("price", {
      async resolve({ price }, _, { country, services }) {
        return services.price.convertPrice(price, country);
      }
    });
  }
});

JavaScript code works, because these fields exist in root, but TypeScript bugs me because NexusGenRootTypes[] does not have price and title fields.


I see two ways to resolve this:

  1. Add extra "resolver" named transform, which would work like authorize resolver, but should be called last (authorize -> resolve -> transform)
  2. Add boolean key to notify transformer to include current property to NexusGenRootTypes. (e.g: belongsToRoot: true).

Related to #36.

@Nayni
Copy link
Contributor

Nayni commented Apr 30, 2019

The problem here is how @tgriesser already explained in the related issue, which comes down to the chicken or the egg problem. You define a field on the type that is computed, but the value you compute from is actually be supposed to be on the root object already. I think the only way(and cleanest way) to do this is to let Nexus know your underlying data models which if you're working with TypeScript are probably already defined with an interface/type/class. You can do this by adding sources to the typegenAutoConfig option of makeSchema.

The star-wars example shows how to do this:

export const schema = makeSchema({
  types: allTypes,
  outputs: {
    schema: path.join(__dirname, "../star-wars-schema.graphql"),
    typegen: path.join(__dirname, "./star-wars-typegen.ts"),
  },
  typegenAutoConfig: {
    sources: [
      {
        source: path.join(__dirname, "./types/backingTypes.ts"),
        alias: "swapi",
      },
    ],
    contextType: "swapi.ContextType",
  },
});

The docs (https://nexus.js.org/docs/type-generation) also have a section about this although I think it should be shown more in depth of what the power of this feature is.

@avocadowastaken
Copy link
Author

The problem here is how @tgriesser already explained in the related issue, which comes down to the chicken or the egg problem.

Oh, I guess missed it.

You can do this by adding sources to the typegenAutoConfig option of makeSchema.

@Nayni thank you for detailed explanation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants