GraphQLSwift / Graphiti

The Swift GraphQL Schema framework for macOS and Linux
MIT License
526 stars 66 forks source link

Adds a SchemaBuilder type for modular schema creation #87

Closed NeedleInAJayStack closed 1 year ago

NeedleInAJayStack commented 1 year ago

This adds a SchemaBuilder, which enables much more modular schema creation. By breaking up the schema definition, different parts of the schema could be created in different functions, files, or even packages.

paulofaria commented 1 year ago

Are these additive changes? Didn't have enough time to properly look into it, yet.

NeedleInAJayStack commented 1 year ago

Yup, purely additive.

paulofaria commented 1 year ago

Have you tried implementing it using result builders? I think it fits better with Swift when comparing it to fluent builders.

NeedleInAJayStack commented 1 year ago

Can you split up result builder definitions or do they always need to be defined in a single contiguous block?

I'll admit, I'm not a result builder expert. My goal with this was to allow schemas to be defined over a number of different functions, files, or even packages, because my schema definitions get REALLY huge and unwieldy when I have to keep them in a single block. Builders like Vapor's RouteBuilder or SQLKit's SQLPredicateBuilder achieve that goal pretty well. For example, we could have a project with the 3 files below, where functionality is separated effectively:

# Main.swift

let builder = SchemaBuilder<Res, Ctx>()
addHello(to: builder)
addGoodbye(to: builder)
let schema = try builder.build()
print(schema.execute("{ goodbye }", ...)) // Prints: {"goodbye": "for now"}
# Hello.swift

extension Res {
    func hello() -> String {
        "world"
    }
} 
func addHello(to builder: SchemaBuilder<Res, Ctx>) {
    builder.addQuery(
        Field("hello", at: \.hello)
    )
}
# Goodbye.swift

extension Res {
    func goodbye() -> String {
        "for now"
    }
} 
func addGoodbye(to builder: SchemaBuilder<Res, Ctx>) {
    builder.addQuery(
        Field("goodbye", at: \.goodbye)
    )
}

I didn't know how to accomplish something like this with a resultBuilder pattern. If there is one, could you provide me a quick example?

NeedleInAJayStack commented 1 year ago

Also, just to be clear, the SchemaBuilder.add* methods take result builder arguments. And I'm not removing any existing Schema.init result builder functionality.

paulofaria commented 1 year ago

Hey, Jay! Sure, I'll give you an update this week!

NeedleInAJayStack commented 1 year ago

Hey @paulofaria, any updates on this? I'd be happy to make the changes if you can get me an example of the multi-file result-builder schema construction!

paulofaria commented 1 year ago

Sorry! I'm moving to a new house, so things are chaotic around here. I'll try to find the time, though. Should be straight forward.

paulofaria commented 1 year ago

Hey, @NeedleInAJayStack. Can you please check you reddit DMs? 😁

NeedleInAJayStack commented 1 year ago

@paulofaria Hah, what? I'm not on Reddit, but you can always reach me at NeedleInAJayStack@protonmail.com

cshadek commented 1 year ago

Any updates on this?

NeedleInAJayStack commented 1 year ago

I think @paulofaria was going to send me an example of a distributed ResultBuilder

paulofaria commented 1 year ago

Really sorry about the delay. @NeedleInAJayStack can I update this PR directly, with the result builder approach? I think it's easier.

NeedleInAJayStack commented 1 year ago

@paulofaria No worries! Sure, feel free to edit this directly or on your own branch of my work.

paulofaria commented 1 year ago

Hey, I’m really sorry about this. I think it’s best to merge this as is and improve later, if necessary.

NeedleInAJayStack commented 1 year ago

Awesome, thanks Paulo! Mind approving again after my rebase?

paulofaria commented 1 year ago

@NeedleInAJayStack thank you very much for this, Jay!