{"id":13516791,"url":"https://github.com/join-monster/join-monster-graphql-tools-adapter","last_synced_at":"2026-04-01T20:43:44.513Z","repository":{"id":42939578,"uuid":"84163725","full_name":"join-monster/join-monster-graphql-tools-adapter","owner":"join-monster","description":"Use Join Monster to fetch your data with Apollo Server.","archived":false,"fork":false,"pushed_at":"2023-01-07T04:30:10.000Z","size":465,"stargazers_count":142,"open_issues_count":23,"forks_count":20,"subscribers_count":8,"default_branch":"master","last_synced_at":"2026-01-02T06:13:03.867Z","etag":null,"topics":["apollo","batch","data","graphql","join","schema","sql"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/join-monster.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-07T06:34:13.000Z","updated_at":"2025-01-19T18:05:11.000Z","dependencies_parsed_at":"2023-02-06T11:46:22.968Z","dependency_job_id":null,"html_url":"https://github.com/join-monster/join-monster-graphql-tools-adapter","commit_stats":null,"previous_names":["acarl005/join-monster-graphql-tools-adapter"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/join-monster/join-monster-graphql-tools-adapter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/join-monster%2Fjoin-monster-graphql-tools-adapter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/join-monster%2Fjoin-monster-graphql-tools-adapter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/join-monster%2Fjoin-monster-graphql-tools-adapter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/join-monster%2Fjoin-monster-graphql-tools-adapter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/join-monster","download_url":"https://codeload.github.com/join-monster/join-monster-graphql-tools-adapter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/join-monster%2Fjoin-monster-graphql-tools-adapter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31291780,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["apollo","batch","data","graphql","join","schema","sql"],"created_at":"2024-08-01T05:01:25.909Z","updated_at":"2026-04-01T20:43:44.490Z","avatar_url":"https://github.com/join-monster.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Join Monster GraphQL Tools Adapter\n\nUse [Join Monster](https://github.com/stems/join-monster)'s SQL generation and query batching powers with the Apollo [graphql-tools](https://github.com/apollographql/graphql-tools) server package.\n\n### What's this package for?\n\nSuppose you have a GraphQL schema for a forum website, defined with the [Schema Language](http://graphql.org/learn/schema/#type-language) like so:\n\n```js\nconst typeDefs = `\ntype Comment {\n  id: Int!,\n  body: String!,\n  postId: Int,\n  authorId: Int,\n  archived: Boolean\n}\n\ntype Post {\n  id: Int!,\n  body: String!,\n  authorId: Int,\n  numComments: Int!,\n  comments: [Comment]\n}\n\ntype User {\n  id: Int!,\n  email: String!,\n  fullName: String!,\n  favNums: [Int],\n  posts: [Post]\n}\n\ntype Query {\n  user(id: Int!): User\n}\n`\n\nmodule.exports = typeDefs\n```\n\nWhen using [graphql-js](https://github.com/graphql/graphql-js), the reference implementation, you tag the Type constructors with extra metadata to configure Join Monster.\nThe schema language does not allow adding arbitrary properties to the type definitions.\n\nThis package let's you add those tags without messing with the internals of the built schema object.\nOnce you familiarize yourself with [Join Monster's API](http://join-monster.readthedocs.io), you can use all the same properties by passing it to this function.\n\n\n```js\nconst joinMonsterAdapt = require('join-monster-graphql-tools-adapter')\nconst typeDefs = require('../path/to/types')\n\nconst joinMonster = require('join-monster').default\n// node drivers for talking to SQLite\nconst db = require('sqlite')\nconst { makeExecutableSchema } = require('graphql-tools')\n\nconst resolvers = {\n  Query: {\n    // call joinMonster in the \"user\" resolver, and all child fields that are tagged with \"sqlTable\" are handled!\n    user(parent, args, ctx, resolveInfo) {\n      return joinMonster(resolveInfo, ctx, sql =\u003e {\n        return db.all(sql)\n      }, { dialect: 'sqlite3' })\n    }\n  },\n  User: {\n    // the only field that needs a resolver, joinMonster hydrates the rest!\n    fullName(user) {\n      return user.first_name + ' ' + user.last_name\n    }\n  }\n}\n\nconst schema = makeExecutableSchema({\n  typeDefs,\n  resolvers\n})\n\n// tag the schema types with the extra join monster metadata\n// Note the change in JoinMonster API (v3) - extensions: {} block\njoinMonsterAdapt(schema, {\n  Query: {\n    fields: {\n      // add a function to generate the \"where condition\"\n      user: {\n        extensions: {\n          joinMonster: {\n            where: (table, args) =\u003e `${table}.id = ${args.id}`\n          }\n        }\n      }\n    }\n  },\n  User: {\n    // map the User object type to its SQL table\n    extensions: {\n      joinMonster: {\n        sqlTable: 'accounts',\n        uniqueKey: 'id',\n      }\n    },\n    // tag the User's fields\n    fields: {\n      email: {\n        extensions: {\n          joinMonster: {\n            sqlColumn: 'email_address'\n          }\n        }\n      },\n      fullName: {\n        extensions: {\n          joinMonster: {\n            sqlDeps: [ 'first_name', 'last_name' ]\n          }\n        }\n      },\n      posts: {\n        extensions: {\n          joinMonster: {\n            sqlJoin: (userTable, postTable) =\u003e `${userTable}.id = ${postTable}.author_id`,\n          }\n        }\n      }\n    }\n  },\n  Post: {\n    extensions: {\n      joinMonster: {\n        sqlTable: 'posts',\n        uniqueKey: 'id',\n      }\n    },\n    fields: {\n      numComments: {\n        extensions: {\n          joinMonster: {\n        // count with a correlated subquery\n            sqlExpr: table =\u003e `(SELECT count(*) FROM comments where ${table}.id = comments.post_id)`\n          }\n        }\n      },\n      comments: {\n        // fetch the comments in another batch request instead of joining\n        extensions: {\n          joinMonster: {\n            sqlBatch: {\n              thisKey: 'post_id',\n              parentKey: 'id'\n            }\n          }\n        }\n      }\n    }\n  },\n  Comment: {\n    extensions: {\n      joinMonster: {\n        sqlTable: 'comments',\n        uniqueKey: 'id',\n      }\n    },\n    fields: {\n      postId: {\n        extensions: {\n          joinMonster: {\n            sqlColumn: 'post_id'\n            }\n          }\n      },\n      authorId: {\n        extensions: {\n          joinMonster: {\n            sqlColumn: 'author_id'\n          }\n        }\n      }\n    }\n  }\n})\n```\n\nNow that our schema is *Join-monsterized*, we are ready to start executing some queries!\n\n```js\nconst { graphql } = require('graphql')\n\nconst query = `{\n  user(id: 1) {\n    id\n    fullName\n    email\n    posts {\n      id\n      body\n      numComments\n      comments {\n        id\n        body\n        authorId\n        archived\n      }\n    }\n  }\n}`\ngraphql(schema, query).then(doSomethingCrazy)\n```\n\n### Advisory\nThere is a known issue (see #4) that passing the `logger` in graphql-tools `makeExecutableSchema` breaks automatic fetching of default column values. For the time being, it is suggested to remove the logger or add `sqlColumn` to every field.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoin-monster%2Fjoin-monster-graphql-tools-adapter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoin-monster%2Fjoin-monster-graphql-tools-adapter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoin-monster%2Fjoin-monster-graphql-tools-adapter/lists"}