{"id":13454256,"url":"https://github.com/mickhansen/graphql-sequelize","last_synced_at":"2025-04-11T04:22:59.092Z","repository":{"id":31478885,"uuid":"35042996","full_name":"mickhansen/graphql-sequelize","owner":"mickhansen","description":"GraphQL \u0026 Relay for MySQL \u0026 Postgres via Sequelize","archived":false,"fork":false,"pushed_at":"2022-11-16T09:28:09.000Z","size":698,"stargazers_count":1897,"open_issues_count":0,"forks_count":163,"subscribers_count":36,"default_branch":"master","last_synced_at":"2025-04-09T06:01:49.374Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mickhansen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-04T15:31:41.000Z","updated_at":"2025-04-03T15:21:00.000Z","dependencies_parsed_at":"2022-09-09T12:41:41.907Z","dependency_job_id":null,"html_url":"https://github.com/mickhansen/graphql-sequelize","commit_stats":null,"previous_names":[],"tags_count":147,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mickhansen%2Fgraphql-sequelize","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mickhansen%2Fgraphql-sequelize/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mickhansen%2Fgraphql-sequelize/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mickhansen%2Fgraphql-sequelize/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mickhansen","download_url":"https://codeload.github.com/mickhansen/graphql-sequelize/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248333607,"owners_count":21086199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T08:00:52.292Z","updated_at":"2025-04-11T04:22:59.060Z","avatar_url":"https://github.com/mickhansen.png","language":"JavaScript","readme":"# graphql-sequelize\n\n[![NPM](https://img.shields.io/npm/v/graphql-sequelize.svg)](https://www.npmjs.com/package/graphql-sequelize)\n[![Build Status](https://travis-ci.org/mickhansen/graphql-sequelize.svg?branch=master)](https://travis-ci.org/mickhansen/graphql-sequelize)\n[![Slack](http://sequelize-slack.herokuapp.com/badge.svg)](http://sequelize-slack.herokuapp.com)\n[![Coverage](https://codecov.io/gh/mickhansen/graphql-sequelize/branch/master/graph/badge.svg)](https://codecov.io/gh/mickhansen/graphql-sequelize)\n\nShould be used with [dataloader-sequelize](https://github.com/mickhansen/dataloader-sequelize) to avoid N+1 queries\n\n- [Installation](#installation)\n- [Resolve helpers](#resolve-helpers)\n- [field helpers](#field-helpers)\n- [args helpers](#args-helpers)\n\n## Installation\n\n`$ npm install --save graphql-sequelize`\n\ngraphql-sequelize assumes you have graphql and sequelize installed.\n\n## Resolve helpers\n\n```js\nimport { resolver } from \"graphql-sequelize\";\n\nresolver(SequelizeModel[, options]);\n```\n\nA helper for resolving graphql queries targeted at Sequelize models or associations.\nPlease take a look at [the tests](https://github.com/mickhansen/graphql-sequelize/blob/master/test/integration/resolver.test.js) to best get an idea of implementation.\n\n### Features\n\n- Automatically converts args to where if arg keys matches model attributes\n- Automatically converts an arg named 'limit' to a sequelize limit\n- Automatically converts an arg named 'order' to a sequelize order\n\n### Relay \u0026 Connections\n\n[Relay documentation](docs/relay.md)\n\n### Options\n\nThe `resolver` function takes a model as its first (required) argument, but also\nhas a second options object argument. The available options are:\n\n```js\nresolver(SequelizeModel, {\n  // Whether or not this should return a list. Defaults to whether or not the\n  // field type is an instance of `GraphQLList`.\n  list: false,\n\n  // Whether or not relay connections should be handled. Defaults to `true`.\n  handleConnection: true,\n\n  /**\n   * Manipulate the query before it's sent to Sequelize.\n   * @param findOptions {object} - Options sent to Seqeulize model's find function\n   * @param args {object} - The arguments from the incoming GraphQL query\n   * @param context {object} - Resolver context, see more at GraphQL docs below.\n   * @returns findOptions or promise that resolves with findOptions\n   */\n  before: (findOptions, args, context) =\u003e {\n    findOptions.where = { /* Custom where arguments */ };\n    return findOptions;\n  },\n  /**\n   * Manipulate the Sequelize find results before it's sent back to the requester.\n   * @param result {object|array} - Result of the query, object or array depending on list or not.\n   * @param args {object} - The arguments from the incoming GraphQL query\n   * @param context {object} - Resolver context, see more at GraphQL docs below.\n   * @returns result(s) or promise that resolves with result(s)\n   */\n  after: (result, args, context) =\u003e {\n    result.sort(/* Custom sort function */);\n    return result;\n  },\n\n  /*\n   * Transfer fields from the graphql context to the options passed to model calls\n   * Inherits from global resolver.contextToOptions\n   */\n  contextToOptions: {\n    a: 'a',\n    b: 'c'\n  }\n});\n\nresolver.contextToOptions = {}; /* Set contextToOptions globally */\n```\n\n_The `args` and `context` parameters are provided by GraphQL. More information\nabout those is available in their [resolver docs](http://graphql.org/learn/execution/#root-fields-resolvers)._\n\n### Examples\n\n```js\nimport {resolver} from 'graphql-sequelize';\n\nlet User = sequelize.define('user', {\n  name: Sequelize.STRING\n});\n\nlet Task = sequelize.define('task', {\n  title: Sequelize.STRING\n});\n\nUser.Tasks = User.hasMany(Task, {as: 'tasks'});\n\nlet taskType = new GraphQLObjectType({\n  name: 'Task',\n  description: 'A task',\n  fields: {\n    id: {\n      type: new GraphQLNonNull(GraphQLInt),\n      description: 'The id of the task.',\n    },\n    title: {\n      type: GraphQLString,\n      description: 'The title of the task.',\n    }\n  }\n});\n\nlet userType = new GraphQLObjectType({\n  name: 'User',\n  description: 'A user',\n  fields: {\n    id: {\n      type: new GraphQLNonNull(GraphQLInt),\n      description: 'The id of the user.',\n    },\n    name: {\n      type: GraphQLString,\n      description: 'The name of the user.',\n    },\n    tasks: {\n      type: new GraphQLList(taskType),\n      resolve: resolver(User.Tasks)\n    }\n  }\n});\n\nlet schema = new GraphQLSchema({\n  query: new GraphQLObjectType({\n    name: 'RootQueryType',\n    fields: {\n      // Field for retrieving a user by ID\n      user: {\n        type: userType,\n        // args will automatically be mapped to `where`\n        args: {\n          id: {\n            description: 'id of the user',\n            type: new GraphQLNonNull(GraphQLInt)\n          }\n        },\n        resolve: resolver(User)\n      },\n\n      // Field for searching for a user by name\n      userSearch: {\n        type: new GraphQLList(userType),\n        args: {\n          query: {\n            description: \"Fuzzy-matched name of user\",\n            type: new GraphQLNonNull(GraphQLString),\n          }\n        },\n        resolve: resolver(User, {\n          // Custom `where` clause that fuzzy-matches user's name and\n          // alphabetical sort by username\n          before: (findOptions, args) =\u003e {\n            findOptions.where = {\n              name: { \"$like\": `%${args.query}%` },\n            };\n            findOptions.order = [['name', 'ASC']];\n            return findOptions;\n          },\n          // Custom sort override for exact matches first\n          after: (results, args) =\u003e {\n            return results.sort((a, b) =\u003e {\n              if (a.name === args.query) {\n                return 1;\n              }\n              else if (b.name === args.query) {\n                return -1;\n              }\n\n              return 0;\n            });\n          }\n        })\n      }\n    }\n  })\n});\n\nlet schema = new GraphQLSchema({\n  query: new GraphQLObjectType({\n    name: 'RootQueryType',\n    fields: {\n      users: {\n        // The resolver will use `findOne` or `findAll` depending on whether the field it's used in is a `GraphQLList` or not.\n        type: new GraphQLList(userType),\n        args: {\n          // An arg with the key limit will automatically be converted to a limit on the target\n          limit: {\n            type: GraphQLInt\n          },\n          // An arg with the key order will automatically be converted to a order on the target\n          order: {\n            type: GraphQLString\n          }\n        },\n        resolve: resolver(User)\n      }\n    }\n  })\n});\n```\n\n## field helpers\n\nfield helpers help you automatically define a models attributes as fields for a GraphQL object type.\n\n```js\nvar Model = sequelize.define('User', {\n  email: {\n    type: Sequelize.STRING,\n    allowNull: false\n  },\n  firstName: {\n    type: Sequelize.STRING\n  },\n  lastName: {\n    type: Sequelize.STRING\n  }\n});\n\nimport {attributeFields} from 'graphql-sequelize';\n\nattributeFields(Model, {\n  // ... options\n  exclude: Array, // array of model attributes to ignore - default: []\n  only: Array, // only generate definitions for these model attributes - default: null\n  globalId: Boolean, // return an relay global id field - default: false\n  map: Object, // rename fields - default: {}\n  allowNull: Boolean, // disable wrapping mandatory fields in `GraphQLNonNull` - default: false\n  commentToDescription: Boolean, // convert model comment to GraphQL description - default: false\n  cache: Object, // Cache enum types to prevent duplicate type name error - default: {}\n});\n\n/*\n{\n  id: {\n    type: new GraphQLNonNull(GraphQLInt)\n  },\n  email: {\n    type: new GraphQLNonNull(GraphQLString)\n  },\n  firstName: {\n    type: GraphQLString\n  },\n  lastName: {\n    type: GraphQLString\n  }\n}\n*/\n\nuserType = new GraphQLObjectType({\n  name: 'User',\n  description: 'A user',\n  fields: Object.assign(attributeFields(Model), {\n    // ... extra fields\n  })\n});\n```\n### Providing custom types\n\n`attributeFields` uses the graphql-sequelize `typeMapper` to map Sequelize types to GraphQL types. You can supply your own\nmapping function to override this behavior using the `mapType` export.\n\n```js\nvar Model = sequelize.define('User', {\n  email: {\n    type: Sequelize.STRING,\n    allowNull: false\n  },\n  isValid: {\n    type: Sequelize.BOOLEAN,\n    allowNull: false\n  }\n});\n\nimport {attributeFields,typeMapper} from 'graphql-sequelize';\ntypeMapper.mapType((type) =\u003e {\n   //map bools as strings\n   if (type instanceof Sequelize.BOOLEAN) {\n     return GraphQLString\n   }\n   //use default for everything else\n   return false\n});\n\n//map fields\nattributeFields(Model);\n\n/*\n{\n  id: {\n    type: new GraphQLNonNull(GraphQLInt)\n  },\n  email: {\n    type: new GraphQLNonNull(GraphQLString)\n  },\n  isValid: {\n      type: new GraphQLNonNull(GraphQLString)\n  },\n}\n*/\n\n```\n\n### Renaming generated fields\n\nattributeFields accepts a ```map``` option to customize the way the attribute fields are named. The ```map``` option accepts\nan object or a function that returns a string.\n\n```js\n\nvar Model = sequelize.define('User', {\n  email: {\n    type: Sequelize.STRING,\n    allowNull: false\n  },\n  firstName: {\n    type: Sequelize.STRING\n  },\n  lastName: {\n    type: Sequelize.STRING\n  }\n});\n\nattributeFields(Model, {\n    map:{\n        email:\"Email\",\n        firstName:\"FirstName\",\n        lastName:\"LastName\"\n    }\n});\n\n/*\n{\n  id: {\n    type: new GraphQLNonNull(GraphQLInt)\n  },\n  Email: {\n    type: new GraphQLNonNull(GraphQLString)\n  },\n  FirstName: {\n    type: GraphQLString\n  },\n  LastName: {\n    type: GraphQLString\n  }\n}\n*/\n\nattributeFields(Model, {\n    map:(k) =\u003e k.toLowerCase()\n});\n\n/*\n{\n  id: {\n    type: new GraphQLNonNull(GraphQLInt)\n  },\n  email: {\n    type: new GraphQLNonNull(GraphQLString)\n  },\n  firstname: {\n    type: GraphQLString\n  },\n  lastname: {\n    type: GraphQLString\n  }\n}\n*/\n\n```\n\n### ENUM attributes with non-alphanumeric characters\n\nGraphQL enum types [only support ASCII alphanumeric characters, digits and underscores with leading non-digit](https://facebook.github.io/graphql/#Name).\nIf you have other characters, like a dash (`-`) in your Sequelize enum types,\nthey will be converted to camelCase. If your enum value starts from a digit, it\nwill be prepended with an underscore.\n\nFor example:\n\n- `foo-bar` becomes `fooBar`\n\n- `25.8` becomes `_258`\n\n### VIRTUAL attributes and GraphQL fields\n\nIf 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 ... ])`.\n\nFor example, `fullName` here will not always return valid data when queried via GraphQL:\n```js\nfirstName: { type: Sequelize.STRING },\nlastName: { type: Sequelize.STRING },\nfullName: {\n  type: Sequelize.VIRTUAL,\n  get: function() { return `${this.firstName} ${this.lastName}`; },\n},\n```\n\nTo work properly `fullName` needs to be more fully specified:\n\n```js\nfirstName: { type: Sequelize.STRING },\nlastName: { type: Sequelize.STRING },\nfullName: {\n  type: new Sequelize.VIRTUAL(Sequelize.STRING, ['firstName', 'lastName']),\n  get: function() { return `${this.firstName} ${this.lastName}`; },\n},\n```\n\n## args helpers\n\n### defaultArgs\n\n`defaultArgs(Model)` will return an object containing an arg with a key and type matching your models primary key and\nthe \"where\" argument for passing complex query operations described [here](http://docs.sequelizejs.com/en/latest/docs/querying/)\n\n```js\nvar Model = sequelize.define('User', {\n\n});\n\ndefaultArgs(Model);\n\n/*\n{\n  id: {\n    type: new GraphQLNonNull(GraphQLInt)\n  }\n}\n*/\n\nvar Model = sequelize.define('Project', {\n  project_id: {\n    type: Sequelize.UUID\n  }\n});\n\ndefaultArgs(Model);\n\n/*\n{\n  project_id: {\n    type: GraphQLString\n  },\n  where: {\n    type: JSONType\n  }\n}\n*/\n```\n\nIf you would like to pass \"where\" as a query variable - you should pass it as a JSON string and declare its type as SequelizeJSON:\n\n```\n/* with GraphiQL */\n// request\nquery($where: SequelizeJSON) {\n  user(where: $where) {\n    name\n  }\n}\n\n// query variables\n# JSON doesn't allow single quotes, so you need to use escaped double quotes in your JSON string\n{\n  \"where\": \"{\\\"name\\\": {\\\"like\\\": \\\"Henry%\\\"}}\"\n}\n```\n\n### defaultListArgs\n\n`defaultListArgs` will return an object like:\n\n```js\n{\n  limit: {\n    type: GraphQLInt\n  },\n  order: {\n    type: GraphQLString\n  },\n  where: {\n    type: JSONType\n  }\n}\n```\n\nWhich when added to args will let the resolver automatically support limit and ordering in args for graphql queries.\nShould be used with fields of type `GraphQLList`.\n\n```js\nimport {defaultListArgs} from 'graphql-sequelize'\n\nargs: Object.assign(defaultListArgs(), {\n  // ... additional args\n})\n```\n\n `order` expects a valid field name and will sort `ASC` by default. For `DESC` you would prepend `reverse:` to the field name.\n\n\n ```\n /* with GraphiQL */\n // users represents a GraphQLList of type user\n\n query($limit: Int, $order: String, $where: SequelizeJSON) {\n   users(limit: $limit, order: $order, where: $where) {\n     name\n   }\n }\n\n // query variables\n {\n   \"order\": \"name\" // OR \"reverse:name\" for DESC\n }\n ```\n","funding_links":[],"categories":["JavaScript","Libraries","Implementations","Uncategorized","Community","GraphQL [🔝](#readme)"],"sub_categories":["JavaScript Libraries","JavaScript/TypeScript","Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmickhansen%2Fgraphql-sequelize","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmickhansen%2Fgraphql-sequelize","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmickhansen%2Fgraphql-sequelize/lists"}