Coder Social home page Coder Social logo

Comments (8)

jacobh avatar jacobh commented on August 15, 2024 1

Just like to add my 👍 on specifying the context type for objects. I'm defining a bunch of Result types that optionally contain an object and a human-friendly error message. The object requires context, so I can't use the GraphQLObject derive.

At the moment I've got an example that looks like this

#[derive(GraphQLInputObject)]
pub struct ClaimTicketInput {
    queue_id: Uuid,
    session_id: Uuid,
    ticket_number: String,
}

pub struct ClaimTicketResult {
    queue_entry: Option<ScheduledQueueEntry>,
    error_message: Option<String>,
}

graphql_object!(ClaimTicketResult: Context |&self| {
    field queue_entry() -> Option<&ScheduledQueueEntry> {
        self.queue_entry.as_ref()
    }
    field error_message() -> Option<&String> {
        self.error_message.as_ref()
    }
});

pub struct Mutations {}
graphql_object!(Mutations: Context |&self| {
    ...
    field claim_ticket(
        &executor,
        input: ClaimTicketInput,
    ) -> FieldResult<ClaimTicketResult> {
        ...
    }
});

This seems like a great spot to be able to use the derive macro, so I'd be able to do

#[derive(GraphQLInputObject)]
pub struct ClaimTicketInput {
    queue_id: Uuid,
    session_id: Uuid,
    ticket_number: String,
}

#[derive(GraphQLObject)]
pub struct ClaimTicketResult {
    queue_entry: Option<ScheduledQueueEntry>,
    error_message: Option<String>,
}

pub struct Mutations {}
graphql_object!(Mutations: Context |&self| {
    ...
    field claim_ticket(
        &executor,
        input: ClaimTicketInput,
    ) -> FieldResult<ClaimTicketResult> {
        ...
    }
});

FWIW this is the current compiler error

error[E0277]: the trait bound `graphql::context::Context: juniper::FromContext<()>` is not satisfied
  --> src/common/graphql/mutations/scheduled_queue_entry.rs:19:10
   |
19 | #[derive(GraphQLObject)]
   |          ^^^^^^^^^^^^^ the trait `juniper::FromContext<()>` is not implemented for `graphql::context::Context`

from juniper.

srijs avatar srijs commented on August 15, 2024

This looks like it already landed?

from juniper.

theduke avatar theduke commented on August 15, 2024

An initial implementation has landed that allows deriving for objects.

But we were discussing custom resolver functions to be specified for each field.

Typing is in issue there, sadly, so we might just not do it.

from juniper.

theduke avatar theduke commented on August 15, 2024

Just for the record, this is now possible:

#[derive(GraphQLObject)]
struct User {
  pub id: i32,
  pub username: String,
  #[graphql(name="userProfileInfo", description="lala", deprecated="because...")]
  pub info: Option<String>,
}

The open question is: often, you'd like to derive for a struct, but change one or two fields, for example to change the type of a u64 field to f64, because JS and therefore Juniper do not suppoert i/u64.

So it would be nice to do something like this:

#[graphql(resolver="some_resolver_fn")
pub id: u64,

The problem is, the custom derive code does not now anything about the signature of the given function.

There are two points of data that are missing:

  • type of the Context
  • return type of the resolver

So there are two options here:

  • Do not provide this custom resolver option. One could, for example, have a different struct with the right field types and derive for that struct. Then you could implement From to easily convert between your two structs. This requires boilerplate, but does not introduce any 'magic'.

  • Extend the attribute to support specifying the return type and the context.

For example:

#[graphql(resolver="my_resolver_fn<Context=MyContext> -> FieldResult<u64>")]
pub someField: Option<String>,

The downside to this is that it requires duplicating the function signature and could lead to hard to read error messages when the specified types are different from the actual function signature.

Feedback here would be highly welcome! @mhallin @srijs @stankec

from juniper.

mhallin avatar mhallin commented on August 15, 2024

A nitpick: the Context type is scoped for each type, so specifying it per field might lead to confusing errors if you mistype one of them, e.g.

#[derive(GraphQLObject)]
struct Sample {
  #[graphql(resolver="my_resolve_fn<MyContext>")
  pub x: i32,
  #[graphql(resolver="my_other_resolve_fn<MyMisspelledContext>")
  pub y: i32,
}

The obvious (but not ideal) solution is to move it to the type instead, though this creates some extra boilerplate when it's just one field to override:

#[derive(GraphQLObject)]
#[graphql(context=MyContext)]
struct Sample {
  #[graphql(resolver="my_resolve_fn")]
  pub x: i32,
  #[graphql(resolver="my_other_resolve_fn")]
  pub y: i32,
}

Regarding duplication of return types; I seems like it's something we can't get around. I think we want to avoid having a mini-syntax for the resolver field, so maybe something like:

#[graphql(resolver="my_resolve_fn")] // defaults to the struct field type and () context
#[graphql(resolver="my_resolve_fn", type="FieldResult<f64>")] // overrides the field type
#[graphql(resolver="my_resolve_fn", context="MyContext")] // override context (unless we do as written above)

Additionally, if the resolver argument is an expression, you could also write:

struct Sample {
  #[graphql(resolver="|x| x as f64", type="f64")]
  x: i64,
}

Which I don't know is a good or bad thing :)

from juniper.

thedodd avatar thedodd commented on August 15, 2024

Yea, I'm having the same issue that @jacobh mentioned above.

from juniper.

bbqsrc avatar bbqsrc commented on August 15, 2024

Has there been any progress on this issue?

from juniper.

theduke avatar theduke commented on August 15, 2024

Specifying the context in the custom derive is now possible.

#[derive(GraphQLObject)]
#[graphql(Context = MyContext)]
struct S {}

from juniper.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.