Gathering detailed insights and metrics for graphql-sequelize
Gathering detailed insights and metrics for graphql-sequelize
Gathering detailed insights and metrics for graphql-sequelize
Gathering detailed insights and metrics for graphql-sequelize
@tira/tira-graphql-sequelize
packages/tira-graphql-sequelize
@prodigyems/graphql-sequelize
GraphQL & Relay for MySQL & Postgres via Sequelize
sequelize
Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift and Snowflake’s Data Cloud. It features solid transaction support, relations, eager and lazy loading, read replication and more.
sequelize-cli
The Sequelize CLI
npm install graphql-sequelize
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
1,898 Stars
545 Commits
172 Forks
36 Watching
99 Branches
67 Contributors
Updated on 22 Nov 2024
Minified
Minified + Gzipped
JavaScript (99.94%)
Dockerfile (0.06%)
Cumulative downloads
Total Downloads
Last day
40.8%
2,780
Compared to previous day
Last week
26.6%
12,849
Compared to previous week
Last month
-19.4%
47,953
Compared to previous month
Last year
21.7%
1,618,565
Compared to previous year
3
Should be used with dataloader-sequelize to avoid N+1 queries
$ npm install --save graphql-sequelize
graphql-sequelize assumes you have graphql and sequelize installed.
1import { resolver } from "graphql-sequelize"; 2 3resolver(SequelizeModel[, options]);
A helper for resolving graphql queries targeted at Sequelize models or associations. Please take a look at the tests to best get an idea of implementation.
The resolver
function takes a model as its first (required) argument, but also
has a second options object argument. The available options are:
1resolver(SequelizeModel, { 2 // Whether or not this should return a list. Defaults to whether or not the 3 // field type is an instance of `GraphQLList`. 4 list: false, 5 6 // Whether or not relay connections should be handled. Defaults to `true`. 7 handleConnection: true, 8 9 /** 10 * Manipulate the query before it's sent to Sequelize. 11 * @param findOptions {object} - Options sent to Seqeulize model's find function 12 * @param args {object} - The arguments from the incoming GraphQL query 13 * @param context {object} - Resolver context, see more at GraphQL docs below. 14 * @returns findOptions or promise that resolves with findOptions 15 */ 16 before: (findOptions, args, context) => { 17 findOptions.where = { /* Custom where arguments */ }; 18 return findOptions; 19 }, 20 /** 21 * Manipulate the Sequelize find results before it's sent back to the requester. 22 * @param result {object|array} - Result of the query, object or array depending on list or not. 23 * @param args {object} - The arguments from the incoming GraphQL query 24 * @param context {object} - Resolver context, see more at GraphQL docs below. 25 * @returns result(s) or promise that resolves with result(s) 26 */ 27 after: (result, args, context) => { 28 result.sort(/* Custom sort function */); 29 return result; 30 }, 31 32 /* 33 * Transfer fields from the graphql context to the options passed to model calls 34 * Inherits from global resolver.contextToOptions 35 */ 36 contextToOptions: { 37 a: 'a', 38 b: 'c' 39 } 40}); 41 42resolver.contextToOptions = {}; /* Set contextToOptions globally */
The args
and context
parameters are provided by GraphQL. More information
about those is available in their resolver docs.
1import {resolver} from 'graphql-sequelize';
2
3let User = sequelize.define('user', {
4 name: Sequelize.STRING
5});
6
7let Task = sequelize.define('task', {
8 title: Sequelize.STRING
9});
10
11User.Tasks = User.hasMany(Task, {as: 'tasks'});
12
13let taskType = new GraphQLObjectType({
14 name: 'Task',
15 description: 'A task',
16 fields: {
17 id: {
18 type: new GraphQLNonNull(GraphQLInt),
19 description: 'The id of the task.',
20 },
21 title: {
22 type: GraphQLString,
23 description: 'The title of the task.',
24 }
25 }
26});
27
28let userType = new GraphQLObjectType({
29 name: 'User',
30 description: 'A user',
31 fields: {
32 id: {
33 type: new GraphQLNonNull(GraphQLInt),
34 description: 'The id of the user.',
35 },
36 name: {
37 type: GraphQLString,
38 description: 'The name of the user.',
39 },
40 tasks: {
41 type: new GraphQLList(taskType),
42 resolve: resolver(User.Tasks)
43 }
44 }
45});
46
47let schema = new GraphQLSchema({
48 query: new GraphQLObjectType({
49 name: 'RootQueryType',
50 fields: {
51 // Field for retrieving a user by ID
52 user: {
53 type: userType,
54 // args will automatically be mapped to `where`
55 args: {
56 id: {
57 description: 'id of the user',
58 type: new GraphQLNonNull(GraphQLInt)
59 }
60 },
61 resolve: resolver(User)
62 },
63
64 // Field for searching for a user by name
65 userSearch: {
66 type: new GraphQLList(userType),
67 args: {
68 query: {
69 description: "Fuzzy-matched name of user",
70 type: new GraphQLNonNull(GraphQLString),
71 }
72 },
73 resolve: resolver(User, {
74 // Custom `where` clause that fuzzy-matches user's name and
75 // alphabetical sort by username
76 before: (findOptions, args) => {
77 findOptions.where = {
78 name: { "$like": `%${args.query}%` },
79 };
80 findOptions.order = [['name', 'ASC']];
81 return findOptions;
82 },
83 // Custom sort override for exact matches first
84 after: (results, args) => {
85 return results.sort((a, b) => {
86 if (a.name === args.query) {
87 return 1;
88 }
89 else if (b.name === args.query) {
90 return -1;
91 }
92
93 return 0;
94 });
95 }
96 })
97 }
98 }
99 })
100});
101
102let schema = new GraphQLSchema({
103 query: new GraphQLObjectType({
104 name: 'RootQueryType',
105 fields: {
106 users: {
107 // The resolver will use `findOne` or `findAll` depending on whether the field it's used in is a `GraphQLList` or not.
108 type: new GraphQLList(userType),
109 args: {
110 // An arg with the key limit will automatically be converted to a limit on the target
111 limit: {
112 type: GraphQLInt
113 },
114 // An arg with the key order will automatically be converted to a order on the target
115 order: {
116 type: GraphQLString
117 }
118 },
119 resolve: resolver(User)
120 }
121 }
122 })
123});
field helpers help you automatically define a models attributes as fields for a GraphQL object type.
1var Model = sequelize.define('User', {
2 email: {
3 type: Sequelize.STRING,
4 allowNull: false
5 },
6 firstName: {
7 type: Sequelize.STRING
8 },
9 lastName: {
10 type: Sequelize.STRING
11 }
12});
13
14import {attributeFields} from 'graphql-sequelize';
15
16attributeFields(Model, {
17 // ... options
18 exclude: Array, // array of model attributes to ignore - default: []
19 only: Array, // only generate definitions for these model attributes - default: null
20 globalId: Boolean, // return an relay global id field - default: false
21 map: Object, // rename fields - default: {}
22 allowNull: Boolean, // disable wrapping mandatory fields in `GraphQLNonNull` - default: false
23 commentToDescription: Boolean, // convert model comment to GraphQL description - default: false
24 cache: Object, // Cache enum types to prevent duplicate type name error - default: {}
25});
26
27/*
28{
29 id: {
30 type: new GraphQLNonNull(GraphQLInt)
31 },
32 email: {
33 type: new GraphQLNonNull(GraphQLString)
34 },
35 firstName: {
36 type: GraphQLString
37 },
38 lastName: {
39 type: GraphQLString
40 }
41}
42*/
43
44userType = new GraphQLObjectType({
45 name: 'User',
46 description: 'A user',
47 fields: Object.assign(attributeFields(Model), {
48 // ... extra fields
49 })
50});
attributeFields
uses the graphql-sequelize typeMapper
to map Sequelize types to GraphQL types. You can supply your own
mapping function to override this behavior using the mapType
export.
1var Model = sequelize.define('User', { 2 email: { 3 type: Sequelize.STRING, 4 allowNull: false 5 }, 6 isValid: { 7 type: Sequelize.BOOLEAN, 8 allowNull: false 9 } 10}); 11 12import {attributeFields,typeMapper} from 'graphql-sequelize'; 13typeMapper.mapType((type) => { 14 //map bools as strings 15 if (type instanceof Sequelize.BOOLEAN) { 16 return GraphQLString 17 } 18 //use default for everything else 19 return false 20}); 21 22//map fields 23attributeFields(Model); 24 25/* 26{ 27 id: { 28 type: new GraphQLNonNull(GraphQLInt) 29 }, 30 email: { 31 type: new GraphQLNonNull(GraphQLString) 32 }, 33 isValid: { 34 type: new GraphQLNonNull(GraphQLString) 35 }, 36} 37*/ 38
attributeFields accepts a map
option to customize the way the attribute fields are named. The map
option accepts
an object or a function that returns a string.
1 2var Model = sequelize.define('User', { 3 email: { 4 type: Sequelize.STRING, 5 allowNull: false 6 }, 7 firstName: { 8 type: Sequelize.STRING 9 }, 10 lastName: { 11 type: Sequelize.STRING 12 } 13}); 14 15attributeFields(Model, { 16 map:{ 17 email:"Email", 18 firstName:"FirstName", 19 lastName:"LastName" 20 } 21}); 22 23/* 24{ 25 id: { 26 type: new GraphQLNonNull(GraphQLInt) 27 }, 28 Email: { 29 type: new GraphQLNonNull(GraphQLString) 30 }, 31 FirstName: { 32 type: GraphQLString 33 }, 34 LastName: { 35 type: GraphQLString 36 } 37} 38*/ 39 40attributeFields(Model, { 41 map:(k) => k.toLowerCase() 42}); 43 44/* 45{ 46 id: { 47 type: new GraphQLNonNull(GraphQLInt) 48 }, 49 email: { 50 type: new GraphQLNonNull(GraphQLString) 51 }, 52 firstname: { 53 type: GraphQLString 54 }, 55 lastname: { 56 type: GraphQLString 57 } 58} 59*/ 60
GraphQL enum types only support ASCII alphanumeric characters, digits and underscores with leading non-digit.
If you have other characters, like a dash (-
) in your Sequelize enum types,
they will be converted to camelCase. If your enum value starts from a digit, it
will be prepended with an underscore.
For example:
foo-bar
becomes fooBar
25.8
becomes _258
If you have Sequelize.VIRTUAL
attributes on your sequelize model, you need to explicitly set the return type and any field dependencies via new Sequelize.VIRTUAL(returnType, [dependencies ... ])
.
For example, fullName
here will not always return valid data when queried via GraphQL:
1firstName: { type: Sequelize.STRING }, 2lastName: { type: Sequelize.STRING }, 3fullName: { 4 type: Sequelize.VIRTUAL, 5 get: function() { return `${this.firstName} ${this.lastName}`; }, 6},
To work properly fullName
needs to be more fully specified:
1firstName: { type: Sequelize.STRING }, 2lastName: { type: Sequelize.STRING }, 3fullName: { 4 type: new Sequelize.VIRTUAL(Sequelize.STRING, ['firstName', 'lastName']), 5 get: function() { return `${this.firstName} ${this.lastName}`; }, 6},
defaultArgs(Model)
will return an object containing an arg with a key and type matching your models primary key and
the "where" argument for passing complex query operations described here
1var Model = sequelize.define('User', { 2 3}); 4 5defaultArgs(Model); 6 7/* 8{ 9 id: { 10 type: new GraphQLNonNull(GraphQLInt) 11 } 12} 13*/ 14 15var Model = sequelize.define('Project', { 16 project_id: { 17 type: Sequelize.UUID 18 } 19}); 20 21defaultArgs(Model); 22 23/* 24{ 25 project_id: { 26 type: GraphQLString 27 }, 28 where: { 29 type: JSONType 30 } 31} 32*/
If you would like to pass "where" as a query variable - you should pass it as a JSON string and declare its type as SequelizeJSON:
/* with GraphiQL */
// request
query($where: SequelizeJSON) {
user(where: $where) {
name
}
}
// query variables
# JSON doesn't allow single quotes, so you need to use escaped double quotes in your JSON string
{
"where": "{\"name\": {\"like\": \"Henry%\"}}"
}
defaultListArgs
will return an object like:
1{ 2 limit: { 3 type: GraphQLInt 4 }, 5 order: { 6 type: GraphQLString 7 }, 8 where: { 9 type: JSONType 10 } 11}
Which when added to args will let the resolver automatically support limit and ordering in args for graphql queries.
Should be used with fields of type GraphQLList
.
1import {defaultListArgs} from 'graphql-sequelize' 2 3args: Object.assign(defaultListArgs(), { 4 // ... additional args 5})
order
expects a valid field name and will sort ASC
by default. For DESC
you would prepend reverse:
to the field name.
/* with GraphiQL */
// users represents a GraphQLList of type user
query($limit: Int, $order: String, $where: SequelizeJSON) {
users(limit: $limit, order: $order, where: $where) {
name
}
}
// query variables
{
"order": "name" // OR "reverse:name" for DESC
}
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 11/30 approved changesets -- score normalized to 3
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
93 existing vulnerabilities detected
Details
Score
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More