Neo4j GraphQL Library

repository·dev·Indexed 20 days ago

https://github.com/neo4j/graphql

A collection of tools to bridge Neo4j graph databases with GraphQL. It includes @neo4j/graphql for generating executable schemas with support for @relationship and @auth directives, @neo4j/introspector for transforming existing Neo4j database schemas into GraphQL type definitions, and @neo4j/graphql-toolbox for API experimentation.

Tokens
11.1K
Snippets
36
Records
44
Agent score
68%

What's inside neo4j-graphql

  1. Overview of Neo4j GraphQL Library packages

    dev

    The Neo4j GraphQL monorepo provides several tools for building and managing GraphQL APIs backed by Neo4j databases:

    • @neo4j/graphql: The core library used for GraphQL schema generation. It is designed to be used with API servers like Apollo Server to provide familiar GraphQL capabilities.
    • @neo4j/introspector: A utility to introspect an existing Neo4j database schema to help generate GraphQL schemas.
    • @neo4j/graphql-toolbox: A tool for experimenting with your Neo4j GraphQL API on Neo4j.
  2. Configure Authorization with @auth

    dev

    Use the @auth directive to define fine-grained access control. You can apply rules to entire types or specific fields. Rules can be based on relationships (e.g., checking if a user is a moderator), user attributes (using $jwt.sub to reference the current user's ID), or Role-Based Access Control (RBAC) using the roles property.

    # Rule based on relationship and JWT subject
    extend type Post @auth(rules: [{ allow: [{ moderator: { id: "$jwt.sub" } }], operations: [UPDATE] }])
    
    # Rule based on field-level access and roles
    type User {
        id: ID!
        username: String!
        password: String! @auth(rules: [{ OR: [{ allow: { id: "$jwt.sub" } }, { roles: ["admin"] }] }])
    }
    
    # RBAC on a type
    type Customer @auth(rules: [{ operations: [READ], roles: ["read:customer"] }]) {
        id: ID
        name: String
    }
  3. Generate GraphQL Type Definitions with @neo4j/introspector

    dev

    The introspector can generate GraphQL type definitions with support for:

    • @relationship directives (including relationship properties).
    • @node directives, including label (for mapping non-standard characters) and additionalLabels (for nodes with multiple labels).
    • Read-only schemas by applying a @exclude(operations: [CREATE, DELETE, UPDATE]) directive to all node types.

    Limitation: If a property has mixed types across different nodes in your graph, that property will be excluded from the generated definitions to prevent GraphQL server errors.

  4. Run package tests for @neo4j/graphql

    dev

    Package tests are used to verify that the production build packages expose the expected endpoints and behave correctly in different environments. These tests are designed to run against a standalone npm package to ensure that no devDependencies from the main @neo4j/graphql package are required for the library to function in production.

    To run these tests, you must execute them from the packages/graphql directory.

    Note: These tests are not part of the standard lerna run test suite and are intended for use during PRs and before releases, rather than during active development.

    cd packages/graphql
    npm run test:package-tests
  5. Quick Start with Apollo Server

    dev

    To use @neo4j/graphql, define your GraphQL schema using @relationship directives to map to Neo4j relationships, instantiate Neo4jGraphQL with your typeDefs and a neo4j-driver instance, and then use neoSchema.getSchema() to generate the executable schema for your GraphQL server (e.g., Apollo Server).

    const { Neo4jGraphQL } = require("@neo4j/graphql");
    const neo4j = require("neo4j-driver");
    const { ApolloServer } = require("apollo-server");
    
    const typeDefs = `
        type Movie {
            title: String
            year: Int
            imdbRating: Float
            genres: [Genre!]! @relationship(type: "IN_GENRE", direction: OUT)
        }
    
        type Genre {
            name: String
            movies: [Movie!]! @relationship(type: "IN_GENRE", direction: IN)
        }
    `;
    
    const driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("neo4j", "letmein"));
    
    const neoSchema = new Neo4jGraphQL({ typeDefs, driver });
    
    async function main() {
        const schema = await neoSchema.getSchema();
    
        const server = new ApolloServer({
            schema,
            context: ({ req }) => ({ req }),
        });
    
        await server.listen(4000);
    
        console.log("Online");
    }
    
    main();
  6. Install @neo4j/introspector

    dev
    The @neo4j/introspector package is a tool used to introspect the schema and data model of an existing Neo4j database. It can transform this schema into various data structures, most commonly GraphQL type definitions, which serve as a starting point for building a GraphQL schema.
  7. Run the Apollo Federation Subgraph Compatibility environment with Docker Compose

    dev

    This docker-compose.yml file sets up a local development environment consisting of a Neo4j Enterprise database and a products service. The products service is built from the local directory and is configured to connect to the Neo4j instance.

    Service Configuration

    Neo4j Service

    • Image: neo4j:enterprise
    • Ports:
      • 7474: HTTP Browser interface
      • 7687: Bolt protocol
    • Environment Variables:
      • NEO4J_ACCEPT_LICENSE_AGREEMENT=yes: Required to start the enterprise edition.
      • NEO4J_AUTH=neo4j/password: Sets the default credentials.
      • NEO4J_PLUGINS=["apoc"]: Installs the APOC plugin.
    • Healthcheck: Uses wget on the HTTP port to ensure the database is ready before dependent services start.

    Products Service

    • Build Context: Current directory (.)
    • Ports: 4001:4001
    • Environment Variables:
      • NEO4J_URI=neo4j://neo4j:7687/neo4j: The connection string used by the service to reach the Neo4j container.
    • Dependencies: Waits for the neo4j service to pass its healthcheck before starting.
    version: "3.9"
    services:
      neo4j:
        image: "neo4j:enterprise"
        ports:
          - 7474:7474
          - 7687:7687
        environment:
          - NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
          - NEO4J_AUTH=neo4j/password
          - NEO4J_PLUGINS=["apoc"]
        healthcheck:
          test: wget http://localhost:7474/browser -O -
          interval: 1s
          timeout: 1s
          retries: 40
      products:
        build: .
        ports:
          - "4001:4001"
        environment:
          - NEO4J_URI=neo4j://neo4j:7687/neo4j
        depends_on:
          neo4j:
            condition: service_healthy
  8. Example Mutations and Queries

    dev

    The library automatically generates mutation and query capabilities based on your schema.

    • Create: Use create<Type>s with an input array.
    • Update/Connect: Use update<Type>s with a where clause and a connect object to link existing nodes.
    • Nested Creation: You can connect existing nodes during a creation mutation using the connect key within the input object.
    • Querying: Standard GraphQL queries allow traversing relationships defined via @relationship.
    # Create Movies
    mutation {
        createMovies(input: [{ title: "The Matrix", year: 1999, imdbRating: 8.7 }]) {
            movies {
                title
            }
        }
    }
    
    # Connect existing movies to genres
    mutation {
        updateMovies(
            where: { title: "The Matrix" }
            connect: { genres: { where: { node: { OR: [{ name: "Sci-fi" }, { name: "Action" }] } } } }
        ) {
            movies {
                title
            }
        }
    }
    
    # Create Movie and connect Genre in one step
    mutation {
        createMovies(
            input: [
                {
                    title: "The Matrix"
                    year: 1999
                    imdbRating: 8.7
                    genres: { connect: { where: { node: { AND: [{ name: "Sci-fi" }, { name: "Action" }] } } } }
                }
            ]
        ) {
            movies {
                title
            }
        }
    }
    
    # Find Movies with Genres
    query {
        movies {
            title
            genres {
                name
            }
        }
    }