Skip to content

Commit

Permalink
Add support for custom scalars (resolves neo4j-graphql#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy2003 committed Aug 3, 2020
1 parent 4792d3f commit e801a8e
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 4 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@
<artifactId>neo4j-opencypher-dsl</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
3 changes: 2 additions & 1 deletion readme.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ You find more usage examples in the:
* link:src/test/resources/translator-tests1.adoc[Translator 1 TCK]
* link:src/test/resources/translator-tests2.adoc[Translator 2 TCK]
* link:src/test/resources/translator-tests3.adoc[Translator 3 TCK]
* link:src/test/resources/translator-tests-custom-scalars.adoc[Translator custom scalars TCK]
* link:src/test/resources/optimized-query-for-filter.adoc[Alternative Filter TCK]

== Demo
Expand Down Expand Up @@ -246,14 +247,14 @@ This example doesn't handle introspection queries, but the one in the test direc
* date(time)
* interfaces
* complex filter parameters, with optional query optimization strategy
* scalars

=== Next

* skip limit params
* sorting (nested)
* input types
* unions
* scalars
* spatial

== Documentation
Expand Down
11 changes: 11 additions & 0 deletions src/main/kotlin/org/neo4j/graphql/NoOpCoercing.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.neo4j.graphql

import graphql.schema.Coercing

object NoOpCoercing : Coercing<Any, Any> {
override fun parseLiteral(input: Any?) = input

override fun serialize(dataFetcherResult: Any?) = dataFetcherResult

override fun parseValue(input: Any?) = input
}
21 changes: 19 additions & 2 deletions src/main/kotlin/org/neo4j/graphql/SchemaBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import graphql.Scalars
import graphql.language.*
import graphql.schema.*
import graphql.schema.idl.RuntimeWiring
import graphql.schema.idl.ScalarInfo.STANDARD_SCALAR_DEFINITIONS
import graphql.schema.idl.SchemaGenerator
import graphql.schema.idl.SchemaParser
import graphql.schema.idl.TypeDefinitionRegistry
Expand Down Expand Up @@ -40,7 +41,23 @@ object SchemaBuilder {
enhancedRegistry.add(ObjectTypeDefinition.newObjectTypeDefinition().name(QUERY).build())
}

val builder = RuntimeWiring.newRuntimeWiring().scalar(DynamicProperties.INSTANCE)
val builder = RuntimeWiring.newRuntimeWiring()
typeDefinitionRegistry.scalars()
.filterNot { entry -> STANDARD_SCALAR_DEFINITIONS.containsKey(entry.key) }
.forEach { (name, definition) ->
val scalar = when (name) {
"DynamicProperties" -> DynamicProperties.INSTANCE
else -> GraphQLScalarType.newScalar()
.name(name)
.description(definition.description?.getContent() ?: "Scalar $name")
.withDirectives(*definition.directives.filterIsInstance<GraphQLDirective>().toTypedArray())
.definition(definition)
.coercing(NoOpCoercing)
.build()
}
builder.scalar(scalar)
}


enhancedRegistry
.getTypes(InterfaceTypeDefinition::class.java)
Expand Down Expand Up @@ -205,4 +222,4 @@ object SchemaBuilder {
typeDefinitionRegistry.add(inputType)
return inputName
}
}
}
5 changes: 4 additions & 1 deletion src/test/kotlin/org/neo4j/graphql/CypherTests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class CypherTests {
@TestFactory
fun `translator-tests3`() = CypherTestSuite("translator-tests3.adoc").run()

@TestFactory
fun `translator-tests-custom-scalars`() = CypherTestSuite("translator-tests-custom-scalars.adoc").run()

@TestFactory
fun `optimized-query-for-filter`() = CypherTestSuite("optimized-query-for-filter.adoc").run()
}
}
202 changes: 202 additions & 0 deletions src/test/resources/translator-tests-custom-scalars.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
:toc:

= Translator Tests

== Schema

[source,graphql,schema=true]
----
scalar Date
type Movie {
_id: ID!
title: String!
released: Date
}
----

== Tests

=== Create

.GraphQL-Query
[source,graphql]
----
mutation {
createMovie(title:"Forrest Gump", released: 1994) {
title
released
}
}
----

.Cypher params
[source,json]
----
{
"createMovieTitle": "Forrest Gump",
"createMovieReleased": 1994
}
----

.Cypher
[source,cypher]
----
CREATE (createMovie:Movie { title: $createMovieTitle, released: $createMovieReleased })
WITH createMovie
RETURN createMovie { .title, .released } AS createMovie
----

=== Update

.GraphQL-Query
[source,graphql]
----
mutation {
updateMovie(_id: 1, released: 1995) {
title
released
}
}
----

.Cypher params
[source,json]
----
{
"updateMovie_id": 1,
"updateMovieReleased": 1995
}
----

.Cypher
[source,cypher]
----
MATCH (updateMovie: Movie)
WHERE ID(updateMovie) = toInteger($updateMovie_id)
SET updateMovie = { released: $updateMovieReleased }
WITH updateMovie
RETURN updateMovie { .title, .released } AS updateMovie
----

=== Merge

.GraphQL-Query
[source,graphql]
----
mutation {
mergeMovie(_id: 1, released: 1995) {
title
released
}
}
----

.Cypher params
[source,json]
----
{
"mergeMovie_id": 1,
"mergeMovieReleased": 1995
}
----

.Cypher
[source,cypher]
----
MATCH (mergeMovie: Movie)
WHERE ID(mergeMovie) = toInteger($mergeMovie_id)
SET mergeMovie += { released: $mergeMovieReleased }
WITH mergeMovie
RETURN mergeMovie { .title, .released } AS mergeMovie
----

=== Merge null

.GraphQL-Query
[source,graphql]
----
mutation {
updateMovie(_id: 1, released: null) {
title
released
}
}
----

.Cypher params
[source,json]
----
{
"updateMovie_id": 1,
"updateMovieReleased": null
}
----

.Cypher
[source,cypher]
----
MATCH (updateMovie: Movie)
WHERE ID(updateMovie) = toInteger($updateMovie_id)
SET updateMovie = { released: $updateMovieReleased }
WITH updateMovie
RETURN updateMovie { .title, .released } AS updateMovie
----

=== Find

.GraphQL-Query
[source,graphql]
----
{
movie(released: 1994) {
title
released
}
}
----

.Cypher params
[source,json]
----
{
"movieReleased": 1994
}
----

.Cypher
[source,cypher]
----
MATCH (movie: Movie)
WHERE movie.released = $movieReleased
RETURN movie { .title, .released } AS movie
----

=== Filter

.GraphQL-Query
[source,graphql]
----
{
movie(filter:{released_gte: 1994}) {
title
released
}
}
----

.Cypher params
[source,json]
----
{
"filterMovieReleased_GTE": 1994
}
----

.Cypher
[source,cypher]
----
MATCH (movie: Movie)
WHERE movie.released >= $filterMovieReleased_GTE
RETURN movie { .title, .released } AS movie
----

0 comments on commit e801a8e

Please sign in to comment.