1.2.4 • Published 3 years ago

@graphex/core v1.2.4

Weekly downloads
-
License
ISC
Repository
github
Last release
3 years ago

Graphex Core

npm.io

Build Status

Description

This package allows you to automatically generate Apollo Server schema and resolvers for MongoDB using Prisma-like SDL.

Quick preview on codesandbox

Note! In Codesandbox any change in the code will restart the service. In this setup we use in memory DB, hence any restart will purge the data you'll create with Mutations

Edit graphex-example

Installation

With yarn:

yarn add @graphex/core

or using npm:

npm install --save @graphex/core

Usage

Project initialization is the same as for Apollo Server. The only difference is that we use makeExecutableSchema from this package to generate schema.

import ApolloModelMongo, { QueryExecutor } from '@graphex/core';
const schema = await new ApolloModelMongo({
  queryExecutor: QueryExecutor(db),
}).makeExecutablSchema({
  typeDefs,
});

const server = new ApolloServer({
  schema,
});

You can find full examples here

SDL example

type Category @model {
  id: ObjectID! @id @unique @db(name: "_id")
  title: String @default(value: "New Category")
  parentCategory: Category @relation(storeField: "parentCategoryId")
  subcategories: [Category!] @extRelation(storeField: "parentCategoryId")
  posts: [Post!] @extRelation
  createdAt: Date @createdAt
  updatedAt: Date @updatedAt
}

type Comment {
  body: String
  user: User! @relation
}

type Post @model {
  id: ObjectID! @id @unique @db(name: "_id")
  title: String!
  body: String!
  category: Category @relation
  keywords: [String!]
  owner: User! @relation
  place: GeoJSONPoint
  comments: [Comment!]
}

interface User @inherit @model {
  id: ObjectID! @id @unique @db(name: "_id")
  username: String! @unique
}

enum AdminRole {
  superadmin
  moderator
}

type Admin implements User {
  role: AdminRole
}

enum SubscriberRole {
  free
  standard
  premium
}

type SubscriberProfile {
  firstName: String!
  lastName: String!
}

type Subscriber implements User {
  role: SubscriberRole
  profile: SubscriberProfile!
}

The above SDL generates this endpoint https://apollo-model-mongodb-example.now.sh

Example queries below

Directives

The model directive

  • Connects object with MongoDB collection.
  • Valid locations: OBJECT or INTERFACE
  • Optional
  • Arguments
    • collection:String
    • The name of MongoDB collection * Optional (Default value is pluralized name of the object)

The unique directive

  • Add field to WHERE_UNIQUE input type
  • Valid locations: FIELD
  • Optional

The id directive

  • Mark field as identifier. Skip creation.
  • Valid locations: FIELD
  • Optional

The db directive

  • Map GraphQL field to collection.
  • Valid locations: FIELD
  • Optional
  • Arguments
    • name:String
    • The name of field in collection * Required

The default directive

  • Sets a default value for a field.
  • Valid locations: FIELD
  • Optional
  • Arguments
    • value:String
    • The default value for the field * Required

The inherit directive

  • Clones interface fields to objects.
  • Valid locations: INTERFACE
  • Required

The discriminator directive

  • Used to define field and values to resolve implementation type.
  • Valid locations: INTERFACE or OBJECT
  • Optional
  • Arguments
    • value:String
    • Required

The relation directive

  • Used to define relation between two collections.
  • Valid locations: FIELD
  • Optional
  • Arguments
    • field:String
    • Optional
    • Default value: _id
    • storeField:String
    • Optional
    • Default value: ${TypeName}Id${s}

The extRelation directive

  • Used to define external relation between two collections (identifiers stored in related documents).
  • Valid locations: FIELD
  • Optional
  • Arguments

    • field:String
      • Optional
      • Default value: _id
    • storeField:String
      • Optional
      • Default value: ${TypeName}Id${s}
    • many:Boolean

      • Optional
      • Default value: false

The createdAt directive

  • Sets date on field on CREATE.
  • Valid locations: FIELD
  • Optional

The updatedAt directive

  • Sets date on field on CREATE and UPDATE.
  • Valid locations: FIELD

Serverless

You can use this package with serverless environments. Read more here. Also take a look at example-now if you are using Zeit Now.

Customization

  • You can define your own scalars and directives as for usual Apollo server.
  • You can add custom modules at MongoModel stage (docs coming soon)
  • All queries to DB executes with QueryExecutor function. This package has predefined one, but you can override it and add hooks or check user authorization.
const QueryExecutor = ({ type, collection, doc, docs, selector, options })=>Promise

Contribution

You are welcome to open Issues, Feature Requests and PR with new features and bug fixes

Roadmap

  • Filter by Nth array element
  • Add subscriptions
  • Release stable version 1.0.0
  • Add Moment scalar
  • Improve Geo queries support

Features

Simple query

query
{
  categories {
    id
    title
  }
}
response
{
  "data": {
    "categories": [
      {
        "id": "5c3f4d84e98bd4e76e1d34d1",
        "title": "root"
      },
      {
        "id": "5c3f4dd3e98bd4e76e1d34d2",
        "title": "JS"
      },
      {
        "id": "5c3f4f46e98bd4e76e1d34d3",
        "title": "MongoDB"
      }
    ]
  }
}

Simple create

query
mutation {
  createCategory(data: { title: "root" }) {
    id
  }
}
response
{
  "data": {
    "createCategory": {
      "id": "5c3f4d84e98bd4e76e1d34d1"
    }
  }
}

Filter

request
{
  categories(where: { title: "root" }) {
    id
    title
  }
}

response

{
  "data": {
    "categories": [
      {
        "id": "5c3f4d84e98bd4e76e1d34d1",
        "title": "root"
      }
    ]
  }
}

Difficult filter

request
{
  categories(where: { OR: [{ title: "root" }, { title: "JS" }] }) {
    id
    title
  }
}

response

{
  "data": {
    "categories": [
      {
        "id": "5c3f4d84e98bd4e76e1d34d1",
        "title": "root"
      },
      {
        "id": "5c3f4dd3e98bd4e76e1d34d2",
        "title": "JS"
      }
    ]
  }
}

Relation query

query
{
  categories {
    id
    title
    parentCategory {
      title
    }
  }
}
response
{
  "data": {
    "categories": [
      {
        "id": "5c3f4d84e98bd4e76e1d34d1",
        "title": "root",
        "parentCategory": null
      },
      {
        "id": "5c3f4dd3e98bd4e76e1d34d2",
        "title": "JS",
        "parentCategory": {
          "title": "root"
        }
      },
      {
        "id": "5c3f4f46e98bd4e76e1d34d3",
        "title": "MongoDB",
        "parentCategory": {
          "title": "root"
        }
      }
    ]
  }
}

Relation filter

query
{
  categories(where: { parentCategory: { title: "root" } }) {
    id
    title
  }
}
response
{
  "data": {
    "categories": [
      {
        "id": "5c3f4dd3e98bd4e76e1d34d2",
        "title": "JS"
      },
      {
        "id": "5c3f4f46e98bd4e76e1d34d3",
        "title": "MongoDB"
      }
    ]
  }
}

Relation create

query
mutation {
  createCategory(
    data: {
      title: "Mongodb"
      parentCategory: { connect: { id: "5c3f4d84e98bd4e76e1d34d1" } }
    }
  ) {
    id
  }
}
response
{
  "data": {
    "createCategory": {
      "id": "5c3f4f46e98bd4e76e1d34d3"
    }
  }
}

Nested create

query
mutation {
  createSubscriber(
    data: {
      username: "subscriber1"
      profile: { create: { firstName: "Gwion", lastName: "Britt" } }
    }
  ) {
    id
    username
  }
}
response
{
  "data": {
    "createSubscriber": {
      "id": "5c3f555b190d25e7bda1dea2",
      "username": "subscriber1"
    }
  }
}

Interfaces

Connect

query
mutation {
  createPost(
    data: {
      title: "Build GraphQL API with Apollo"
      body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
      owner: { connect: { Admin: { username: "admin" } } }
    }
  ) {
    id
  }
}
response
{
  "data": {
    "createPost": {
      "id": "5c401347de7e67e9540abad2"
    }
  }
}

Query

query
{
  posts {
    title
    owner {
      username
      ... on Subscriber {
        profile {
          firstName
          lastName
        }
      }
    }
  }
}
response
{
  "data": {
    "posts": [
      {
        "title": "Build GraphQL API with Apollo",
        "owner": {
          "username": "admin"
        }
      }
    ]
  }
}

Geo queries

query
{
  posts(
    where: {
      place_near: {
        geometry: { type: Point, coordinates: [0, 51.01] }
        maxDistance: 10000
      }
    }
  ) {
    id
    title
    place {
      distance(toPoint: { type: Point, coordinates: [0, 51.01] })
    }
  }
}
response
{
  "data": {
    "posts": [
      {
        "id": "5c401347de7e67e9540abad2",
        "title": "Build GraphQL API with Apollo",
        "place": {
          "distance": 1111.9492664453662
        }
      }
    ]
  }
}