npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

graphqlizejs

v0.4.4

Published

Generate DataTypes and Resolvers from your ORM Sequilize models

Downloads

5

Readme

Graphqlizejs

Build Status NPM JavaScript Style Guide

Graphqlizejs automatically generate data types and resolvers for graphql servers from your sequelizejs models!

it's awesome... really awesome!

You define your models and everything it's available!

  • Inputs

    • inputs wheres
    • inputs operators
    • inputs mutations
  • Types

    • types models
    • types associations
  • Queries

    • queries models
    • queries counters
  • Mutations

    • create mutation
    • update mutation
    • delete mutation
  • Subscriptions

    • create
    • update
    • delete

Install

git clone https://github.com/stvkoch/graphqlize.git
cd graphqlize
npm install# or npm
npm start # or npm
# open url http://localhost:4000/graphql
# can access complete generate schema in http://localhost:4000

It's awesome because SequelizeJs it's very powerful!

Do you know about sequelizejs?

  • No? Then check out the site http://docs.sequelizejs.com/

You can do a lot of things with sequelizejs and Graphqlizejs automagic generate graphql datatype and resolvers from your models

No patience?

OK, let's check the demo?

Graphql

graphql> https://graphqlize.herokuapp.com/graphql

schema> https://graphqlize.herokuapp.com/

Examples of queries that you can play

{
  # IN operator
  queryAsInOp: services(where: {id: { in: ["3", "7", "12"] }}) {
    id
    name
    price
  }
  # operator combination AND
  countQueryAsAndOp: _servicesCount(where: {price: { gt: 150, lt: 200 }})
  queryAsAndOp: services(where: {price: { gt: 150, lt: 200 }}) {
    id
    name
    price
  }
  # you can also use conditions inside of yours associations
  country(where: {id: { eq: "PT" }}) {
    id
    name
    _servicesCount(where: {price: { gt: 150, lt: 200 }})
    services(where: {price: { gt: 150, lt: 200 }}) {
      id
      name
      price
    }
  }
  # we don't support directly OR, but in graphql you request more that one list
  expensiveServices: services(where: {price: { gt: 980 }}) {
    id
    name
    price
  }
  #OR
  cheapServices: services(where: {price: { lt: 20 }}) {
    id
    name
    price
  }

  # query over JSONB structures
  overJsonb: services(where: { meta: { path: "meta.baz.foo", where: { eq: "baz" } } }) {
    id
    meta
    countryId
    country {
      id
      name
    }
  }
}

Go to by examples

Let's imagine that we have follow models (example folder):

// models/category.js file with all graphqlizejs options available
export default (sequelize, DataTypes) => {
  const Category = sequelize.define(
    "category",
    {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,

         // option enable/disable graphql prop [default: false]
        gqIgnore: false
      },
      name: {
        type: DataTypes.STRING,

        // option enable/disable graphql prop [default: false]
        gqIgnore: false
      }
    },
    {
      freezeTableName: true,

      // optional different name for graphql
      gqName: 'category',

      // option enable/disable generate all grapqhl queries/mutations for this model [default: false]
      gqIgnore: false,

      // option enable/disable generate grapqhl query for this model [default: true]
      gqQuery: true,

      // option enable/disable generate grapqhl query count  for this model [default: true]
      gqQueryCount: true,

      // option enable/disable generate grapqhl mutation create for this model [default: true]
      gqCreate: true,

      // option enable/disable generate grapqhl mutation update for this model [default: true]
      gqUpdate: true,

      // option enable/disable generate grapqhl mutation delete for this model [default: true]
      gqDelete: true,

      // enable/disable generate grapqhl subscriptions of follow operations [default: false]
      gqSubscriptionCreate: false,
      gqSubscriptionUpdate: false,
      gqSubscriptionDelete: false,

      // set middlewares for each operations to restrict or changes requests or results [default: defaultMiddleware]
      gqMiddleware: {
        query: defaultMiddleware,
        queryCount: defaultMiddleware,
        create: defaultMiddleware,
        update: defaultMiddleware,
        delete: defaultMiddleware,
        subscribe: defaultMiddleware
      }
    }
  );
  Category.associate = models => {
    Category.hasOne(models.category, { as: "parent", foreignKey: "parentId" });
    Category.hasMany(models.service);
  };
  return Category;
};

// models/service.js file
export default (sequelize, DataTypes) => {
  const Service = sequelize.define(
    "service",
    {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true
      },
      name: DataTypes.STRING,
      price: DataTypes.DECIMAL(10, 2),
      meta: {
        type: DataTypes.JSONB,
        allowNull: false
      }
    },
    {
      freezeTableName: true
    }
  );
  Service.associate = models => {
    Service.belongsTo(models.category);
  };
  return Service;
};

Generating schema and resolvers

//...
import { schema, resolvers } from "graphqlizejs";
import db from './models';

const schemaGenerated = schema(db.sequelize);
const resolversGenerated = resolvers(db.sequelize);


const server = new ApolloServer({
  typeDefs: gql(schemaGenerated),
  resolvers: resolversGenerated,
  context: { db },
  introspection: true,
  playground: true
});
....

Simple Queries

query GetCategory {
  categories {
    id
    name
  }
}

Simple Queries With Conditions

To add conditions in your queries you should use _inputWhere input generated for each model. This kind inputs will hold field model and input operators for the type defined.

query GetCategory($where: _inputWhereCategory) {
  categories(where: $where) {
    id
    name
  }
}

variable:
{
  "where": {"name": {"like": "%u%"}}
}

To avoid collisions names, graphqlizejs generate input names and counter association fields starting with an underscore character. Example: _associationsCount, _inputs.

Simple Count Queries

Each associate field defined in your model has your counter field called by underscore + association name + Count word.

In the example, below look for _servicesCount.

query GetCategory {
  categories {
    id
    name
    totalServices: _servicesCount
    serviceCountStartU: _servicesCount(where: {name: {like:"u%"}})
    services(where: {name:{like:"u%"}}) {
      id
      name
    }
  }
}

Association Queries

Retrieve all services by category:

query GetCategory {
  categories {
    id
    name
    services {
      id
      name
    }
  }
}

You also can filter your association's data as you did "Simple Queries With Conditions" example.

Association Count Queries

Each query also has your counter association field follow the same name definition: underscore + model name* + _Count* word.

query GetCategoryCount {
  renameCategoryCount: _categoriesCount
  _categoriesCount(where: {name:{like:"%u%"}})
}

Inputs Where

For each model, graphqlize will create a graphql input with all available model fields to be used in your conditions. You will see that, the fields defined in your input not use the model type, instead, it's used the type _input Type Operator_ that will hold all operators supported by the model type specified.

For instance country model, graphqlize will generate the _inputWhereCountry.

Inputs Operators

Sequelize ORM supports several query operators to allow filtered your data using findAll method. For this reason was create _inputTypeOperator.

Most of the types support the following operators:

eq
ne
gte
gt
lte
lt
not
is
in
notIn
between
notBetween

String type support the follow additional operators:

like
notLike
iLike
notILike
startsWith
endsWith
substring
regexp
notRegexp
iRegexp
notIRegexp
overlap
contains
contained
adjacent
strictLeft
strictRight

JSONB type support same operators found into String

in JSON type you can't query looking into the JSON struture, JSON as storage as String/Text, so you can use String operators

Inputs Create and Update

To able to mutate your data you will need to hold your data inside of the input mutation type. Graphqlizejs will generate the _inputCreate and _inputUpdate for each model and through models.

Input Create

Example of country model:

type _inputCreateCountry {
  name: String!
  callCode: String
  currencyCode: String
  createdAt: String
  updatedAt: String
}

Note that graphqlizejs didn't create the input with the primary keys. If you want to create or update your primary keys, enable graphqlizejs to create the input with the primary keys setting the model options with:

gqInputCreateWithPrimaryKeys: true

Input Update

type _inputUpdateCountry {
  name: String!
  callCode: String
  currencyCode: String
  createdAt: String
  updatedAt: String
}

Same way, if you want to enable update primary keys set the model option:

gqInputUpdateWithPrimaryKeys: true

Pagination handlers inside of input where type:

  • _limit: Int
  • _offset: Int
  • _orderBy: Array[Array]
  • _group: Array

orderBy

_orderBy argument accept a array with fieldName and direction. Ex: ['username', 'DESC']

Subscriptions

You can subscribe changes using graphqlizejs subscriptions generated for each mutation by setting:

gqSubscriptionCreate: true,
gqSubscriptionUpdate: true,
gqSubscriptionDelete: true

Example Subscription

subscription {
  updateCountry(where: { id: { eq: "PT" } }) {
    id
    name
    serviceCount: _servicesCount
  }
}
mutation {
  updateCountry(
    where: { id: { eq: "PT" } },
    input: { name: "Purtugaal" }
  ) {
    id
  }
}

Middlewares Resolvers

Middleware is the way to add some control over the model resolvers. You can add middlewares receiving the next resolver and returning the function with the same signature found in apollo server resolvers (root/parent, args, context, info) arguments.

Defining middleware:

function requireUser(nextResolver) {
  return (parent, args, context, info) => {
    if (!context.user)
      throw new AuthenticationError('Required valid authentication.');

    // you always should call the next resolver if you want to keep flow the resolvers.
    return nextResolver(parent, args, context, info);
  }
}

Using middleware in your models:

import flow from 'lodash.flow';
import {requireUser, onlyOwnData} from '../models/middlewares';

// models/service.js file
export default (sequelize, DataTypes) => {
  const Service = sequelize.define(
    "service",
    {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true
      },
      name: DataTypes.STRING,
      price: DataTypes.DECIMAL(10, 2)
    },
    {
      freezeTableName: true,
      gqMiddleware: {
        query: requireUser,
        queryCount: requireUser,
        create: flow([requireUser, onlyOwnData]),
        update: flow([requireUser, onlyOwnData]),
        destroy: flow([requireUser, onlyOwnData])
      }
    }
  );
  Service.associate = models => {
    Service.belongsTo(models.category);
  };
  return Service;
};

Complete example

https://github.com/stvkoch/example-graphqlizejs