Git Product home page Git Product logo

Comments (13)

pgutkowski avatar pgutkowski commented on July 19, 2024 1

These would be great improvements. Both proposed features need to be thoroughly analyzed in context of KGraphQL's architecture and API. I will come back to you soon with some proposals/conclusions. Thanks!

from kgraphql.

Paradoxia avatar Paradoxia commented on July 19, 2024

Awesome! While your at it, maybe you can think of a good way to control the introspection. As an example you don't want to give easy access to the graphql schema on a public website. Maybe an interface that normally return "true" (= allow introspection) but which can be overriden?

from kgraphql.

pgutkowski avatar pgutkowski commented on July 19, 2024

I agree that possibility to limit access to introspection is a must have. I guess it will be introduced with field permission control.

I was prototyping a bit today, trying to implement context parameter to resolvers. What do you think about following snippet:

data class UserData(val name : String, val isAdmin : Boolean = false)

val contextDemoSchema = KGraphQL.schema {
    query("me"){
        //Context is class provided by library, it wraps context pairs provided to execute method
        resolver { ctx: Context -> ctx.get<UserData>("userData").name }
    }
}

fun main(args : Array<String>) {
    //fun execute(request: String, vararg context: Pair<String, Any> = emptyArray())
    val meName = contextDemoSchema.execute("{me}", "userData" to UserData("Jan Kowalski"))
    println(meName) // prints '{"data":{"me":"Jan Kowalski"}}'
}

About permission control - I'm still collecting informations and searching for best approach.

from kgraphql.

Paradoxia avatar Paradoxia commented on July 19, 2024

That is one way of doing it. Though what I love with your library is how clean and readable the code become. Wrapping stuff in a Context object make the code less readable.

Hmm, maybe if we drop the "Context" definition and see this like a need of being able to pass a custom object to the resolver (some might use it as a Context, others for debugging) and then have an additional resolver that begins with _ (underscore).

    // How we do it today  
    query("me"){
        resolver { name : String -> ......  }
    }

    // Optional way  
    query("me"){
        _resolver {  _ : Any, name : String -> ......  }
    }

_resolver always pass the custom object defined as third parameter in execute as first parameter.

Well something like this to still keep the code clean. Remember that we are trying to solve a problem most likely only used on public websites.

from kgraphql.

pgutkowski avatar pgutkowski commented on July 19, 2024

I see your point. At glance, your proposal looks more readable and straightforward. On the other hand, client code would have to cast context object to expected type, and in case if it would need multiple context objects(because code calling Schema.execute shouldn't care what query is executed), custom context class would need to be created. So, effectively it would look like this:

data class UserData(val name : String, val isAdmin : Boolean = false)

data class RequestData(val time: Timestamp)

//just wrapper for context objects
data class Context(val userData: UserData, val requestData : RequestData)

val contextDemoSchema = KGraphQL.schema {
    query("me"){
        _resolver { _ctx: Any -> (_ctx as Context).userData.name }
    }

    query("time"){
        _resolver{ _ctx : Any -> (_ctx as Context).requestData.timestamp }
    }
}

fun main(args : Array<String>) {
    val context =  Context(UserData("Jan Kowalski"), RequestData(System.currentTimeMillis()))
    val meName = contextDemoSchema.execute("{me}", context)
    println(meName) // prints '{"data":{"me":"Jan Kowalski"}}'
}

that's why I think that in long run, this solution may be less flexible and a bit inconvenient for bigger codebases.

I'm thinking, maybe we can meet somewhat in the middle, and introduce @Context annotation, so library would know which arguments it should inject into resolvers so previous example would look like this:

@Context
data class UserData(val name : String, val isAdmin : Boolean = false)

@Context
data class RequestData(val time: Timestamp)

val contextDemoSchema = KGraphQL.schema {
    query("me"){
        resolver { userData: UserData -> userData.name }
    }

    query("time"){
        resolver{ requestData : RequestData -> requestData.timestamp }
    }
}

fun main(args : Array<String>) {
    val meName = contextDemoSchema.execute("{me}", UserData("Jan Kowalski"), RequestData(System.currentTimeMillis()))
    println(meName) // prints '{"data":{"me":"Jan Kowalski"}}'
}

It would work a little like Spring's injection of controller handlers, but we have to remember that it would introduce big portion of complexity and behind the scenes 'magic'. Another concern is that client code may want to pass instance of class defined by another library/framework, so maybe DSL method like

context<UserData>()
context<RequestData>()

would be convenient as well.

What do you think?

from kgraphql.

Paradoxia avatar Paradoxia commented on July 19, 2024

Would it be possible to add T2 to the definition of resolver?

        resolver<T> { param1 : Int -> ... }
        resolver<T1, T2> { ctx (T2), param1 : Int -> .... }

        T, T1 = Return Type
        T2 = Context Type

I use Spring injection in all my projects and love it, but if you walk that path then you will steer away from the simplicity of your library (which i also love).

from kgraphql.

pgutkowski avatar pgutkowski commented on July 19, 2024

So to sum up, if we agree on single context type created by client code, maybe it should be generic parameter of Schema interface? this way, execute method and resolvers could be type checked.

data class UserData(val name : String, val isAdmin : Boolean = false)

data class RequestData(val time: Timestamp)

//just wrapper for context objects
data class Context(val userData: UserData, val requestData : RequestData)

val contextDemoSchema = KGraphQL.schema<Context> {
    query("me"){
        _resolver { ctx: Context -> ctx.userData.name }
    }

    query("time"){
        _resolver{ ctx : Context -> ctx.requestData.timestamp }
    }
}

fun main(args : Array<String>) {
    val context =  Context(UserData("Jan Kowalski"), RequestData(System.currentTimeMillis()))
    //fun execute(request: String, context: Context) where Context is type paramter of contextDemoSchema
    val meName = contextDemoSchema.execute("{me}", context)
    println(meName) // prints '{"data":{"me":"Jan Kowalski"}}'
}

from kgraphql.

Paradoxia avatar Paradoxia commented on July 19, 2024

I like it. Clean and easy to read/understand

from kgraphql.

pgutkowski avatar pgutkowski commented on July 19, 2024

0.2.4 has been released with support for custom context objects. Example snippet:

data class UserData(val name : String, val isAdmin : Boolean = false)

data class RequestData(val time: Timestamp)

//just wrapper for context objects
data class Context(val userData: UserData, val requestData : RequestData)

val contextDemoSchema = KGraphQL.schema(Context::class) {
    query("me"){
        resolver { ctx: Context -> ctx.userData.name }
    }

    query("time"){
        resolver{ now : Boolean, ctx : Context -> if(now) ctx.requestData.timestamp else 0 }
    }
}

fun main(args : Array<String>) {
    val context =  Context(UserData("Jan Kowalski"), RequestData(System.currentTimeMillis()))
    //fun execute(request: String, context: Context) where Context is type parameter of contextDemoSchema
    val meName = contextDemoSchema.execute("{me}", context)
    println(meName) // prints '{"data":{"me":"Jan Kowalski"}}'
}

As you can see, schema creation invocations is KGraphQL.schema(Context::class){}, not KGraphQL.schema<Context>{}. Reasoning behind this is that I wanted to KGraphQL.schema {} to be still valid, and second variant would lead to function signature clash. Besides, context argument can be declared in any position.

from kgraphql.

Paradoxia avatar Paradoxia commented on July 19, 2024

Nice!! Will try this a.s.p.

from kgraphql.

pgutkowski avatar pgutkowski commented on July 19, 2024

Hey @Paradoxia did you try it? If so, please let me know if it works as you expected.

from kgraphql.

Paradoxia avatar Paradoxia commented on July 19, 2024

Sorry for the delayed answer. I've been stuck in another project.

I've been trying to migrate to 0.2.4 but the compiler give me tons of errors and intellisense doesn't want to help me out.

interface SchemaService {
    fun schema(): Schema
    fun docs(): String
}

What should I add to : Schema to avoid the One type argument expected for interface Schema<Context> : __Schema defined in com.github.pgutkowski.kgraphql.schema error message.

I've created my own Context class (i call it SchemaContext).

from kgraphql.

pgutkowski avatar pgutkowski commented on July 19, 2024

No problem, thank you for quick response!

Handling parameterized context object forced us to add generic parameter to Schema, so please try changing Schema to Schema<SchemaContext>

from kgraphql.

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.