Code Monkey home page Code Monkey logo

graphql-kit's People

Contributors

abidon avatar alexsteinerde avatar cameroncooke avatar jaredh159 avatar maxdesiatov avatar maximkrouk avatar portellaa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql-kit's Issues

Selection Set from the Resolver

Hi,
I would need to get access to the Selection Set from the Resolver.
Do you think it is hard to implement ?
The selectionSet is a flat list of the fields that the user requested, for example,

family {
   name
   child {
     name
  }
}

Would give the selectionSet ["name", "child/name"]

Thank you

Error on graphql rout

I started getting an error, before everything was working

{
  "error": true,
  "reason": "The operation couldn’t be completed. (GraphQLKit.GraphQLResolveError error 0.)"
}

[ INFO ] GET /graphql [request-id: F648C1E3-5FB5-4AAD-B864-955003387E2C]
[ WARNING ] The operation couldn’t be completed. (GraphQLKit.GraphQLResolveError error 0.) [request-id: F648C1E3-5FB5-4AAD-B864-955003387E2C]

Get pivots

Hi, can you tell me how to get pivot?
I tried this but it gives the error "Unknown kind of type: TodoTag"

Type(Todo.self) {
    Field("id", at: \.id)
    Field("title", at: \.title)
    Field("user", with: \.$user)
    Field("tags", with: \.$tags.$pivots)
}

subscription support

It looks like this library in its current form doesn't support GraphQL subscriptions. Is that correct? I'm wanting to implement some new websocket-based functionality in one of my vapor/graphql apps, and I'm trying to get a feel for how much work it would be to keep it purely graphql, or whether I should just build this feature outside of graphql for now. I know the Graphiti library has some support for subscriptions, by subclassing EventStream from the core GraphQL library.

have you thought about this at all, or do you have any plans on implementing this? or thoughts on how it would be accomplished? if the path forward seemed not to crazy, i thought maybe i could possibly try an initial implementation, if it was something you were interested in adding support for, or could possibly give me a pointer or two how you'd like to see it implemented in the context of this library.

[Help] How to enrich a response using GraphQL, Vapor and Graphiti

I'm building a GraphQL server application in Swift using GraphQL-Kit, Graphiti, Vapor, and Fluent with an SQL database.

Below is a basic example to attempt to illustrate my problem. I have a User model that maps to a users table, and a Purchase model that maps to a purchases table.

I have a resolver that exposes a function called getUsers. For brevity I've not included the schema or setup code, for this example assume that the schema replicates roughly the same structure and links to the resolver.

What I would like to do is enrich the response that getUsers function returns. I have data that comes from another source that I would like to add to the Purchase response, my idea was to just create a normal property on the Purchase model called notes and then in the resolver just use map to access the instance of each purchase model and assign the values into the notes field, I assumed this would work as the models are classes.

final class User: Model, Codable {
    static let schema = "users"

    @ID(key: .id)
    var id: UUID?

    @Children(for: \.$user)
    var purchases: [Purchase]

    init() {}

    init(id: UUID? = nil) {
        self.id = id
    }
}

final class Purchase: Model, Codable {
    static let schema = "purchases"

    @ID(key: .id)
    var id: UUID?

    @Field(key: "name")
    var name: String

    @Field(key: "price")
    var price: Double

    @Parent(key: "user_id")
    var user: User

    var notes: String?

    init() {}

    init(id: UUID? = nil, name: String, price: Double, userId: UUID, notes: String?) {
        self.id = id
        self.name = name
        self.price = price
        self.$user.id = userId
        self.notes = notes
    }
}

func getUser(
    request: Request,
    arguments: GetUserArguments
) throws -> EventLoopFuture<User> {
    User.find(arguments.id, on: request.db)
        .unwrap(or: Abort(.notFound))
        .map {
            $0.purchases.forEach {
                $0.notes = "Some value that comes from somewhere else that I can compute at resolution time"
            }
            return $0
        }
}

When I run my server and perform a query:

query {
  users(id: $userId) {
    userId
    purchases {
        name
        price
        notes
    }
}

The notes field in the graph comes back with a null.

I'm pretty sure this is just a lack of understanding of how this all works but at the moment I can't for the life of me work out how to enrich the response of a query with data that isn't coming from the db.

For context, I followed the setup and examples in this tutorial series: https://www.kodeco.com/21148796-graphql-tutorial-for-server-side-swift-with-vapor-getting-started#toc-anchor-001

Cross posted on StackOverflow: https://stackoverflow.com/questions/77812573/how-to-enrich-a-response-using-graphql-vapor-and-graphiti

querying @OptionalParent relation

are you sick of me yet? 😄

OK, so now I'm struggling with a Model that has an @OptionalParent. I spent a while trying to add my own extension to Graphiti.Field to support the OptionalParentProperty property wrapper, akin to what you did with the Siblings wrapper. I figured I'd PR it if I could get it to work.

But... I seem to only sorta be able to get it working. I have a Schema type definition that looks sort of like this:

Type("MyModel", MyModel.self) {
  // [...]
  Field("category", with \.$category) // 👋  <-- here's the @OptionalParent prop
}

The schema won't compile, none of the initializers match an OptionalParent. Below is my attempt at adding another initializer to handle the relationship:

extension Graphiti.Field where Arguments == NoArguments, Context == Request, ObjectType: Model {
  public convenience init<ParentType: Model>(
    _ name: FieldKey,
    with keyPath: KeyPath<ObjectType, OptionalParentProperty<ObjectType, ParentType>>
  ) where FieldType == TypeReference<ParentType?> {
    self.init(
      name.description,
      at: {
        (type) -> (Request, NoArguments, EventLoopGroup) throws -> EventLoopFuture<ParentType?> in
        return { (context: Request, arguments: NoArguments, eventLoop: EventLoopGroup) in
          return type[keyPath: keyPath].get(on: context.db)
        }
      }, as: TypeReference<ParentType?>.self)
  }
}

The new initializer allows my Schema to compile. But then, trying to send a query, I get Cannot complete value of unexpected type "CategoryOptional". Which makes me wonder if I'm just messing up my Schema and resolvers somehow, and if maybe the extension is in fact correct.

The other thing I tried is removing the ? on the fifth line of the extension and the third-to-last line (both places where it says TypeReference<ParentType?>. This also allows the schema to compile, but upon querying I get Cannot return null for non-nullable field MyModel.category.

Any possibility you are able to see at a glance what I've done wrong? Thanks in advance, really appreciate it!

Enum in GraphQL schema

Hi, I'm trying to use enum in my GraphQL schema. But I get the following error.
Снимок экрана 2023-08-02 в 11 27 21
I did everything just like it says in README.md
My code:

import Fluent

enum FamilyStatus: String, Codable, CaseIterable {
    case Free
    case inRelationships = "In Relationships"
    case inFreeRelationships = "In Free Relationships"
    case allAreComplicated = "All Are Complicated"
    
    static func migrate(_ db: Database) async throws {
        _ = try await db.enum("family_status")
            .case(FamilyStatus.Free.rawValue)
            .case("inRelationships")
            .case("inFreeRelationships")
            .case("allAreComplicated")
            .create()
    }
}

Enum(FamilyStatus.self)

What is my mistake and how do I fix it?

Registered GraphQL Schema ignores authenticators

The following code (using a simple UserAuthenticator example from Vapor's Authentication Docs) does not respect the authenticator:

routes.grouped(UserAuthenticator()).register(graphQLSchema: schema, withResolver: resolver)

I believe the same would hold true for any sort of Vapor middleware, but have only tested the authenticator.

how to use @Timestamp model properties in graphql types

Can you provide any input on how to expose @Timestamp model properties like createdAt, updatedAt, on graphql types? I tried just adding Scalar(Date.self) to my Schema, but I end up just getting numbers (like "createdAt": 648570561.42727697) in the json output.

After digging around a bit, I think I might need to somehow register a DateScalar with a Graphiti.DateFormatter, but I'm struggling to figure out where or how.

I debated opening this on the Swift Graphiti repo, but since it tied in directly with Vapor/Fluent, I thought maybe it might be appropriate here. But feel free to close if you think I should raise it over there instead.

Thanks again!

getting "Cannot complete value of unexpected type X" error with children

I'm having trouble resolving the children of a model. I definitely might be doing something super dumb though. What's odd is, in my other vapor/graphql app (yes, I have two now...) I haven't hit this problem, but I use parent/children a decent bit. Anyway, I have models like this:

final class Order: Model, Content {
  static let schema = "orders"

  @ID(key: .id)
  var id: UUID?

  @Field(key: "email")
  var email: String

  @Children(for: \OrderItem.$order)
  var items: [OrderItem]

  init() {}
}

final class OrderItem: Model, Content {
  static let schema = "order_items"

  @ID(key: .id)
  var id: UUID?

  @Parent(key: "order_id")
  var order: Order

  @Field(key: "title")
  var title: String

  init() {}
}

The schema looks like this:

let AppSchema = try! Graphiti.Schema<Resolver, Request> {
  Scalar(UUID.self)

  Type(Order.self) {
    Field("id", at: \.id)
    Field("email", at: \.email)
    Field("items", with: \.$items)
  }

  Type(OrderItem.self) {
    Field("title", at: \.title)
    Field("order", with: \.$order)
  }

  Query {
    Field("getOrder", at: Resolver.getOrder) {
      Argument("id", at: \.id)
    }
  }
}

And the resolver looks like this:

final class Resolver {
  struct IdentifyEntityArgs: Codable {
    let id: UUID
  }

  func getOrder(
    request: Request,
    args: IdentifyEntityArgs
  ) throws -> Future<Order> {
    return Order.query(on: request.db)
      .with(\.$items)
      .filter(\.$id == args.id)
      .first()
      .unwrap(or: Abort(.notFound))
  }
}

But when I send a graphql query like so:

query {
  order: getOrder(id: "FBF9C172-E57E-49A8-8806-85F6C923E55A") {
    id
    items {
      title # <-- trying to get one of the children causes the error, without this, it works
    }
  }
}

I get the error Cannot complete value of unexpected type \"OrderItem\".

I feel like I'm missing something stupid. I think I'm sort of following your examples for users/todos in the readme.

If the code above isn't clear enough, I've created a super minimal reproduction repository using an in-memory sql-lite db. If you want to take a look, you can just clone the repo, then run swift run and (in another terminal tab) try bash ./test-error.sh to send the query shown above.

Date error

When trying to send a date as an argument, I get the error "The data couldn't be read because it isn't in the correct format." At the same time, the date from the database is decoded normally. If Scalar(Date.self) is changed to DateScalar(formatter: ISO8601DateFormatter()), the error becomes: "Argument \"date\" got invalid value 670427457.\nExpected type \"Date\", found 670427457.". I send the date in ISO 8601 format "2022-03-31T13:50:57Z"

Overriding response status code

Hi @alexsteinerde,
How can I return response code other that 200 for specific scenarios (unauthorized etc)?
I've tried adding a custom error middleware but because RoutesBuilder status is always ok I it never uses it.

Can't add parent and child fields to schema due to circular dependency

Given this slightly reworked example:

final class User: Model {
    ...
    
    @Children(for: \.$user)
    var todos: [Todo]
    
    ...
}

final class Todo: Model {
    ...
    
    @Parent(key: "user_id")
    var user: User
    
    ...
}
// Schema types
Type(Todo.self) {
    Field("user", with: \.$user)
}

Type(User.self) {
    Field("todos", with: \.$todos)
}

I get the following error:

Fatal error: 'try!' expression unexpectedly raised an error: Type "User" was referenced but not defined.

This seems to be because User needs to be defined in the schema before Todo for Todo's @Parent relation, but Todo also needs to be defined before User for User's @Children relation. Essentially we have a circular dependency issue.

support for @Sibling many-to-many relationships?

Hi there. Thanks for this amazing library and all the work you put into it! It's been fantastic to use so far! 🙏

I'm having trouble modeling a many-to-many pivot-table based sibling relationship with vapor+graphql-kit. I'm a bit at a loss of even how to approach the problem. I'm wondering if it's something that is not supported yet, or if possibly I just don't know how to set up the schema and resolvers to make it work.

I see that you extended Graphiti's Field class here to add keypath-based resolution specifically for children and parent relationships. I'm wondering if something similar would need to be done for sibling relationships. Or is it not possible without some deeper work in the library? Or is it possible by dropping down and working at the Graphiti layer itself somehow?

Have you written an example with some code somewhere of how to do this? (I ask because I relied heavily on your excellent blog posts with the Todo examples when getting up and running).

Any info or pointers would be greatly appreciated. Thanks again!

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.