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

sequelize-graphql-cruder

v1.0.2

Published

Generate GraphQL Schema and CRUD operations from Sequelize models

Downloads

9

Readme

Sequelize GraphQL Cruder

npm npm NPM

Automatically generate GraphQL schema and CRUD operations from Sequelize models

Install

Install using NPM.

npm i sequelize-graphql-cruder

Or clone the repository

git clone https://github.com/SalahBelila/sequelize-graphql-cruder.git

Features

  • [x] Simple and easy to use
  • [x] Does not depend on any package
  • [x] Generates the schema and resolvers for you in the form of JS modules
  • [x] Handles Sequelize associations automatically
  • [x] Generates custom scalars when needed

Usage

The package exposes the function codeGen which allows you to generate the schema and resolvers from the seqeulize models.
The codeGen function takes two parameters (required), sequelize models and the schema directory respectively.

const sequelizeModels = require('./models');
const { codeGen } = require('sequelize-graphql-cruder');

const SCHEMA_DIR = './schema';
codeGen(sequelizeModels, SCHEMA_DIR);

After the schema is generated you can import it into your project in the following manner:

const {schema, resolvers, customScalars} = require('./schema');

A Simple Server Example

const { plugCustomScalars } = require('sequelize-graphql-cruder');
const { Sequelize } = require('sequelize');
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');
const sequelizeModels = require('./models');
const sequelizeConfig = require('./sequelize_config');
const { schema, resolvers, customScalars } = require('./schema');

// Build the schema.
const executableSchema = buildSchema(schema);
// Add the generated custom scalars to schema type mapper.
plugCustomScalars(executableSchema, customScalars);

const sequelize = new Sequelize(sequelizeConfig);

const app = express();
// the models and the sequelize instance must provided to the resolvers through the context;
app.use('/graphql', graphqlHTTP({
    schema: executableSchema,
    context: {
        models: sequelizeModels,
        sequelize
    },
    rootValue: resolvers,
    graphiql: true
}));

app.listen(5000, () => console.log("The Server is Running..."));

Generated Files

The generated schema is split into several JS modules, each module corresponds to a data model providing the schema Typedefs and resolvers of that model.

Schema

The Schema generated by the package is totally infered from the given sequelize models. As mentioned before, each model has its corresponding JS module that exposes two objects, one of which is the schema object. A schema object may look like this:

const schema = {
	typeDefs: `
		type Author {
			id: Int
			name: String
			bio: String
			books: [Book!]
		}
		input AuthorInput {
			id: Int
			name: String
			bio: String
		}
	`,

	Query: `
		authorGet(id: Int, name: String, bio: String): [Author!]
	`,

	Mutation: `
		authorAdd(id: Int, name: String, bio: String): Author
		authorUpdate(searchInput: AuthorInput, updateInput: AuthorInput): Int
		authorDelete(id: Int, name: String, bio: String): Int
	`
}

The above schema object has three properties typeDefs, Query and Mutation. You may have noticed that this follows the same logic of GraphQL, meaning that you can add a third proprety Subscription.
All properties are optional.
All properties must follow GraphQL schema definition language syntax

This is what the above schema object would look like in GraphQL SDL:

type Author {
    id: Int
    name: String
    bio: String
    books: [Book!]
}

input AuthorInput {
    id: Int
    name: String
    bio: String
}

type Query {
    authorGet(id: Int, name: String, bio: String): [Author!]
}

type Mutation {
    authorAdd(id: Int, name: String, bio: String): Author
    authorUpdate(searchInput: AuthorInput, updateInput: AuthorInput): Int
    authorDelete(id: Int, name: String, bio: String): Int
}

Resolvers

The resolvers are exposed in each JS module as mentioned before. The exposed Resolvers are merely an object with four methods, each method represents a CRUD operation. This is how a resolvers object looks:

const resolvers = {
	authorAdd: async (args, { models, sequelize }) => {
		const transaction = await sequelize.transaction();
		try {
			const result = await models.Author.create(args, {transaction});
			await transaction.commit();
			return result;
		} catch { await transaction.rollback(); }
	},

	authorGet: async (args, { models, sequelize }) => {
		const transaction = await sequelize.transaction();
		try {
			const result = await models.Author.findAll({ where: args, transaction });
			await transaction.commit();
			return result;
		} catch { await transaction.rollback(); }
	},

	authorUpdate: async (args, { models, sequelize }) => {
		const transaction = await sequelize.transaction();
		try {
			const result = await models.Author.update
			(
				args.updateInput,
				{ where: args.searchInput, transaction }
			);
			await transaction.commit();
			return result[0];
		} catch { await transaction.rollback(); }
	},

	authorDelete: async (args, { models, sequelize }) => {
		const transaction = await sequelize.transaction();
		try {
			const result = await models.Author.destroy({where: args, transaction});
			await transaction.commit();
			return result;
		} catch { await transaction.rollback(); }
	}
}

Notice that the context parameter must contain the models and the sequelize instance

Custom Scalars

Requiring the generated schema yields an object with three properties schema, resolvers and customScalars. We discussed above the schema and resolvers and now it is time to talk about customScalars.
customScalars is just a list containing the names of all custom scalars used in the schema. This list can be passed to the plugCustomScalars function which is responsible for adding the custom scalars to the built schema type map.

const { plugCustomScalars } = require('sequelize-graphql-cruder');
const { schema, resolvers, customScalars } = require('./schema');

// Build the schema.
const executableSchema = buildSchema(schema);
// Add the generated custom scalars to schema type mapper.
plugCustomScalars(executableSchema, customScalars);

Alternatively you can add the mapping manually using your own Custom Scalar objects.
If the schema does not use any custom scalars customScalars will be an empty array

The table below shows all provided custom scalars and the corresponding Seqeulize data types:

|Custom Scalar | Sequelize data type| |:-------------:|:--------:| |Date | DATE DATEONLY| |Time | TIME|
|Numeric | NUMERIC DECIMAL DOUBLE DOUBLE PRECISION| |BigInt | BIGINT|
Note: if a mapping could not be found for a Sequelize data type, the string scalar will be used.

Sequelize Associations

Sequelize implements the three types of associations (one-to-one, one-to-many, many-to-many) through four methods of the Model class: belongsTo, hasOne, hasMany and belongsToMany. Sequelize GraphQL Cruder takes these associations into consideration when generating the schema. The table below describes how Sequelize GraphQL Cruder behaves when it finds any of the aforementionned associations defined on a model:
|Association| Cruder Behaviour | |:---------:|:----------------:| |BelongsTo| Cruder will generate a field of the same type of the referenced Object (replaces the FK reference).| |HasMany | Cruder will generate a field of type list, each element of the list is of the same type of the referenced Object.| |HasOne | Not supported yet, Cruder will generate the fields as they are in the model.| |BelongsToMany| Not supported yet, Cruder will generate the fields as they are in the model.|