3.0.0 Migration

How to upgrade

Simply update @neo4j/graphql using npm or your package manager of choice:

npm update @neo4j/graphql

Asynchronous schema generation

Schema generation is now asynchronous. Instead of using the property schema, now the method getSchema will return the schema as a Promise. This means that creating a server now requires awaiting for that method:

Instead of

const neoSchema = new Neo4jGraphQL({ typeDefs, driver });
const server = new ApolloServer({
    schema: neoSchema.schema,
});

Now you’ll need to do the following:

const neoSchema = new Neo4jGraphQL({ typeDefs, driver });
neoSchema.getSchema().then((schema) => {
    const server = new ApolloServer({
        schema: schema
    });
});

Relationship changes

This release contains an overhaul of our relationship validations, which will require a few changes to the schema.

Many-to-* relationships

To improve consistency and validation, all "many-to-*" relationships need to be defined as required in the schema:

type Movie {
    actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN)
    director: Director @relationship(type: "DIRECTED", direction: IN)
}

Note that any other notation, such as [Actor] or [Actor!] will not be valid. "One-to-one" relationships such as Director remain unchanged.

Relationship cardinality

Runtime checks for "one-to*" relationships have been added in this release, ensuring that the correct number of relationships exist. This means that some databases with inconsistent relationships between the schema definition and the actual data may now fail in some queries. This may have happened due to different reasons such as direct changes in the database or changes to the type definitions. Previous versions of @neo4j/graphql did not have any consistency check, so normal use of these versions may have lead to inconsistent relationships.

For these cases, please ensure that the database is following your schema definition or update the schema to reflect the actual existing relationships, taking care of which relationships are 1-to-* or many-to-many.

Count query no longer supported

Queries using count at the root level are no longer supported. For example:

query {
    usersCount
}

The same operation, can now be achieved with a count aggregation query:

query {
    usersAggregate {
        count
    }
}

Relationship filters

where filters for relationship queries now explicitly state ALL, NONE, SINGLE, and SOME as part of filter name.

Queries using old relationship filters, will now need to use {relationship}_SOME. For example:

query {
  movies(where: {
    actors: {
      name: "John"
    }
  }) {
    title
  }
}

Should be:

query {
  movies(where: {
    actors_SOME: {
      name: "John"
    }
  }) {
    title
  }
}

And, instead of _NOT, _NONE should be used.

Old queries will still work in this release, but are marked as @deprecated and will not be available in the future.

@ignore directive renamed to @computed

To better reflect its intended usage, the @ignore directive is now named @computed. Behaviour is unchanged, so you just need to rename this directive in your schema.

Auth plugin system

Auth setup now relies on plugins to setup the configuration. You’ll need to install @neo4j/graphql-plugin-auth or a custom plugin as shown in the auth setup page.

JWT auth

For JWT authorization, instead of the previous configuration:

const neoSchema = new Neo4jGraphQL({
    typeDefs,
    config: {
        jwt: {
            secret
        }
    }
});

Now the configuration should be passed through Neo4jGraphQLAuthJWTPlugin:

import { Neo4jGraphQL } from "@neo4j/graphql";
import { Neo4jGraphQLAuthJWTPlugin } from "@neo4j/graphql-plugin-auth";

const neoSchema = new Neo4jGraphQL({
    typeDefs,
    plugins: {
        auth: new Neo4jGraphQLAuthJWTPlugin({
            secret: "super-secret"
        })
    }
});

JWKS decoding

JSON Web Key Sets are now supported through Neo4jGraphQLAuthJWKSPlugin.

Instead of setting the endpoint directly:

const neoSchema = new Neo4jGraphQL({
    typeDefs,
    config: {
        jwt: {
            jwksEndpoint: "https://YOUR_DOMAIN/.well-known/jwks.json"
        }
    }
});

Now the Neo4jGraphQLAuthJWKSPlugin would take care of that:

import { Neo4jGraphQL } from "@neo4j/graphql";
import { Neo4jGraphQLAuthJWKSPlugin } from "@neo4j/graphql-plugin-auth";

const neoSchema = new Neo4jGraphQL({
    typeDefs,
    plugins: {
        auth: new Neo4jGraphQLAuthJWKSPlugin({
            jwksEndpoint: "https://YOUR_DOMAIN/well-known/jwks.json",
        })
    }
});
Please, refer to auth setup before setting up auth.

Types plurals changes

To improve consistency, some automatically generated plurals (e.g. createActors) have changed. This may cause issues if your types use conventions such as snake_case.

Because of this, you may find generated queries and mutations may have different names. If you encounter this problem, please update your clients to use the new query names or use the plural option in the @node directive to force a custom plural value.

Custom Directives

Defining and applying custom directives has changed significantly, if you are using or plan to use custom directives, make sure to check the up-to-date documentation on custom directives.

Types changes

Some automatically generated types have changed to improve consistency. These should not require any changes from most developers, unless types names are directly used.

Some automatically generated types have changed to improve consistency. These should not require any changes from the developer in most cases, unless in cases where types names are directly used.

Removal of nested operation fields for connectOrCreate

Input types for onCreate in connectOrCreate operations no longer accept relationship fields. They were originally added in error and did not function as one would expect, so there is no regression in functionality.

Non Nullable Aggregation Results

Aggregation results may now be non-nullable for required fields, yielding more accurate types.

For example, for the following types:

type User {
    name: String!
    lastName: String
}

Will yield different types for aggregations over name and lastName:

type UserAggregateSelection {
  count: Int!
  name: StringAggregateSelectionNonNullable!
  lastName: StringAggregateSelectionNullable!
}

ConnectionWhere types renamed

ConnectionWhere types renamed to improve consistency with other similarly named types.

Neo4j support

Neo4j 4.1 is no longer supported in 3.0.0, inline with the supported versions list.

GraphQL support

graphql@^15.0.0 is no longer supported, please upgrade to graphql@^16.0.0 using npm or the package manager of your choice.