Comments (8)
@paulofaria, is this an easy fix? I'd be happy to work on it if you can point me in the right direction.
from graphiti.
Hey, @cshadek. This is indeed a bug. I'll work on it on the next release. I don't have any indication of when that might happen, though. Please send a PR if you want this fixed sooner rather than later.
from graphiti.
I came across this issue myself today.
I dig into the code and I couldn't find a solution without touching the underlying GraphQL package too.
So I created a fork each. The Graphiti fork depends on my GraphQL fork (referenced in the Package.swift
file.
If we want to keep the GraphQL package untouched, I think we need some more heavy refactoring:
In FileProvider.swift
the GraphQLTypeReference
is created with a reflection (Reflection.name(for: type.wrappedType)
), not with the typename itself. But as we pass only the Type.Type
into that function, I don't have an idea to access that alias property.
Any additional insights or better ways are welcome.
from graphiti.
Oof, yeah this is a tough one. @alexsteinerde, you're right - the crux of the issue is TypeProvider.swift L53, where we map a Graphiti TypeReference
to a GraphQL GraphQLTypeReference
using only the name of the type itself (as opposed to the "mapped" name as specified in a type declaration)... This code is executed incrementally as the Graphiti schema is built, so unfortunately we cannot inspect the TypeProvider to find the declared name, because it might not have been declared yet! Ugh.
The GraphQL package does a type-reference reduction operation here after the entire schema has been declared. But by this time, we've long since lost the separation between the Swift name and the declared name.
I see 2 potential approaches:
- Change
Graphiti.Schema
to have its own type-reference resolution process, prior to creatingGraphQLType
objects. - Change
GraphQL.GraphQLTypeReference
to have 2 string fields (maybeswiftName
andgraphQLName
or something), in which either are used to match it up to another type during the GraphQL type reduction process.
from graphiti.
I can confirm that this is also an issue when using Optional types (not only TypeReferences).
For example, the following code fails on the optional LocationObject?
because it was aliased to Location
in GraphQL:
func testOptionalOfNamedType() throws {
struct LocationObject: Codable {
let id: String
let name: String
}
struct User: Codable {
let id: String
let location: LocationObject?
}
struct TestResolver {
func user(context _: NoContext, arguments _: NoArguments) -> User {
return User(
id: "user1",
location: LocationObject(
id: "location1",
name: "Earth"
)
)
}
}
let testSchema = try Schema<TestResolver, NoContext> {
Type(User.self) {
Field("id", at: \.id)
Field("location", at: \.location)
}
Type(LocationObject.self, as: "Location") {
Field("id", at: \.id)
Field("name", at: \.name)
}
Query {
Field("user", at: TestResolver.user)
}
}
let api = TestAPI<TestResolver, NoContext>(
resolver: TestResolver(),
schema: testSchema
)
let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
defer { try? group.syncShutdownGracefully() }
XCTAssertEqual(
try api.execute(
request: """
query {
user {
location {
name
}
}
}
""",
context: NoContext(),
on: group
).wait(),
GraphQLResult(data: [
"user": [
"location": [
"name": "Earth",
],
],
])
)
}
It returns:
XCTAssertEqual failed: ("{"data":{"user":{"location":null}},"errors":[{"message":"Cannot complete value of unexpected type \"LocationObject\".","path":[]}]}") is not equal to ("{"data":{"user":{"location":{"name":"Earth"}}}}")
from graphiti.
Thanks for confirming the issue and detecting a related one.
- Change
Graphiti.Schema
to have its own type-reference resolution process, prior to creatingGraphQLType
objects.
I don't know how much work it would be to write a second resolution process. But from an outsiders perspective I would question if this wouldn't be code/work duplication.
- Change
GraphQL.GraphQLTypeReference
to have 2 string fields (maybeswiftName
andgraphQLName
or something), in which either are used to match it up to another type during the GraphQL type reduction process.
That's what I did in my forks. Except that I did use a different naming.
This seems to be the only solution I have in mind at the moment. But personally it feels a bit off to make changes to the GraphQL
package because of an implementation detail issue in a higher package.
from graphiti.
@alexsteinerde I took a look at your forks - thanks for referencing them! I'm agree that we should probably not require GraphQL
changes in order to support the Graphiti feature of aliasing types.
I pushed an alternative fix that uses approach 1, and created an MR here: #90
I'd love it if you could review! Thanks again!
from graphiti.
Thanks @NeedleInAJayStack! Looks good for me.
I tested it in a local project and it works fine.
from graphiti.
Related Issues (20)
- PartialSchema with coders HOT 1
- Federation N+1 query problem HOT 2
- Schema Introspection Failure HOT 2
- How to access the selectionSet from the Resolver ? HOT 3
- Renaming ConnectionTypes isn't working HOT 6
- Feature: Create better support for custom connections HOT 2
- PartialSchema error with argument in type field HOT 5
- Federation reference resolver with filtering
- Potential Bug with Input types HOT 2
- 'Identifiable' is only available in iOS 13.0 or newer HOT 2
- Decimal and NSDecimal HOT 3
- Bearer and basic authorization HOT 1
- Would it make sense to make NoArguments init public? HOT 2
- Is there a way to override the name of a Value in an Enum? HOT 2
- Coders with Date as Double in schema
- Improvements to SchemaBuilder and allowing sub schemas HOT 13
- Some types don't resolve anymore after updating to 1.2.1 HOT 8
- PartialSchema Type extensions HOT 9
- How do you include a ConnectionType in a PartialSchema? HOT 2
- The order of PartialSchemas matters for Interfaces, Unions, and ConnectionTypes - is this intentional? HOT 9
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from graphiti.