{"id":13679753,"url":"https://github.com/nicolasdao/graphql-s2s","last_synced_at":"2025-04-05T06:04:51.694Z","repository":{"id":21485630,"uuid":"92844514","full_name":"nicolasdao/graphql-s2s","owner":"nicolasdao","description":"Add GraphQL Schema support for type inheritance, generic typing, metadata decoration. Transpile the enriched GraphQL string schema into the standard string schema understood by graphql.js and the Apollo server client.","archived":false,"fork":false,"pushed_at":"2023-10-09T12:14:39.000Z","size":4333,"stargazers_count":187,"open_issues_count":19,"forks_count":15,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-03-24T03:41:52.163Z","etag":null,"topics":["generic-types","graphql","graphql-schema","inheritance-styles","metadata","parser"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nicolasdao.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-05-30T14:57:56.000Z","updated_at":"2024-06-04T00:13:59.000Z","dependencies_parsed_at":"2023-01-11T21:14:14.775Z","dependency_job_id":"c0929c00-1997-4bd1-9477-c2bab214ae1c","html_url":"https://github.com/nicolasdao/graphql-s2s","commit_stats":{"total_commits":194,"total_committers":9,"mean_commits":"21.555555555555557","dds":0.3917525773195877,"last_synced_commit":"eb7475832d9c88020fba235df705d646a9801c96"},"previous_names":[],"tags_count":66,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasdao%2Fgraphql-s2s","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasdao%2Fgraphql-s2s/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasdao%2Fgraphql-s2s/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasdao%2Fgraphql-s2s/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nicolasdao","download_url":"https://codeload.github.com/nicolasdao/graphql-s2s/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247294538,"owners_count":20915340,"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":["generic-types","graphql","graphql-schema","inheritance-styles","metadata","parser"],"created_at":"2024-08-02T13:01:09.046Z","updated_at":"2025-04-05T06:04:51.672Z","avatar_url":"https://github.com/nicolasdao.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\n\u003e This project is still maintained but has been superseded by [graphql-schemax](https://github.com/nicolasdao/graphql-schemax). graphql-schemax takes the approach of compiling standard JSON object into a GraphQL Schema string.\n\n# GraghQL Schema-2-Schema Transpiler \u0026middot;  [![NPM](https://img.shields.io/npm/v/graphql-s2s.svg?style=flat)](https://www.npmjs.com/package/graphql-s2s) [![Tests](https://travis-ci.org/nicolasdao/graphql-s2s.svg?branch=master)](https://travis-ci.org/nicolasdao/graphql-s2s) [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![Neap](https://neap.co/img/made_by_neap.svg)](#this-is-what-we-re-up-to) [![npm downloads](https://img.shields.io/npm/dt/graphql-s2s.svg?style=flat)](https://www.npmjs.com/package/graphql-s2s)\n\n# Table Of Contents\n\u003e * [What It Does](#what-it-does)\n\u003e * [Install](#install)\n\u003e * [Getting Started](#getting-started)\n\u003e\t- [Basic](#basic)\n\u003e\t- [Type Inheritance](#type-inheritance)\n\u003e\t- [Generic Types](#generic-types)\n\u003e\t- [Metadata Decoration](#metadata-decoration)\n\u003e\t- [Deconstructing - Transforming - Rebuilding Queries](#deconstructing---transforming---rebuilding-queries)\n\u003e * [How To](#how-to)\n\u003e\t- [How to use a custom name on generic types?](#how-to-use-a-custom-name-on-generic-types)\n\u003e * [Examples](#examples)\n\u003e * [Contribute](#contribute)\n\u003e * [About Neap](#this-is-what-we-re-up-to)\n\u003e * [License](#license)\n\n# What It Does\nGraphQL S2S enriches the standard GraphQL Schema string used by both [graphql.js](https://github.com/graphql/graphql-js) and the [Apollo Server](https://github.com/apollographql/graphql-tools). The enriched schema supports:\n* [**Type Inheritance**](#type-inheritance)\n* [**Generic Types**](#generic-types)\n* [**Metadata Decoration**](#metadata-decoration)\n* [**Deconstructing - Transforming - Rebuilding Queries**](#deconstructing---transforming---rebuilding-queries)\n\n# Install\n### node\n```js\nnpm install graphql-s2s --save\n```\n### browser\n```html\n\u003cscript src=\"https://unpkg.com/graphql-s2s@0.11.2/lib/graphqls2s.min.js\"\u003e\u003c/script\u003e\n```\n\u003e Using the awesome [unpkg.com](https://unpkg.com), all versions are supported at https\u003cspan\u003e://unpkg\u003c/span\u003e.com/graphql-s2s@__*:VERSION*__/lib/graphqls2s.min.js.\nThe API will be accessible through the __*graphqls2s*__ object.\n\nIt is also possible to embed it after installing the _graphql-s2s_ npm package:\n```html\n\u003cscript src=\"./node_modules/graphql-s2s/lib/graphqls2s.min.js\"\u003e\u003c/script\u003e\n```\n\n# Getting Started\n## Basic\n```js\nconst { transpileSchema } = require('graphql-s2s').graphqls2s\nconst { makeExecutableSchema } = require('graphql-tools')\n\nconst schema = `\ntype Node {\n\tid: ID!\n}\n\ntype Person inherits Node {\n\tfirstname: String\n\tlastname: String\n}\n\ntype Student inherits Person {\n\tnickname: String\n}\n\ntype Query {\n  students: [Student]\n}\n`\n\nconst resolver = {\n        Query: {\n            students(root, args, context) {\n            \t// replace this dummy code with your own logic to extract students.\n                return [{ id: 1, firstname: \"Carry\", lastname: \"Connor\", nickname: \"Cannie\" }]\n            }\n        }\n    };\n\nconst executableSchema = makeExecutableSchema({\n  typeDefs: [transpileSchema(schema)],\n  resolvers: resolver\n})\n```\n\n## Type Inheritance\n\n### Single Inheritance\n\n```js\nconst schema = `\ntype Node {\n\tid: ID!\n}\n\n# Inheriting from the 'Node' type\ntype Person inherits Node {\n\tfirstname: String\n\tlastname: String\n}\n\n# Inheriting from the 'Person' type\ntype Student inherits Person {\n\tnickname: String\n}\n`\n```\n\n### Multiple Inheritance\n\n```js\nconst schema = `\n\ntype Node {\n\tid: ID!\n}\n\ntype Address {\n\tstreetAddress: String\n\tcity: String\n\tstate: String\n}\n\n# Inheriting from the 'Node' \u0026 'Adress' type\ntype Person inherits Node, Address {\n\tid: ID!\n\tstreetAddress: String\n\tcity: String\n\tstate: String\n\tfirstname: String\n\tlastname: String\n}\n\n`\n```\n\nMore details in the [code below](#type-inheritance).\n\n## Generic Types\n\n```js\nconst schema = `\n# Defining a generic type\ntype Paged\u003cT\u003e {\n\tdata: [T]\n\tcursor: ID\n}\n\ntype Question {\n\tname: String!\n\ttext: String!\n}\n\n# Using the generic type\ntype Student {\n\tname: String\n\tquestions: Paged\u003cQuestion\u003e\n}\n\n# Using the generic type\ntype Teacher {\n\tname: String\n\tstudents: Paged\u003cStudent\u003e\n}\n`\n```\n\nMore details in the [code below](#generic-types).\n\n## Metadata Decoration\n\n```js\nconst schema = `\n# Defining a custom 'node' metadata attribute\n@node\ntype Node {\n\tid: ID!\n}\n\ntype Student inherits Node {\n\tname: String\n\n\t# Defining another custom 'edge' metadata, and supporting a generic type\n\t@edge(some other metadata using whatever syntax I want)\n\tquestions: [String]\n}\n`\n```\n\nThe enriched schema provides a richer and more compact notation. The transpiler converts the enriched schema into the standard expected by [graphql.js](https://github.com/graphql/graphql-js) (using the _buildSchema_ method) as well as the [Apollo Server](https://github.com/apollographql/graphql-tools). For more details on how to extract those extra information from the string schema, use the method _getSchemaAST_ (example in section [_Metadata Decoration_](#metadata-decoration)). \n\n_Metadata_ can be added to decorate the schema types and properties. Add whatever you want as long as it starts with _@_ and start hacking your schema. The original intent of that feature was to decorate the schema with metadata _@node_ and _@edge_ so we could add metadata about the nature of the relations between types.\n\nMetadata can also be used to customize generic types names as shown in section [How to use a custom name on generic types?](#how-to-use-a-custom-name-on-generic-types).\n\n## Deconstructing - Transforming - Rebuilding Queries\n\nThis feature allows your GraphQl server to deconstruct any GraphQl query as an AST that can then be filtered and modified based on your requirements. That AST can then be rebuilt as a valid GraphQL query. A great example of that feature in action is the [__graphql-authorize__](https://github.com/nicolasdao/graphql-authorize.git) middleware for [__graphql-serverless__](https://github.com/nicolasdao/graphql-serverless) which filters query's properties based on the user's rights.\n\nFor a concrete example, refer to the [code below](#deconstructing---transforming---rebuilding-queries-1).\n\n# How To\n## How to use a custom name on generic types?\n\nUse the special keyword `@alias` as follow:\n\n```js\nconst schema = `\n  type Post {\n    code: String\n  }\n\n  type Brand {\n    id: ID!\n    name: String\n    posts: Page\u003cPost\u003e\n  }\n\n  @alias((T) =\u003e T + 's')\n  type Page\u003cT\u003e {\n    data: [T]\n  }\n  `\n```\n\nAfter transpilation, the resulting schema is:\n\n```js\nconst output = transpileSchema(schema)\n// output:\n// =======\n// \ttype Post {\n// \t\tcode: String\n// \t}\n// \n// \ttype Brand {\n// \t\tid: ID!\n// \t\tname: String\n// \t\tposts: Posts\n// \t}\n// \n// \ttype Posts {\n// \t\tdata: [Post]\n// \t}\n\n````\n\n# Examples\n_WARNING: the following examples will be based on '[graphql-tools](https://github.com/apollographql/graphql-tools)' from the Apollo team, but the string schema could also be used with the 'buildSchema' method from graphql.js_\n\n### Type Inheritance\n_NOTE: The examples below only use 'type', but it would also work on 'input' and 'interface'_\n\n__*Before graphql-s2s*__\n```js\nconst schema = `\ntype Teacher {\n\tid: ID!\n\tcreationDate: String\n\n\tfirstname: String!\n\tmiddlename: String\n\tlastname: String!\n\tage: Int!\n\tgender: String \n\n\ttitle: String!\n}\n\ntype Student {\n\tid: ID!\n\tcreationDate: String\n\n\tfirstname: String!\n\tmiddlename: String\n\tlastname: String!\n\tage: Int!\n\tgender: String \n\n\tnickname: String!\n}`\n\n```\n__*After graphql-s2s*__\n```js\nconst schema = `\ntype Node {\n\tid: ID!\n\tcreationDate: String\n}\n\ntype Person inherits Node {\n\tfirstname: String!\n\tmiddlename: String\n\tlastname: String!\n\tage: Int!\n\tgender: String \n}\n\ntype Teacher inherits Person {\n\ttitle: String!\n}\n\ntype Student inherits Person {\n\tnickname: String!\n}`\n\n```\n\n__*Full code example*__\n\n```js\nconst { transpileSchema } = require('graphql-s2s').graphqls2s\nconst { makeExecutableSchema } = require('graphql-tools')\nconst { students, teachers } = require('./dummydata.json')\n\nconst schema = `\ntype Node {\n\tid: ID!\n\tcreationDate: String\n}\n\ntype Person inherits Node {\n\tfirstname: String!\n\tmiddlename: String\n\tlastname: String!\n\tage: Int!\n\tgender: String \n}\n\ntype Teacher inherits Person {\n\ttitle: String!\n}\n\ntype Student inherits Person {\n\tnickname: String!\n\tquestions: [Question]\n}\n\ntype Question inherits Node {\n\tname: String!\n\ttext: String!\n}\n\ntype Query {\n  # ### GET all users\n  #\n  students: [Student]\n\n  # ### GET all teachers\n  #\n  teachers: [Teacher]\n}\n`\n\nconst resolver = {\n        Query: {\n            students(root, args, context) {\n                return Promise.resolve(students)\n            },\n\n            teachers(root, args, context) {\n                return Promise.resolve(teachers)\n            }\n        }\n    }\n\nconst executableSchema = makeExecutableSchema({\n  typeDefs: [transpileSchema(schema)],\n  resolvers: resolver\n})\n```\n\n### Generic Types\n_NOTE: The examples below only use 'type', but it would also work on 'input'_\n\n__*Before graphql-s2s*__\n```js\nconst schema = `\ntype Teacher {\n\tid: ID!\n\tcreationDate: String\n\tfirstname: String!\n\tmiddlename: String\n\tlastname: String!\n\tage: Int!\n\tgender: String \n\ttitle: String!\n}\n\ntype Student {\n\tid: ID!\n\tcreationDate: String\n\tfirstname: String!\n\tmiddlename: String\n\tlastname: String!\n\tage: Int!\n\tgender: String \n\tnickname: String!\n\tquestions: Questions\n}\n\ntype Question {\n\tid: ID!\n\tcreationDate: String\n\tname: String!\n\ttext: String!\n}\n\ntype Teachers {\n\tdata: [Teacher]\n\tcursor: ID\n}\n\ntype Students {\n\tdata: [Student]\n\tcursor: ID\n}\n\ntype Questions {\n\tdata: [Question]\n\tcursor: ID\n}\n\ntype Query {\n  # ### GET all users\n  #\n  students: Students\n\n  # ### GET all teachers\n  #\n  teachers: Teachers\n}\n`\n\n```\n__*After graphql-s2s*__\n```js\nconst schema = `\ntype Paged\u003cT\u003e {\n\tdata: [T]\n\tcursor: ID\n}\n\ntype Node {\n\tid: ID!\n\tcreationDate: String\n}\n\ntype Person inherits Node {\n\tfirstname: String!\n\tmiddlename: String\n\tlastname: String!\n\tage: Int!\n\tgender: String \n}\n\ntype Teacher inherits Person {\n\ttitle: String!\n}\n\ntype Student inherits Person {\n\tnickname: String!\n\tquestions: Paged\u003cQuestion\u003e\n}\n\ntype Question inherits Node {\n\tname: String!\n\ttext: String!\n}\n\ninput Filter\u003cFilterFields\u003e {\n  field: FilterFields!,\n  value: String!\n}\n\nenum TeachersFilterFields {\n  firstName\n  lastName\n}\n\ntype Query {\n  # ### GET all users\n  #\n  students: Paged\u003cStudent\u003e\n\n  # ### GET all teachers\n  # You can use generic types on parameters, too.\n  #\n  teachers(filter: Filter\u003cTeachersFilterFields\u003e): Paged\u003cTeacher\u003e\n}\n`\n```\nThis is very similar to C# or Java generic classes. What the transpiler will do is to simply recreate 3 types (one for Paged\\\u003cQuestion\\\u003e, Paged\\\u003cStudent\\\u003e and Paged\\\u003cTeacher\\\u003e), and one input (Filter\\\u003cTeachersFilterFields\\\u003e). If we take the Paged\\\u003cQuestion\\\u003e example, the transpiled type will be:\n```js\ntype PagedQuestion {\n\tdata: [Question]\n\tcursor: ID\n}\n```\n\n__*Full code example*__\n\n```js\nconst { transpileSchema } = require('graphql-s2s').graphqls2s\nconst { makeExecutableSchema } = require('graphql-tools')\nconst { students, teachers } = require('./dummydata.json')\n\nconst schema = `\ntype Paged\u003cT\u003e {\n\tdata: [T]\n\tcursor: ID\n}\n\ntype Node {\n\tid: ID!\n\tcreationDate: String\n}\n\ntype Person inherits Node {\n\tfirstname: String!\n\tmiddlename: String\n\tlastname: String!\n\tage: Int!\n\tgender: String \n}\n\ntype Teacher inherits Person {\n\ttitle: String!\n}\n\ntype Student inherits Person {\n\tnickname: String!\n\tquestions: Paged\u003cQuestion\u003e\n}\n\ntype Question inherits Node {\n\tname: String!\n\ttext: String!\n}\n\ntype Query {\n  # ### GET all users\n  #\n  students: Paged\u003cStudent\u003e\n\n  # ### GET all teachers\n  #\n  teachers: Paged\u003cTeacher\u003e\n}\n`\n\nconst resolver = {\n        Query: {\n            students(root, args, context) {\n                return Promise.resolve({ data: students.map(s =\u003e ({ __proto__:s, questions: { data: s.questions, cursor: null }})), cursor: null })\n            },\n\n            teachers(root, args, context) {\n                return Promise.resolve({ data: teachers, cursor: null });\n            }\n        }\n    }\n\nconst executableSchema = makeExecutableSchema({\n  typeDefs: [transpileSchema(schema)],\n  resolvers: resolver\n})\n```\n\n### Metadata Decoration\nDefine your own custom metadata and decorate your GraphQL schema with new types of data. Let's imagine we want to explicitely add metadata about the type of relations between nodes, we could write something like this:\n```js\nconst { getSchemaAST } = require('graphql-s2s').graphqls2s\nconst schema = `\n@node\ntype User {\n\t@edge('\u003c-[CREATEDBY]-')\n\tposts: [Post]\n}\n`\n\nconst schemaObjects = getSchemaAST(schema);\n\n// -\u003e schemaObjects\n//\t{ \n//\t\t\"type\": \"TYPE\", \n//\t\t\"name\": \"User\", \n//\t\t\"metadata\": { \n//\t\t\t\"name\": \"node\", \n//\t\t\t\"body\": \"\", \n//\t\t\t\"schemaType\": \"TYPE\", \n//\t\t\t\"schemaName\": \"User\", \"parent\": null \n//\t\t}, \n//\t\t\"genericType\": null, \n//\t\t\"blockProps\": [{ \n//\t\t\t\"comments\": \"\", \n//\t\t\t\"details\": { \n//\t\t\t\t\"name\": \"posts\", \n//\t\t\t\t\"metadata\": { \n//\t\t\t\t\t\"name\": \"edge\", \n//\t\t\t\t\t\"body\": \"(\\'\u003c-[CREATEDBY]-\\')\", \n//\t\t\t\t\t\"schemaType\": \"PROPERTY\", \n//\t\t\t\t\t\"schemaName\": \"posts: [Post]\", \n//\t\t\t\t\t\"parent\": { \n//\t\t\t\t\t\t\"type\": \"TYPE\", \n//\t\t\t\t\t\t\"name\": \"User\", \n//\t\t\t\t\t\t\"metadata\": { \n//\t\t\t\t\t\t\t\"type\": \"TYPE\", \n//\t\t\t\t\t\t\t\"name\": \"node\" \n//\t\t\t\t\t\t} \n//\t\t\t\t\t} \n//\t\t\t\t}, \n//\t\t\t\t\"params\": null, \n//\t\t\t\t\"result\": { \n//\t\t\t\t\t\"originName\": \"[Post]\", \n//\t\t\t\t\t\"isGen\": false, \n//\t\t\t\t\t\"name\": \"[Post]\" \n//\t\t\t\t} \n//\t\t\t}, \n//\t\t\t\"value\": \"posts: [Post]\" \n//\t\t}], \n//\t\t\"inherits\": null, \n//\t\t\"implements\": null \n//\t}\n```\n### Deconstructing - Transforming - Rebuilding Queries\nThis feature allows your GraphQl server to deconstruct any GraphQl query as an AST that can then be filtered and modified based on your requirements. That AST can then be rebuilt as a valid GraphQL query. A great example of that feature in action is the [__graphql-authorize__](https://github.com/nicolasdao/graphql-authorize.git) middleware for [__graphql-serverless__](https://github.com/nicolasdao/graphql-serverless) which filters query's properties based on the user's rights.\n\n```js\nconst { getQueryAST, buildQuery, getSchemaAST } = require('graphql-s2s').graphqls2s\nconst schema = `\n\ttype Property {\n\t\tname: String\n\t\t@auth\n\t\taddress: String\n\t}\n\t\n\tinput InputWhere {\n\t\tname: String\n\t\tlocations: [LocationInput]\n\t}\n\t\n\tinput LocationInput {\n\t\ttype: String \n\t\tvalue: String\n\t}\n\t\n\ttype Query {\n\t\tproperties(where: InputWhere): [Property]\n\t}`\n\nconst query = `\n\tquery {\n\t\tproperties(where: { name: \"Love\", locations: [{ type: \"house\", value: \"Bellevue hill\" }] }){\n\t\t\tname\n\t\t\taddress\n\t\t}\n\t}`\n\nconst schemaAST = getSchemaAST(schema)\nconst queryAST = getQueryAST(query, null, schemaAST)\nconst rebuiltQuery = buildQuery(queryAST.filter(x =\u003e !x.metadata || x.metadata.name != 'auth'))\n\n//\tquery {\n//\t\tproperties(where:{name:\"Love\",locations:[{type:\"house\",value:\"Bellevue hill\"}]}){\n//\t\t\tname\n//\t\t}\n// \t}\n```\n\nNotice that the original query was requesting the `address` property. Because we decorated that property with the custom metadata `@auth` (feature demonstrated previously [Metadata Decoration](#metadata-decoration)), we were able to filter that property to then rebuilt the query without it.\n\n#### API\n\n__*getQueryAST(query, operationName, schemaAST, options): QueryAST*__\n\nReturns an GraphQl query AST.\n\n| Arguments      | type    | Description  |\n| :------------- |:-------:| :------------ |\n| query      \t | String  | GraphQl Query. |\n| operationName  | String  | GraphQl query operation. Only useful if multiple operations are defined in a single query, otherwise use `null`. |\n| schemaAST      | Object  | Original GraphQl schema AST obtained thanks to the `getSchemaAST` function. |\n| options.defrag | Boolean | If set to true and if the query contained fragments, then all fragments are replaced by their explicit definition in the AST. |\n\n__*QueryAST Object Structure*__\n\n| Properties | type   | Description  |\n| :--------- |:------:| :------------ |\n| name    \t | String | Field's name. |\n| kind       | String | Field's kind. |\n| type       | String | Field's type. |\n| metadata   | String | Field's metadata. |\n| args       | Array  | Array of argument objects. |\n| properties | Array  | Array of QueryAST objects. |\n\n__*QueryAST.filter((ast:QueryAST) =\u003e ...): QueryAST*__\n\nReturns a new QueryAST object where only ASTs complying to the predicate `ast =\u003e ...` are left.\n\n__*QueryAST.propertyPaths((ast:QueryAST) =\u003e ...): [String]*__\n\nReturns an array of strings. Each one represents the path to the query property that matches the predicate `ast =\u003e ...`.\n\n__*QueryAST.containsProp(property:String): Boolean*__\n\nReturns a boolean indicating the presence of a property in the GraphQl query. Example:\n\n```js\nconst schema = `\ntype User {\n  id: ID!\n  name: String\n  details: UserDetails\n}\n\ntype UserDetails {\n  gender: String \n}\n\ntype Query {\n  users: [User]\n}\n`\nconst query = `\n{\n  users {\n    id\n    details {\n      gender\n    }\n  }\n}`\nconst schemaAST = getSchemaAST(schema)\nconst queryAST = getQueryAST(query, null, schemaAST)\nqueryAST.containsProp('users.id') // true\nqueryAST.containsProp('users.details.gender') // true\nqueryAST.containsProp('details.gender') // true\nqueryAST.containsProp('users.name') // false\n```\n\n__*QueryAST.some((ast:QueryAST) =\u003e ...): Boolean*__\n\nReturns a boolean indicating whether the QueryAST contains at least one AST matching the predicate `ast =\u003e ...`.\n\n__*buildQuery(ast:QueryAST): String*__\n\nRebuilds a valid GraphQl query from a QueryAST object.\n\n# Contribute\n## Step 1. Don't Forget To Test Your Feature\nWe only accept pull request that have been thoroughly tested. To do so, simply add your test under the `test/browser/graphqls2s.js` file. \n\nOnce that's done, simply run your the following command to test your features:\n```\nnpm run test:dev\n```\nThis sets an environment variable that configure the project to load the main dependency from the _src_ folder (source code in ES6) instead of the _lib_ folder (transpiled ES5 code). \n\n## Step 2. Compile \u0026 Rerun Your Test Before Pushing\n```\nnpm run dev\nnpm run build\nnpm test\n```\nThis project is built using Javascript ES6. Each version is also transpiled to ES5 using Babel through Webpack 2, so this project can run in the browser. In order to write unit test only once instead of duplicating it for each version of Javascript, the all unit tests have been written using Javascript ES5 in mocha. That means that if you want to test the project after some changes, you will need to first transpile the project to ES5. \n\n# This Is What We re Up To\nWe are Neap, an Australian Technology consultancy powering the startup ecosystem in Sydney. We simply love building Tech and also meeting new people, so don't hesitate to connect with us at [https://neap.co](https://neap.co).\n\nOur other open-sourced projects:\n#### GraphQL\n* [__*graphql-s2s*__](https://github.com/nicolasdao/graphql-s2s): Add GraphQL Schema support for type inheritance, generic typing, metadata decoration. Transpile the enriched GraphQL string schema into the standard string schema understood by graphql.js and the Apollo server client.\n* [__*schemaglue*__](https://github.com/nicolasdao/schemaglue): Naturally breaks down your monolithic graphql schema into bits and pieces and then glue them back together.\n* [__*graphql-authorize*__](https://github.com/nicolasdao/graphql-authorize.git): Authorization middleware for [graphql-serverless](https://github.com/nicolasdao/graphql-serverless). Add inline authorization straight into your GraphQl schema to restrict access to certain fields based on your user's rights.\n\n#### React \u0026 React Native\n* [__*react-native-game-engine*__](https://github.com/bberak/react-native-game-engine): A lightweight game engine for react native.\n* [__*react-native-game-engine-handbook*__](https://github.com/bberak/react-native-game-engine-handbook): A React Native app showcasing some examples using react-native-game-engine.\n\n#### General Purposes\n* [__*core-async*__](https://github.com/nicolasdao/core-async): JS implementation of the Clojure core.async library aimed at implementing CSP (Concurrent Sequential Process) programming style. Designed to be used with the npm package 'co'.\n* [__*jwt-pwd*__](https://github.com/nicolasdao/jwt-pwd): Tiny encryption helper to manage JWT tokens and encrypt and validate passwords using methods such as md5, sha1, sha256, sha512, ripemd160.\n\n#### Google Cloud Platform\n* [__*google-cloud-bucket*__](https://github.com/nicolasdao/google-cloud-bucket): Nodejs package to manage Google Cloud Buckets and perform CRUD operations against them.\n* [__*google-cloud-bigquery*__](https://github.com/nicolasdao/google-cloud-bigquery): Nodejs package to manage Google Cloud BigQuery datasets, and tables and perform CRUD operations against them.\n* [__*google-cloud-tasks*__](https://github.com/nicolasdao/google-cloud-tasks): Nodejs package to push tasks to Google Cloud Tasks. Include pushing batches.\n\n# License\nCopyright (c) 2017-2019, Neap Pty Ltd.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n* Neither the name of Neap Pty Ltd nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL NEAP PTY LTD BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"https://neap.co\" target=\"_blank\"\u003e\u003cimg src=\"https://neap.co/img/neap_color_horizontal.png\" alt=\"Neap Pty Ltd logo\" title=\"Neap\" height=\"89\" width=\"200\"/\u003e\u003c/a\u003e\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicolasdao%2Fgraphql-s2s","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnicolasdao%2Fgraphql-s2s","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicolasdao%2Fgraphql-s2s/lists"}