1.0.6 • Published 9 months ago

@mavvy/mgql v1.0.6

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

Mongoose + Graphql + Apollo all in one

Creating graphql server just got easier

Getting Started

Installation

install dependencies

npm install @mavvy/mgql @apollo/server mongoose graphql

Example

see examples directory examples

What is MGql?

Basically it generates mongoose schema and graphql schema at the same time from a model array data. Also, it helps create resolvers with additional helpers that has automatic integration to the database.

Object model to mongoose and graphql schema

This will be transformed into a mongoose and graphql schema

[
  {
    name: 'Comment',
    fields: {
      body: String,
      date: Date,
    },
  },
  {
    name: 'Blog',
    fields: {
      title: String, // String is shorthand for {type: String}
      author: String,
      body: String,
      comments: [
        {
          _gql: '[Comment]',
          body: String,
          date: Date,
        },
      ],
      hidden: Boolean,
      meta: {
        _gql: 'Meta',
        votes: Number,
        favs: Number,
      },
    },
  },
]

the above code will create this gql schema below:

type Comment {
  body: String
  date: String
  createdAt: Float
  updatedAt: Float
  deletedAt: Float
  isDeleted: Boolean
  id: ID
}

type Meta {
  votes: Int
  favs: Int
  createdAt: Float
  updatedAt: Float
  deletedAt: Float
  isDeleted: Boolean
  id: ID
}

type Blog {
  title: String
  author: String
  body: String
  comments: [Comment]
  hidden: Boolean
  meta: Meta
  createdAt: Float
  updatedAt: Float
  deletedAt: Float
  isDeleted: Boolean
  id: ID
}

And then will create mongoose schema for Comment and Blog

Usage

import 'dotenv/config';
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import * as mgql from '@mavvy/mgql';

const uri = process.env.MONGO_URI as string;
const models = [
  {
    name: 'Comment',
    fields: {
      body: String,
      date: Date,
    },
  },
  {
    name: 'Blog',
    fields: {
      title: String, // String is shorthand for {type: String}
      author: String,
      body: String,
      comments: [
        {
          _gql: '[Comment]',
          body: String,
          date: Date,
        },
      ],
      hidden: Boolean,
      meta: {
        _gql: 'Meta',
        votes: Number,
        favs: Number,
      },
    },
  },
];
const resolvers = [
  {
    name: 'blogs',
    model: 'Blog',
    resolverType: 'Query',
    handler: async ({ model }) => model().find(),
    returnType: '[Blog]',
  },
  {
    name: 'addBlog',
    model: 'Blog',
    resolverType: 'Mutation',
    handler: ({ actions, input }) => actions.create(input),
    inputVariable: 'CreateBlogInput!',
    returnType: 'Blog',
  },
  {
    name: 'addComment',
    model: 'Comment',
    resolverType: 'Mutation',
    inputVariable: 'AddCommentInput!',
    handler: async ({ model, actions, input }) => {
      const blogModel = model('Blog');
      const blog = await blogModel.findById(input.blogId);
      const comment = await actions.create({ body: input.body });

      blog.comments.push(comment);

      await blog.save();

      return comment;
    },
    returnType: 'Comment',
  },
] as mgql.MgqlResolvers[];

const appSchema = `input CreateBlogInput {
  title: String!
  author: String!
  body: String!
}

input AddCommentInput {
  blogId: ID!
  body: String!
}`;

const main = async () => {
  const modelSchema = mgql.toSchema(models);
  await mgql.initDb({ uri, models });

  const schema = mgql.createSchema(
    [appSchema].concat(modelSchema),
    resolvers,
    models,
  );

  const server = new ApolloServer({
    typeDefs: schema.typeDefs,
    resolvers: schema.resolvers,
  });

  const { url } = await startStandaloneServer(server, {
    listen: { port: 4000 },
  });

  console.log(`🚀  Server ready at: ${url}`);
};

main();

API

Models

keytypedescription
namestringname of the mongoose schema
fieldsobjectproperties of the schema. The shape of the documents within that collection
Model Field Item Attributes
_gql: string

Graphql schema to apply to the field item

{
  name: 'Blog',
  fields: {
    author: {
      _gql: 'Author',
      name: String
    }
  }
}

will generate:

type Author {
  name: String
}
type Blog {
  author: Author
}
_hidden: boolean

Will not generate a gql schema for that field item

{
  name: 'Blog',
  fields: {
    title: String,
    author: {
      _gql: 'Author',
      _hidden: true,
      name: String
    }
  }
}

will generate:

type Blog {
  title: String
}
_omit: string[]

will not generate gql fields which are listed on the _omit field

{
  name: 'Blog',
  fields: {
    author: {
      _gql: 'Author',
      _omit: ['foo', 'bar'],
      name: String
      foo: String
      bar: String
    }
  }
}

will generate:

type Author {
  name: String
}
type Blog {
  author: Author
}
_override: boolean

Nested objects will automatically generate a schema type. If you don't want to override the schema type, set _override to true

[
  {
    name: 'User',
    fields: {
      name: String
    }
  },
  {
    name: 'Project',
    fields: {
      todo: {
        _gql: 'Todo',
        user: {
          _gql: 'User',
          _override: true,
          nickname: String
        },
        tag: {
          _gql: 'Tag',
          name: String
        }
      }
    }
  }
]

Will generate gql schema:

type User {
  nickname: String
}
type Tag {
  name: String
}
type Todo {
  user: User
  tag: Tag
}
type Project {
  todo: Todo
}

Resolvers

A resolver item is a configuration to create a Query or Mutation (Subscriptions soon).

keytypedescription
namestringname of the resolver
modelstring?name of the mongoose model to use inside the handler
resolverTypeQuery | Mutationtype of the resolver
returnTypestringSchema name of the return data
inputVariablestring?Schema name of the input
disabledboolean?disables the resolver
rolesstring[]?array of roles that is authorized to use the resolver
handler(handlerArgs) => anythe main resolver function
handlerArgs object
keydescription
parentContextresolver.parentContext param from apolo
variablesresolver.variables param from apollo
contextresolver.context param from apollo
optionsresolver options such as model name, returnType, etc.
inputshorthand to return the value from variables.input
model(name?: string) => mongoose.Model . the default name is the model name value from the resolver
actionsactions.create is use to add data to db. actions.search is use to find data from the db
1.0.2

9 months ago

1.0.1

9 months ago

1.0.0

9 months ago

1.0.6

9 months ago

1.0.5

9 months ago

1.0.4

9 months ago

1.0.3

9 months ago

0.1.0

9 months ago

0.2.0

9 months ago

0.3.2

9 months ago

0.3.1

9 months ago

0.3.3

9 months ago

0.0.1

1 year ago