Alpha 🏗
A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations.
$ npm install @neo4j/graphql
⚠ graphql
& neo4j-driver
are peerDependency(s)
$ npm install graphql neo4j-driver
Import libraries using either import
:
import { Neo4jGraphQL } from "@neo4j/graphql";
import * as neo4j from "neo4j-driver";
import { ApolloServer } from "apollo-server";
Or require
:
const { Neo4jGraphQL } = require("@neo4j/graphql");
const neo4j = require("neo4j-driver");
const { ApolloServer } = require("apollo-server");
Then proceed to create schema objects and serve over port 4000 using 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 neoSchema = new Neo4jGraphQL({ typeDefs });
const driver = neo4j.driver(
"bolt://localhost:7687",
neo4j.auth.basic("neo4j", "letmein")
);
const server = new ApolloServer({
schema: neoSchema.schema,
context: ({ req }) => ({ req, driver }),
});
server.listen(4000).then(() => console.log("Online"));
mutation {
createMovies(
input: [{ title: "The Matrix", year: 1999, imdbRating: 8.7 }]
) {
movies {
title
}
}
}
mutation {
updateMovies(
where: { title: "The Matrix" }
connect: {
genres: { where: { OR: [{ name: "Sci-fi" }, { name: "Action" }] } }
}
) {
movies {
title
}
}
}
mutation {
createMovies(
input: [
{
title: "The Matrix"
year: 1999
imdbRating: 8.7
genres: {
connect: { where: [{ name: "Sci-fi" }, { name: "Action" }] }
}
}
]
) {
movies {
title
}
}
}
query {
movies {
title
genres {
name
}
}
}
Use the GraphQL schema language to power an OGM layer.
import { OGM } from "@neo4j/graphql";
import * as neo4j from "neo4j/driver";
const driver = neo4j.driver(
"bolt://localhost:7687",
neo4j.auth.basic("admin", "password")
);
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 ogm = new OGM({ typeDefs, driver });
const Movie = ogm.model("Movie");
await Movie.create({
input: [
{
title: "The Matrix"
year: 1999
imdbRating: 8.7
genres: {
connect: { where: [{ name: "Sci-fi" }, { name: "Action" }] }
}
}
]
});
Define, nested & related, authorization rules such as; “grant update access to all moderators of a post”;
type User {
id: ID!
username: String!
}
type Post {
id: ID!
title: String!
moderator: User @relationship(type: "MODERATES_POST", direction: "IN")
}
extend type Post
@auth(
rules: [
{
allow: [{ moderator: { id: "$jwt.sub" } }]
operations: ["update"]
}
]
)
Specify rules on fields;
type User {
id: ID!
username: String!
}
extend type User {
password: String!
@auth(
rules: [
{
OR: [{ allow: { id: "$jwt.sub" } }, { roles: ["admin"] }]
operations: "*"
}
]
)
}
Use RBAC;
type CatalogItem @auth(rules: [{ operations: "read", roles: "read:catalog" }]) {
id: ID
title: String
}
type Customer @auth(rules: [{ operations: "read", roles: "read:customer" }]) {
id: ID
name: String
password: String @auth(rules: [{ operations: "read", roles: "admin" }])
}
type Invoice @auth(rules: [{ operations: "read", roles: "read:invoice" }]) {
id: ID
csv: String
total: Int
}