Git Product home page Git Product logo

almost-full-stack / graphcraft Goto Github PK

View Code? Open in Web Editor NEW
51.0 6.0 19.0 1.76 MB

Rapildy build and extend GraphQL API based on Sequelize models. This library helps you focus on business logic while taking care of GraphQL schema automatically.

Home Page: https://almost-full-stack.github.io/graphcraft/

License: MIT License

JavaScript 100.00%
sequelize-graphql-schema sequelize-models sequelize graphql-js graphql microservices serverless sequelize-model

graphcraft's People

Contributors

alirizwan avatar antiavanti avatar dependabot[bot] avatar emanuelet avatar jjcollinge avatar nek97 avatar nephti57 avatar yehonal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

graphcraft's Issues

Support for destroy bulk action

Hey, thanks for the package

Model options 'create' and 'edit' work great for bulk, but 'destroy' doesn't (even thought it is in examples), I also analyzed code and looks like there is no support for it at all?

Thanks

Bulk Update

Just a quick question, I've found the ability to allow for bulk mutations to be exposed.

I've exposed both Create and Update.

However I've tried the Bulk Update and it seems to be trying to run a delete on the table rather than an update?

Many thanks,

Lewis

Float support

Hi - thanks for the package, very helpful!

Is there a particular reason why the graphql scalar Float is not supported? Currently DECIMALs, DOUBLEs etc. are treated as strings.

Update graphql dependency to 14.1.1

I think it would be good to upgrade to the last version of graphql so that people can use all the latest features. Moreover, I'm forced to keep the version back on my package.json as well to avoid breaking the library

Custom attributes and resolvers

I'm trying to add a custom attribute to my model with a custom resolver to be able to calculate the value based on the record data.

Can you advise how I can do it? So far I've been able to add the field but I'm not able to connect the resolver correctly (or I don't know if even that's possible)

This is one of the things I've tried:

hotels.graphql = {
    attributes: {
      include: { key: 'string', lead_image: 'string' },
    },
    extend: {
      fetch: (data, source, args, context, info) => {
        data.lead_image = 'Added by extension.'
  
        return data
      },
    },
  }

Thank for any help

useCLS error

Wondering what the model files are supposed to look like. I've already defined models and resolvers and also have built my own schemas as well, but wanted to see if this gave more functionality. However, I'm bumping into an issue where it seems like it doesn't like the models I've built. I do have the dependencies sequelize and graphql installed.

Make context available to Sequelize hooks?

Could the context be passed through to Sequelize hooks through options?

In our authorizer function we attach the current user to ctx and use that for logging and related activity through a request's lifecycle. We can use graphql.before.create/update to achieve this, but that only applies to the graphql request and not any subsequent Sequelize model work.

cannot read property 'useCLS' of undefined

I was really hoping this would work, but I'm having some problems...

The error:

  Models.Sequelize.useCLS(sequelizeNamespace);
                   ^

TypeError: Cannot read property 'useCLS' of undefined
    at generateSchema (C:\Users\Funshine\Desktop\webjav\socialpirates\backend\
node_modules\sequelize-graphql-schema\dist\sequelize-graphql-schema.js:870:20)
    at Function.module.exports (C:\Users\Funshine\Desktop\webjav\socialpirates
\backend\src\middleware\index.js:50:31)
    at Function.configure (C:\Users\Funshine\Desktop\webjav\socialpirates\back
end\node_modules\@feathersjs\feathers\lib\application.js:59:8)
    at Object.<anonymous> (C:\Users\Funshine\Desktop\webjav\socialpirates\back
end\src\app.js:61:5)
    at Module._compile (internal/modules/cjs/loader.js:799:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:810:10)
    at Module.load (internal/modules/cjs/loader.js:666:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:606:12)
    at Function.Module._load (internal/modules/cjs/loader.js:598:3)
    at Module.require (internal/modules/cjs/loader.js:705:19)
    at require (internal/modules/cjs/helpers.js:14:16)
    at Object.<anonymous> (C:\Users\Funshine\Desktop\webjav\socialpirates\back
end\src\index.js:3:13)
    at Module._compile (internal/modules/cjs/loader.js:799:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:810:10)
    at Module.load (internal/modules/cjs/loader.js:666:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:606:12)
    at Function.Module._load (internal/modules/cjs/loader.js:598:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:862:12)
    at internal/main/run_main_module.js:21:11

my middleware where I'm sticking it in:

  const { GraphQLSchema } = require('graphql');
  const graphqlHTTP = require('express-graphql');

  var options = {
    exclude: ["Users"]
  }

  const {generateSchema} = require('sequelize-graphql-schema')(options);
const models = require( process.cwd() + '\\src\\models\\activity.js');
app.use(
  '/graphql',
  graphqlHTTP({
    schema: new GraphQLSchema(generateSchema(models)),
    graphiql: true
  })
)

One example of models named activity.js

module.exports = function(sequelize, DataTypes) {
	return sequelize.define('activity', {
		activityID: {
			type: DataTypes.INTEGER,
			allowNull: false,
			primaryKey: true,
			autoIncrement: true
		},
		belongsTo: {
			type: DataTypes.INTEGER,
			allowNull: false,
			references: {
				model: 'users',
				key: 'id'
			},
			unique: true
		},
		profileID: {
			type: DataTypes.INTEGER,
			allowNull: true,
			references: {
				model: 'profile',
				key: 'profileID'
			}
		}
	}, {
		tableName: 'activity'
	});
};

Custom nested type is assumed to be Sequelize model, query overrides requested return values

Given these custom GraphQL types that are generated dynamically in my resolver:

Widget.graphql.types.order = {
    number: 'string!',
    jobs: '[orderJob]'
};

Widget.graphql.types.orderJob = {
    type: 'string!',
};

I receive the following error when I attempt to query for a job:

Cannot query field "jobs" on type "order".

It seems that it assumed jobs is a Sequelize association and tries to handle it that way. Is that correct? How can I handle nested custom types?

Thanks for any info you can share.

`belongsToMany` associations have undefined output type

I've run into an issue regarding belongsToMany relationships. It seems that a type is not generated when there is a join table. This is causing graphcraft to not function using graphql and graphql-http (specifically the express library).

For example:

This is the error: The type of Workorder.WorkorderParts must be Output Type but got: undefined.

We have a Workorder model, a Parts model and a join table, WorkorderParts.

Can anyone provide any guidance as to why this is happening? Is this a known issue or am I just doing something incorrectly?

Thanks in advance.

1.0.0-beta.17 questions

Hi guys,

I was testing version 1.0.0-beta.17 to see the new funcionalitys and two points came up:

  • Querys and Mutations names pattern changed. In the stable version a Sequelize model "ws_export" becames "wsExportGet" and now is "WsExport". Is this new pattern that will be adopted? Is there any way to make an alias and rewrite to the previous pattern? Cause I have a few projects calling my graphql endpoint and rewrite them to use the new pattern will be caotic.

  • The resetCache function stop working. Is this normal?

Thanks!

Excluding attributes

Hi - thanks for the package, very helpful!

It doesn't seem like the model.attributes.exclude option is implemented? Is there another way to exclude an attribute from a graphql type?

Does not work with ApolloServer

new ApolloServer({ typeDefs }); takes this typeDefs object. Which expects a definitions property.

However when doing

const { ApolloServer } = require('apollo-server-koa');
const { GraphQLSchema } = require('graphql');
const db = require('./models');
const typeDefs = new GraphQLSchema(generateSchema(db))
const server = new ApolloServer({ typeDefs, resolvers);

We get TypeError: Cannot read property 'some' of undefined in apollo-server-core/src/utils/isDirectiveDefined.ts:16:32 Which is this line

typeDef.definitions.some

It seems the schema generated by this, doesn't have what normally is present when doing a simple require('./schema);

Subscriptions - example.

Hi Mr Ali Rizwan,

Could you please create some example of how to use Subscription?

{mySubs: { output: '[myType]', resolver: customResolver, subscriber: customSubscriber }}

Especially how to build a subscriber from the documentation example above. Many other examples are in the tests in the repo, unfortunately I could not find subscription examples.

Thank you!

Example of how to use "join" option?

We're on 1.0.0-beta.11. I'm trying to require inner joins on some queries to limit the result set. It looks like #34 covers it. Is that the case? If so, how can I use an inner join in my query? For example:

{
  Design (
    where: {
      customerId: 2635
    }
  ) {
    id
    name
    DesignLocations {
      location
    }
  }
}

we'd like to limit the result set with an inner join. Actually, we have a 3rd level of relation that we'd like to require as well if that doesn't overcomplicate things.

SQL Where conditions in Edit mutation

Hi guys,

I can't find anyway to pass a where condition in the auto generated edit mutation. The documentation only shows a input type argument, where I belive is for the fields I wanna change, but how to do this operation only on the rows I want to?

Thanks!

Trying to import remote schema appears to remove local one

I'm trying to import the GraphQL schema from another micro-service that I have to create an association with a model.
When I try to set it up though in the main options, the change removes all the local sequelize models from the GraphQL schema.

var options = {
  remote: {
    import: {
      RemoteData: {
        endpoint: 'http://localhost:3000/graphql',
        queries: { cardPaymentGet: { as: 'CardPaymentQuery' } },
      },
    },
  },
}

const { generateSchema } = require('sequelize-graphql-schema')(options)

Am I doing something wrong?


Screenshot_2019-09-06 Playground - http manuzbook 4000 graphql
Screenshot_2019-09-06 Playground - http manuzbook 4000 graphql(1)

attributes: exclude is never used

attributes -> exclude option from README is declared but never used, so the feature is not implemented

i'm going to fix it, PR soon

Understanding the `before` options (specifically for authorization layer)

First – thanks for this library. Really moving quickly with it, and have the start of an elegant new codebase for our API. Our structure for models and custom mutations/queries is very clean and easy to extend, and we get the power of Sequelize at the persistence layer.

We're trying to implement authorization at the most appropriate layer. We already have authentication handled up front (directly in a Koa middleware function, not via authorizer although I'm curious if there's any benefit there), and the current user + role is available to all queries/mutations via context. We've looked into graphql-shield and directives, but it seems that those routes may get us bloated rather quickly, and we'd like to start very small and focused.

It seems like attaching permission definitions to our models via the .graphql property and using before:* to check the current context + action could be a good way to go, but I'm new to GraphQL and don't understand what the before options of "create, fetch, destroy and update" are. Who determines what queries fall into these categories, or are these Sequelize hooks? What categories do my custom mutations and queries fall into?

If you've got a better recommendation, we'd love to hear it. Thanks.

How can I rename the mutations and querys that are generated by default?

due to internal policies, my tables have an unusual name. I want to rename the queries and mutations that are generated automatically. because it is simpler to rename them or use an alias than to have to create them again.

image

Someone will have some idea. I don't think it's an Issue but there is a lack of documentation that addresses these particularities

Support for nested queries

Hello! I was using (and fixing) a similar project called graphql-sequelize-crud, but it doesn't support creation with association, only select queries.

What about this project instead? Can i run a single mutation to create a db instance and it's association within the same call?

Can i do the same with queries?

Support custom documentation on models and fields

First of all: thank you for your efforts in keeping this project alive 👍

I'm having more a question than an issue - do you have any plans to support customized documentation on models and/or model fields? Thinking in the direction of

const MyModel = orm.db.define('my_model', {
    id: {
        type: Sequelize.INTEGER,
        autoIncrement: true,
        primaryKey: true,
        description: "My very custom description of this field" // <- use this in the field's GraphQLType
    },
    anotherField: {
        type: Sequelize.STRING,
        description: "Another an even weirder description, maybe with an example value in markdown `FOO` or `bar_123`" // <- use this in the field's GraphQLType
    }
}, 
{
    description: "The MyModel type represents my model and I really want to tell you something about it." // <- use this in the model's GraphQLType
})

or - if adding custom fields to the model itself is not so desirable - for example

const MyModel.graphql = {
    modelDescription: "...",
    fieldDescriptions: {
        id: ""
    }
}

or maybe (also) supporting converting comments from DB fields to descriptions, like already being supported in graphql-sequelize.

I'd be happy to contribute, let me know what you think.

Cheers!

Readme error

Hi - thanks for the package, very helpful!

Documentation for the excludeQueries property gives the example [ 'fetch' ], however, according to the code this should be [ 'query' ].

How can I deny a request with authorizer()?

I am trying to follow this example, but I want to deny requests. i thought i could place
return Promise.resolve(false);
and that the petition would be denied, however it is still executed.

const options = {
  exclude: ["payments"],
  authorizer: function authorizer(source, args, context, info) {
    const { fieldName } = info; // resource name
 
    return Promise.resolve();
  }
};
 
const { generateSchema } = require("graphcraft")(options);

Any idea how a petition can be denied?
Thank you!

Expose graphql-sequelize hooks to modify findOptions

Currently I'm trying to use a graphcraft model hook to apply an additional operation to the WHERE clause of a fetch. However, because the additional operation needs to be expressed as a Sequelize Literal query it gets mangled in the argsToFindOptions function of graphql-sequelize which stops it working. Would you be open to me adding a way to provide hooks that are directly added as graphql-sequelize hooks rather than invoked beforehand so that I can modify the findOptions directly.

How to keep associations in pascalCase?

I have many associations that instead of having the same naming as my classes type definitions, get a underscored case (just like the file name) so I end up with Products and products or SomethingElse and something_else (when associated).

Is there a way to keep everything with pascalCase?. Thanks!

Creating association records via single mutation

Hi,

This is not an "issue question" but more likely a "how to", hehe.

I was reading the closed issues and saw this one (#4)

So, it is possible to create, within a single mutation, related rows in the db, like creating a new user and a new post associated to that user, right?

If so, what do I need to do with my sequelize models or with the config of this lib to get this working?

Thanks!

inquiry: Possibility of selected sql fields

I'm currently exploring graphql and stumbled upon this project, and it's a great tool for my current project. I noticed though that by default, the execution of the select command fetches all columns. Would it be possible to have a feature to only select fields that were included in the original graphql query? Thanks!

custom mutations with multiple arguments?

I tried many things but can't figure out how to make it work, I need some custom mutations that take multiple arguments and so far I understand I pass input, output and resolver but input won't work if I pass an array or anything really other than a plain string

Exclude column from mutations

Wondering if there is a way/ any thoughts on allow exclusions for specific columns on mutations.

I've tied my model to a view for ease of accessing key information from other tables and would still like to be able
for the mutation to update the base table, but excluding specific columns in the the update.

For example

      jobId: {
        autoIncrement: true,
        type: DataTypes.INTEGER,
        allowNull: false,
        primaryKey: true,
      },
      guid: {
        type: DataTypes.UUID,
        allowNull: false,
        defaultValue: sequelize.fn('newid'),
      },
      buildingName: {
        type: DataTypes.STRING(50),
        allowNull: true,
     },
     description: {
        type: DataTypes.STRING(4000),
        allowNull: false,
      },

In the above model buildingName doesn't exist on the source table but does exist in the view the model is referencing.
When I'm allowing the user to mutate the model, it would be great if I could note that the buildingName is excluded from mutations and therefore won't be included in any auto-generated update statement.

so instead of it generating

insert into dbo.tJobs
(guid, buildingName, description)
VALUES( @1, @2, @3)

it would run

insert into dbo.tJobs
(guid, description)
VALUES( @1,  @3)

as building name has been excluded from mutations.

Which would prevent the error I'm receiving on create mutations

"message": "The column reference "inserted.discipline" is not allowed because it refers to a base table that is not being modified in this statement."

Let me know your thoughts, or even if this is possible without creating a whole new custom mutation?

Thanks

Multiple joins skip relations (data missing)

Query without joins runs fine (super slow tho, hundreds of queries run sequentially):
image
And with a join it simply ignores that find for some reason and ends up not returning data for that node:
image

Note that the first join at the category level is working as expected, a single query returns all the categories + products. I wan't the same for all the product options in a product but it just works by running 1:N queries. Any idea what I'm doing wrong?

n:m queries are not correctly handled

Currently you can query a model associated with another with n:m, but if you need some field that are directly added in "through" model you are not able to retrieve them in any way.

for example if we have model Recipe associated with Ingredients via "RecipeIngredients" relational model that contains the quantity for each Recipe, you cannot access to the quantity field via a query.

It's a critical issue

Error with ENUM fields

In my sequelize schema I have a couple of enum fields (the database is Postgres).

If I don't exclude the corresponding models I receive this error:

Error: Schema must contain unique named types but contains multiple types named "UserroleEnumType".
    at invariant (/home/emanuele/Projects/flightsuit_backend/node_modules/graphql/jsutils/invariant.js:19:11)
    at typeMapReducer (/home/emanuele/Projects/flightsuit_backend/node_modules/graphql/type/schema.js:252:57)
    at typeMapReducer (/home/emanuele/Projects/flightsuit_backend/node_modules/graphql/type/schema.js:309:22)
    at typeMapReducer (/home/emanuele/Projects/flightsuit_backend/node_modules/graphql/type/schema.js:309:22)
    at Array.reduce (<anonymous>)
    at typeMapReducer (/home/emanuele/Projects/flightsuit_backend/node_modules/graphql/type/schema.js:280:38)
    at Array.reduce (<anonymous>)
    at new GraphQLSchema (/home/emanuele/Projects/flightsuit_backend/node_modules/graphql/type/schema.js:125:28)
    at Object.<anonymous> (/home/emanuele/Projects/flightsuit_backend/app.js:227:13)
    at Module._compile (internal/modules/cjs/loader.js:688:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
    at Module.load (internal/modules/cjs/loader.js:598:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
    at Function.Module._load (internal/modules/cjs/loader.js:529:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
    at startup (internal/bootstrap/node.js:285:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3)

Has someone encountered a similar issue?

Error when closing database connection using dataloader with model associations

Hi there!

First of all: thanks for this amazing project and sorry for any english mistake in advance, :)

I'm developing a Grapqhl project in AWS Lambda and, because of the nature of serverless environment, it's necessaire to close and redo the connection between requests.

All works fine if I hit just only one model per request, but, if I try to take advantage of model associations, my application breaks in the second request with the following message:

"ConnectionManager.getConnection was called after the connection manager was closed!"

As you can see in the images below, the first request works flawless but the second one throwns the error after selecting the first table.

First request:
image

Second request:
image

Query log:
image

Here is my lambda handler:

const { ApolloServer } = require('apollo-server-lambda');
const { GraphQLSchema } = require('graphql');
const { generateSchema } = require('sequelize-graphql-schema')({
    dataloader: true
});

const Db = require('../../models/autologpod');

const buildGraphQlContext = ({ context, event }) => ({
    headers: event.headers,
    functionName: context.functionName,
    event,
    context
});

const runHandler = (event, context, handler) =>
    new Promise((resolve, reject) => {
        const callback = (error, body) => (error ? reject(error) : resolve(body));

        handler(event, context, callback);
    }
);

const run = async (event, context) => {    
    let autologpod = await new Db(event.pathParameters.account_id);

    const server = new ApolloServer({
        schema: new GraphQLSchema(await generateSchema(autologpod.db)),
        context: buildGraphQlContext,
    });

    const handler = server.createHandler({ cors: { credentials: true, origin: '*' } });
    const response = await runHandler(event, context, handler);
    
    await autologpod.close();

    return response;
};

exports.graphqlHandler = run;

If I remove the dataloader option, the error is gone. Can any one help me or point a direction? Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.