{"id":30190812,"url":"https://github.com/fibjs/fib-graphql","last_synced_at":"2025-09-02T04:04:53.643Z","repository":{"id":57235119,"uuid":"107545502","full_name":"fibjs/fib-graphql","owner":"fibjs","description":"GraphQL for fibjs","archived":false,"fork":false,"pushed_at":"2017-10-19T12:52:44.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-09T06:21:13.080Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fibjs.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-10-19T12:49:35.000Z","updated_at":"2017-10-20T04:23:05.000Z","dependencies_parsed_at":"2022-08-23T15:50:24.721Z","dependency_job_id":null,"html_url":"https://github.com/fibjs/fib-graphql","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fibjs/fib-graphql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fibjs%2Ffib-graphql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fibjs%2Ffib-graphql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fibjs%2Ffib-graphql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fibjs%2Ffib-graphql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fibjs","download_url":"https://codeload.github.com/fibjs/fib-graphql/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fibjs%2Ffib-graphql/sbom","scorecard":{"id":398901,"data":{"date":"2025-08-11","repo":{"name":"github.com/fibjs/fib-graphql","commit":"67938a6da4f9ceb570a084488034919c1f0a55b5"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/1 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}}]},"last_synced_at":"2025-08-18T19:40:08.436Z","repository_id":57235119,"created_at":"2025-08-18T19:40:08.436Z","updated_at":"2025-08-18T19:40:08.436Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273227970,"owners_count":25067691,"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","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2025-08-12T20:08:56.112Z","updated_at":"2025-09-02T04:04:53.627Z","avatar_url":"https://github.com/fibjs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GraphQL for fibjs\n\nThe GraphQL specification is edited in the markdown files found in [`/spec`](./spec)\nthe latest release of which is published at http://facebook.github.io/graphql/.\n\nThe latest draft specification can be found at http://facebook.github.io/graphql/draft/\nwhich tracks the latest commit to the master branch in this repository.\n\nPrevious releases of the GraphQL specification can be found at permalinks that\nmatch their [release tag](https://github.com/facebook/graphql/releases). For\nexample, http://facebook.github.io/graphql/October2016/. If you are linking\ndirectly to the GraphQL specification, it's best to link to a tagged permalink\nfor the particular referenced version.\n\n## Overview\n\nThis is a Working Draft of the Specification for GraphQL, a query language for APIs created by Facebook.\n\nThe target audience for this specification is not the client developer, but those who have,\nor are actively interested in, building their own GraphQL implementations and\ntools.\n\nIn order to be broadly adopted, GraphQL will have to target a wide\nvariety of backends, frameworks, and languages, which will necessitate a\ncollaborative effort across projects and organizations. This specification serves as a point of coordination for this effort.\n\nLooking for help? Find resources [from the community](http://graphql.org/community/).\n\n## Getting Started\n\nGraphQL consists of a type system, query language and execution semantics,\nstatic validation, and type introspection, each outlined below. To guide you\nthrough each of these components, we've written an example designed to\nillustrate the various pieces of GraphQL.\n\nThis example is not comprehensive, but it is designed to quickly introduce\nthe core concepts of GraphQL, to provide some context before diving into\nthe more detailed specification or the [GraphQL.js](https://github.com/graphql/graphql-js)\nreference implementation.\n\nThe premise of the example is that we want to use GraphQL to query for\ninformation about characters and locations in the original Star Wars\ntrilogy.\n\n### Type System\n\nAt the heart of any GraphQL implementation is a description of what types\nof objects it can return, described in a GraphQL type system and returned\nin the GraphQL Schema.\n\nFor our Star Wars example, the\n[starWarsSchema.js](https://github.com/graphql/graphql-js/blob/master/src/__tests__/starWarsSchema.js)\nfile in GraphQL.js defines this type system.\n\nThe most basic type in the system will be `Human`, representing characters\nlike Luke, Leia, and Han. All humans in our type system will have a name,\nso we define the `Human` type to have a field called \"name\". This returns\na String, and we know that it is not null (since all `Human`s have a name),\nso we will define the \"name\" field to be a non-nullable String. Using a\nshorthand notation that we will use throughout the spec and documentation,\nwe would describe the human type as:\n\n```graphql\ntype Human {\n  name: String\n}\n```\n\nThis shorthand is convenient for describing the basic shape of a type\nsystem; the JavaScript implementation is more full-featured, and allows types\nand fields to be documented. It also sets up the mapping between the\ntype system and the underlying data; for a test case in GraphQL.js, the\nunderlying data is a [set of JavaScript objects](https://github.com/graphql/graphql-js/blob/master/src/__tests__/starWarsData.js),\nbut in most cases the backing data will be accessed through some service, and\nthis type system layer will be responsible for mapping from types and fields to\nthat service.\n\nA common pattern in many APIs, and indeed in GraphQL is to give\nobjects an ID that can be used to refetch the object. So let's add\nthat to our Human type. We'll also add a string for their home\nplanet.\n\n```graphql\ntype Human {\n  id: String\n  name: String\n  homePlanet: String\n}\n```\n\nSince we're talking about the Star Wars trilogy, it would be useful\nto describe the episodes in which each character appears. To do so, we'll\nfirst define an enum, which lists the three episodes in the trilogy:\n\n```graphql\nenum Episode { NEWHOPE, EMPIRE, JEDI }\n```\n\nNow we want to add a field to `Human` describing what episodes they\nwere in. This will return a list of `Episode`s:\n\n```graphql\ntype Human {\n  id: String\n  name: String\n  appearsIn: [Episode]\n  homePlanet: String\n}\n```\n\nNow, let's introduce another type, `Droid`:\n\n\n```graphql\ntype Droid {\n  id: String\n  name: String\n  appearsIn: [Episode]\n  primaryFunction: String\n}\n```\n\nNow we have two types! Let's add a way of going between them: humans\nand droids both have friends. But humans can be friends with both\nhumans and droids. How do we refer to either a human or a droid?\n\nIf we look, we note that there's common functionality between\nhumans and droids; they both have IDs, names, and episodes in which\nthey appear. So we'll add an interface, `Character`, and make\nboth `Human` and `Droid` implement it. Once we have that, we can\nadd the `friends` field, that returns a list of `Character`s.\n\nOur type system so far is:\n\n```graphql\nenum Episode { NEWHOPE, EMPIRE, JEDI }\n\ninterface Character {\n  id: String\n  name: String\n  friends: [Character]\n  appearsIn: [Episode]\n}\n\ntype Human implements Character {\n  id: String\n  name: String\n  friends: [Character]\n  appearsIn: [Episode]\n  homePlanet: String\n}\n\ntype Droid implements Character {\n  id: String\n  name: String\n  friends: [Character]\n  appearsIn: [Episode]\n  primaryFunction: String\n}\n```\n\nOne question we might ask, though, is whether any of those fields can return\n`null`. By default, `null` is a permitted value for any type in GraphQL,\nsince fetching data to fulfill a GraphQL query often requires talking\nto different services that may or may not be available. However, if the\ntype system can guarantee that a type is never null, then we can mark\nit as Non Null in the type system. We indicate that in our shorthand\nby adding an \"!\" after the type. We can update our type system to note\nthat the `id` is never null.\n\nNote that while in our current implementation, we can guarantee that more\nfields are non-null (since our current implementation has hard-coded data),\nwe didn't mark them as non-null. One can imagine we would eventually\nreplace our hardcoded data with a backend service, which might not be\nperfectly reliable; by leaving these fields as nullable, we allow\nourselves the flexibility to eventually return null to indicate a backend\nerror, while also telling the client that the error occurred.\n\n```graphql\nenum Episode { NEWHOPE, EMPIRE, JEDI }\n\ninterface Character {\n  id: String!\n  name: String\n  friends: [Character]\n  appearsIn: [Episode]\n}\n\ntype Human implements Character {\n  id: String!\n  name: String\n  friends: [Character]\n  appearsIn: [Episode]\n  homePlanet: String\n}\n\ntype Droid implements Character {\n  id: String!\n  name: String\n  friends: [Character]\n  appearsIn: [Episode]\n  primaryFunction: String\n}\n```\n\nWe're missing one last piece: an entry point into the type system.\n\nWhen we define a schema, we define an object type that is the basis for all\nqueries. The name of this type is `Query` by convention, and it describes\nour public, top-level API. Our `Query` type for this example will look like\nthis:\n\n```graphql\ntype Query {\n  hero(episode: Episode): Character\n  human(id: String!): Human\n  droid(id: String!): Droid\n}\n```\n\nIn this example, there are three top-level operations\nthat can be done on our schema:\n\n - `hero` returns the `Character` who is the hero of the Star Wars trilogy; it\ntakes an optional argument that allows us to fetch the hero of a specific\nepisode instead.\n - `human` accepts a non-null string as a query argument, a human's ID, and\nreturns the human with that ID.\n - `droid` does the same for droids.\n\nThese fields demonstrate another feature of the type system, the ability\nfor a field to specify arguments that configure their behavior.\n\nWhen we package the whole type system together, defining the `Query` type\nabove as our entry point for queries, this creates a GraphQL Schema.\n\nThis example just scratched the surface of the type system. The specification\ngoes into more detail about this topic in the \"Type System\" section, and the [type](https://github.com/graphql/graphql-js/blob/master/src/type)\ndirectory in GraphQL.js contains code implementing\na specification-compliant GraphQL type system.\n\n### Query Syntax\n\nGraphQL queries declaratively describe what data the issuer wishes\nto fetch from whoever is fulfilling the GraphQL query.\n\nFor our Star Wars example, the\n[starWarsQueryTests.js](https://github.com/graphql/graphql-js/blob/master/src/__tests__/starWarsQuery-test.js)\nfile in the GraphQL.js repository contains a number of queries and responses.\nThat file is a test file that uses the schema discussed above and a set of\nsample data, located in\n[starWarsData.js](https://github.com/graphql/graphql-js/blob/master/src/__tests__/starWarsData.js).\nThis test file can be run to exercise the reference implementation.\n\nAn example query on the above schema would be:\n\n```graphql\nquery HeroNameQuery {\n  hero {\n    name\n  }\n}\n```\n\nThe initial line, `query HeroNameQuery`, defines a query with the operation\nname `HeroNameQuery` that starts with the schema's root query type; in this\ncase, `Query`. As defined above, `Query` has a `hero` field that returns a\n`Character`, so we'll query for that. `Character` then has a `name` field that\nreturns a `String`, so we query for that, completing our query. The result of\nthis query would then be:\n\n\n```json\n{\n  \"hero\": {\n    \"name\": \"R2-D2\"\n  }\n}\n```\n\nSpecifying the `query` keyword and an operation name is only required when a\nGraphQL document defines multiple operations.  We therefore could have written\nthe previous query with the query shorthand:\n\n```graphql\n{\n  hero {\n    name\n  }\n}\n```\n\nAssuming that the backing data for the GraphQL server identified R2-D2 as the\nhero. The response continues to vary based on the request; if we asked for\nR2-D2's ID and friends with this query:\n\n```graphql\nquery HeroNameAndFriendsQuery {\n  hero {\n    id\n    name\n    friends {\n      id\n      name\n    }\n  }\n}\n```\n\nthen we'll get back a response like this:\n\n```json\n{\n  \"hero\": {\n    \"id\": \"2001\",\n    \"name\": \"R2-D2\",\n    \"friends\": [\n      {\n        \"id\": \"1000\",\n        \"name\": \"Luke Skywalker\"\n      },\n      {\n        \"id\": \"1002\",\n        \"name\": \"Han Solo\"\n      },\n      {\n        \"id\": \"1003\",\n        \"name\": \"Leia Organa\"\n      }\n    ]\n  }\n}\n```\n\nOne of the key aspects of GraphQL is its ability to nest queries. In the\nabove query, we asked for R2-D2's friends, but we can ask for more information\nabout each of those objects. So let's construct a query that asks for R2-D2's\nfriends, gets their name and episode appearances, then asks for each of *their*\nfriends.\n\n```graphql\nquery NestedQuery {\n  hero {\n    name\n    friends {\n      name\n      appearsIn\n      friends {\n        name\n      }\n    }\n  }\n}\n```\n\nwhich will give us the nested response\n\n```json\n{\n  \"hero\": {\n    \"name\": \"R2-D2\",\n    \"friends\": [\n      {\n        \"name\": \"Luke Skywalker\",\n        \"appearsIn\": [ \"NEWHOPE\", \"EMPIRE\", \"JEDI\" ],\n        \"friends\": [\n          { \"name\": \"Han Solo\" },\n          { \"name\": \"Leia Organa\" },\n          { \"name\": \"C-3PO\" },\n          { \"name\": \"R2-D2\" }\n        ]\n      },\n      {\n        \"name\": \"Han Solo\",\n        \"appearsIn\": [ \"NEWHOPE\", \"EMPIRE\", \"JEDI\" ],\n        \"friends\": [\n          { \"name\": \"Luke Skywalker\" },\n          { \"name\": \"Leia Organa\" },\n          { \"name\": \"R2-D2\" }\n        ]\n      },\n      {\n        \"name\": \"Leia Organa\",\n        \"appearsIn\": [ \"NEWHOPE\", \"EMPIRE\", \"JEDI\" ],\n        \"friends\": [\n          { \"name\": \"Luke Skywalker\" },\n          { \"name\": \"Han Solo\" },\n          { \"name\": \"C-3PO\" },\n          { \"name\": \"R2-D2\" }\n        ]\n      }\n    ]\n  }\n}\n```\n\nThe `Query` type above defined a way to fetch a human given their\nID. We can use it by hardcoding the ID in the query:\n\n```graphql\nquery FetchLukeQuery {\n  human(id: \"1000\") {\n    name\n  }\n}\n```\n\nto get\n\n```json\n{\n  \"human\": {\n    \"name\": \"Luke Skywalker\"\n  }\n}\n```\n\nAlternately, we could have defined the query to have a query parameter:\n\n```graphql\nquery FetchSomeIDQuery($someId: String!) {\n  human(id: $someId) {\n    name\n  }\n}\n```\n\nThis query is now parameterized by `$someId`; to run it, we must provide\nthat ID. If we ran it with `$someId` set to \"1000\", we would get Luke;\nset to \"1002\", we would get Han. If we passed an invalid ID here,\nwe would get `null` back for the `human`, indicating that no such object\nexists.\n\nNotice that the key in the response is the name of the field, by default.\nIt is sometimes useful to change this key, for clarity or to avoid key\ncollisions when fetching the same field with different arguments.\n\nWe can do that with field aliases, as demonstrated in this query:\n\n```graphql\nquery FetchLukeAliased {\n  luke: human(id: \"1000\") {\n    name\n  }\n}\n```\n\nWe aliased the result of the `human` field to the key `luke`. Now the response\nis:\n\n```json\n{\n  \"luke\": {\n    \"name\": \"Luke Skywalker\"\n  }\n}\n```\n\nNotice the key is \"luke\" and not \"human\", as it was in our previous example\nwhere we did not use the alias.\n\nThis is particularly useful if we want to use the same field twice\nwith different arguments, as in the following query:\n\n```graphql\nquery FetchLukeAndLeiaAliased {\n  luke: human(id: \"1000\") {\n    name\n  }\n  leia: human(id: \"1003\") {\n    name\n  }\n}\n```\n\nWe aliased the result of the first `human` field to the key\n`luke`, and the second to `leia`. So the result will be:\n\n```json\n{\n  \"luke\": {\n    \"name\": \"Luke Skywalker\"\n  },\n  \"leia\": {\n    \"name\": \"Leia Organa\"\n  }\n}\n```\n\nNow imagine we wanted to ask for Luke and Leia's home planets. We could do so\nwith this query:\n\n```graphql\nquery DuplicateFields {\n  luke: human(id: \"1000\") {\n    name\n    homePlanet\n  }\n  leia: human(id: \"1003\") {\n    name\n    homePlanet\n  }\n}\n```\n\nbut we can already see that this could get unwieldy, since we have to add new\nfields to both parts of the query. Instead, we can extract out the common fields\ninto a fragment, and include the fragment in the query, like this:\n\n```graphql\nquery UseFragment {\n  luke: human(id: \"1000\") {\n    ...HumanFragment\n  }\n  leia: human(id: \"1003\") {\n    ...HumanFragment\n  }\n}\n\nfragment HumanFragment on Human {\n  name\n  homePlanet\n}\n```\n\nBoth of those queries give this result:\n\n```json\n{\n  \"luke\": {\n    \"name\": \"Luke Skywalker\",\n    \"homePlanet\": \"Tatooine\"\n  },\n  \"leia\": {\n    \"name\": \"Leia Organa\",\n    \"homePlanet\": \"Alderaan\"\n  }\n}\n```\n\nThe `UseFragment` and `DuplicateFields` queries will both get the same result, but\n`UseFragment` is less verbose; if we wanted to add more fields, we could add\nit to the common fragment rather than copying it into multiple places.\n\nWe defined the type system above, so we know the type of each object\nin the output; the query can ask for that type using the special\nfield `__typename`, defined on every object.\n\n```graphql\nquery CheckTypeOfR2 {\n  hero {\n    __typename\n    name\n  }\n}\n```\n\nSince R2-D2 is a droid, this will return\n\n```json\n{\n  \"hero\": {\n    \"__typename\": \"Droid\",\n    \"name\": \"R2-D2\"\n  }\n}\n```\n\nThis was particularly useful because `hero` was defined to return a `Character`,\nwhich is an interface; we might want to know what concrete type was actually\nreturned. If we instead asked for the hero of Episode V:\n\n```graphql\nquery CheckTypeOfLuke {\n  hero(episode: EMPIRE) {\n    __typename\n    name\n  }\n}\n```\n\nWe would find that it was Luke, who is a Human:\n\n```json\n{\n  \"hero\": {\n    \"__typename\": \"Human\",\n    \"name\": \"Luke Skywalker\"\n  }\n}\n```\n\nAs with the type system, this example just scratched the surface of the query\nlanguage. The specification goes into more detail about this topic in the\n\"Language\" section, and the\n[language](https://github.com/graphql/graphql-js/blob/master/src/language)\ndirectory in GraphQL.js contains code implementing a\nspecification-compliant GraphQL query language parser and lexer.\n\n### Validation\n\nBy using the type system, it can be predetermined whether a GraphQL query\nis valid or not. This allows servers and clients to effectively inform\ndevelopers when an invalid query has been created, without having to rely\non runtime checks.\n\nFor our Star Wars example, the file\n[starWarsValidationTests.js](https://github.com/graphql/graphql-js/blob/master/src/__tests__/starWarsValidation-test.js)\ncontains a number of queries demonstrating various invalidities, and is a test\nfile that can be run to exercise the reference implementation's validator.\n\nTo start, let's take a complex valid query. This is the `NestedQuery` example\nfrom the above section, but with the duplicated fields factored out into\na fragment:\n\n```graphql\nquery NestedQueryWithFragment {\n  hero {\n    ...NameAndAppearances\n    friends {\n      ...NameAndAppearances\n      friends {\n        ...NameAndAppearances\n      }\n    }\n  }\n}\n\nfragment NameAndAppearances on Character {\n  name\n  appearsIn\n}\n```\n\nAnd this query is valid. Let's take a look at some invalid queries!\n\nWhen we query for fields, we have to query for a field that exists on the\ngiven type. So as `hero` returns a `Character`, we have to query for a field\non `Character`. That type does not have a `favoriteSpaceship` field, so this\nquery:\n\n```graphql\n# INVALID: favoriteSpaceship does not exist on Character\nquery HeroSpaceshipQuery {\n  hero {\n    favoriteSpaceship\n  }\n}\n```\n\nis invalid.\n\nWhenever we query for a field and it returns something other than a scalar\nor an enum, we need to specify what data we want to get back from the field.\nHero returns a `Character`, and we've been requesting fields like `name` and\n`appearsIn` on it; if we omit that, the query will not be valid:\n\n```graphql\n# INVALID: hero is not a scalar, so fields are needed\nquery HeroNoFieldsQuery {\n  hero\n}\n```\n\nSimilarly, if a field is a scalar, it doesn't make sense to query for\nadditional fields on it, and doing so will make the query invalid:\n\n```graphql\n# INVALID: name is a scalar, so fields are not permitted\nquery HeroFieldsOnScalarQuery {\n  hero {\n    name {\n      firstCharacterOfName\n    }\n  }\n}\n```\n\nEarlier, it was noted that a query can only query for fields on the type\nin question; when we query for `hero` which returns a `Character`, we\ncan only query for fields that exist on `Character`. What happens if we\nwant to query for R2-D2s primary function, though?\n\n```graphql\n# INVALID: primaryFunction does not exist on Character\nquery DroidFieldOnCharacter {\n  hero {\n    name\n    primaryFunction\n  }\n}\n```\n\nThat query is invalid, because `primaryFunction` is not a field on `Character`.\nWe want some way of indicating that we wish to fetch `primaryFunction` if the\n`Character` is a `Droid`, and to ignore that field otherwise. We can use\nthe fragments we introduced earlier to do this. By setting up a fragment defined\non `Droid` and including it, we ensure that we only query for `primaryFunction`\nwhere it is defined.\n\n```graphql\nquery DroidFieldInFragment {\n  hero {\n    name\n    ...DroidFields\n  }\n}\n\nfragment DroidFields on Droid {\n  primaryFunction\n}\n```\n\nThis query is valid, but it's a bit verbose; named fragments were valuable\nabove when we used them multiple times, but we're only using this one once.\nInstead of using a named fragment, we can use an inline fragment; this\nstill allows us to indicate the type we are querying on, but without naming\na separate fragment:\n\n```graphql\nquery DroidFieldInInlineFragment {\n  hero {\n    name\n    ... on Droid {\n      primaryFunction\n    }\n  }\n}\n```\n\nThis has just scratched the surface of the validation system; there\nare a number of validation rules in place to ensure that a GraphQL query\nis semantically meaningful. The specification goes into more detail about this\ntopic in the \"Validation\" section, and the\n[validation](https://github.com/graphql/graphql-js/blob/master/src/validation)\ndirectory in GraphQL.js contains code implementing a\nspecification-compliant GraphQL validator.\n\n### Introspection\n\nIt's often useful to ask a GraphQL schema for information about what\nqueries it supports. GraphQL allows us to do so using the introspection\nsystem!\n\nFor our Star Wars example, the file\n[starWarsIntrospectionTests.js](https://github.com/graphql/graphql-js/blob/master/src/__tests__/starWarsIntrospection-test.js)\ncontains a number of queries demonstrating the introspection system, and is a\ntest file that can be run to exercise the reference implementation's\nintrospection system.\n\nWe designed the type system, so we know what types are available, but if\nwe didn't, we can ask GraphQL, by querying the `__schema` field, always\navailable on the root type of a Query. Let's do so now, and ask what types\nare available.\n\n```graphql\nquery IntrospectionTypeQuery {\n  __schema {\n    types {\n      name\n    }\n  }\n}\n```\n\nand we get back:\n\n```json\n{\n  \"__schema\": {\n    \"types\": [\n      {\n        \"name\": \"Query\"\n      },\n      {\n        \"name\": \"Character\"\n      },\n      {\n        \"name\": \"Human\"\n      },\n      {\n        \"name\": \"String\"\n      },\n      {\n        \"name\": \"Episode\"\n      },\n      {\n        \"name\": \"Droid\"\n      },\n      {\n        \"name\": \"__Schema\"\n      },\n      {\n        \"name\": \"__Type\"\n      },\n      {\n        \"name\": \"__TypeKind\"\n      },\n      {\n        \"name\": \"Boolean\"\n      },\n      {\n        \"name\": \"__Field\"\n      },\n      {\n        \"name\": \"__InputValue\"\n      },\n      {\n        \"name\": \"__EnumValue\"\n      },\n      {\n        \"name\": \"__Directive\"\n      }\n    ]\n  }\n}\n```\n\nWow, that's a lot of types! What are they? Let's group them:\n\n - **Query, Character, Human, Episode, Droid** - These are the ones that we\ndefined in our type system.\n - **String, Boolean** - These are built-in scalars that the type system\nprovided.\n - **__Schema, __Type, __TypeKind, __Field, __InputValue, __EnumValue,\n__Directive** - These all are preceded with a double underscore, indicating\nthat they are part of the introspection system.\n\nNow, let's try and figure out a good place to start exploring what queries are\navailable. When we designed our type system, we specified what type all queries\nwould start at; let's ask the introspection system about that!\n\n```graphql\nquery IntrospectionQueryTypeQuery {\n  __schema {\n    queryType {\n      name\n    }\n  }\n}\n```\n\nand we get back:\n\n```json\n{\n  \"__schema\": {\n    \"queryType\": {\n      \"name\": \"Query\"\n    }\n  }\n}\n```\n\nAnd that matches what we said in the type system section, that\nthe `Query` type is where we will start! Note that the naming here\nwas just by convention; we could have named our `Query` type anything\nelse, and it still would have been returned here if we had specified it\nas the starting type for queries. Naming it `Query`, though, is a useful\nconvention.\n\nIt is often useful to examine one specific type. Let's take a look at\nthe `Droid` type:\n\n\n```graphql\nquery IntrospectionDroidTypeQuery {\n  __type(name: \"Droid\") {\n    name\n  }\n}\n```\n\nand we get back:\n\n```json\n{\n  \"__type\": {\n    \"name\": \"Droid\"\n  }\n}\n```\n\nWhat if we want to know more about Droid, though? For example, is it\nan interface or an object?\n\n```graphql\nquery IntrospectionDroidKindQuery {\n  __type(name: \"Droid\") {\n    name\n    kind\n  }\n}\n```\n\nand we get back:\n\n```json\n{\n  \"__type\": {\n    \"name\": \"Droid\",\n    \"kind\": \"OBJECT\"\n  }\n}\n```\n\n`kind` returns a `__TypeKind` enum, one of whose values is `OBJECT`. If\nwe asked about `Character` instead:\n\n\n```graphql\nquery IntrospectionCharacterKindQuery {\n  __type(name: \"Character\") {\n    name\n    kind\n  }\n}\n```\n\nand we get back:\n\n```json\n{\n  \"__type\": {\n    \"name\": \"Character\",\n    \"kind\": \"INTERFACE\"\n  }\n}\n```\n\nWe'd find that it is an interface.\n\nIt's useful for an object to know what fields are available, so let's\nask the introspection system about `Droid`:\n\n```graphql\nquery IntrospectionDroidFieldsQuery {\n  __type(name: \"Droid\") {\n    name\n    fields {\n      name\n      type {\n        name\n        kind\n      }\n    }\n  }\n}\n```\n\nand we get back:\n\n```json\n{\n  \"__type\": {\n    \"name\": \"Droid\",\n    \"fields\": [\n      {\n        \"name\": \"id\",\n        \"type\": {\n          \"name\": null,\n          \"kind\": \"NON_NULL\"\n        }\n      },\n      {\n        \"name\": \"name\",\n        \"type\": {\n          \"name\": \"String\",\n          \"kind\": \"SCALAR\"\n        }\n      },\n      {\n        \"name\": \"friends\",\n        \"type\": {\n          \"name\": null,\n          \"kind\": \"LIST\"\n        }\n      },\n      {\n        \"name\": \"appearsIn\",\n        \"type\": {\n          \"name\": null,\n          \"kind\": \"LIST\"\n        }\n      },\n      {\n        \"name\": \"primaryFunction\",\n        \"type\": {\n          \"name\": \"String\",\n          \"kind\": \"SCALAR\"\n        }\n      }\n    ]\n  }\n}\n```\n\nThose are our fields that we defined on `Droid`!\n\n`id` looks a bit weird there, it has no name for the type. That's\nbecause it's a \"wrapper\" type of kind `NON_NULL`. If we queried for\n`ofType` on that field's type, we would find the `String` type there,\ntelling us that this is a non-null String.\n\nSimilarly, both `friends` and `appearsIn` have no name, since they are the\n`LIST` wrapper type. We can query for `ofType` on those types, which will\ntell us what these are lists of.\n\n```graphql\nquery IntrospectionDroidWrappedFieldsQuery {\n  __type(name: \"Droid\") {\n    name\n    fields {\n      name\n      type {\n        name\n        kind\n        ofType {\n          name\n          kind\n        }\n      }\n    }\n  }\n}\n```\n\nand we get back:\n\n```json\n{\n  \"__type\": {\n    \"name\": \"Droid\",\n    \"fields\": [\n      {\n        \"name\": \"id\",\n        \"type\": {\n          \"name\": null,\n          \"kind\": \"NON_NULL\",\n          \"ofType\": {\n            \"name\": \"String\",\n            \"kind\": \"SCALAR\"\n          }\n        }\n      },\n      {\n        \"name\": \"name\",\n        \"type\": {\n          \"name\": \"String\",\n          \"kind\": \"SCALAR\",\n          \"ofType\": null\n        }\n      },\n      {\n        \"name\": \"friends\",\n        \"type\": {\n          \"name\": null,\n          \"kind\": \"LIST\",\n          \"ofType\": {\n            \"name\": \"Character\",\n            \"kind\": \"INTERFACE\"\n          }\n        }\n      },\n      {\n        \"name\": \"appearsIn\",\n        \"type\": {\n          \"name\": null,\n          \"kind\": \"LIST\",\n          \"ofType\": {\n            \"name\": \"Episode\",\n            \"kind\": \"ENUM\"\n          }\n        }\n      },\n      {\n        \"name\": \"primaryFunction\",\n        \"type\": {\n          \"name\": \"String\",\n          \"kind\": \"SCALAR\",\n          \"ofType\": null\n        }\n      }\n    ]\n  }\n}\n```\n\nLet's end with a feature of the introspection system particularly useful\nfor tooling; let's ask the system for documentation!\n\n```graphql\nquery IntrospectionDroidDescriptionQuery {\n  __type(name: \"Droid\") {\n    name\n    description\n  }\n}\n```\n\nyields\n\n```json\n{\n  \"__type\": {\n    \"name\": \"Droid\",\n    \"description\": \"A mechanical creature in the Star Wars universe.\"\n  }\n}\n```\n\nSo we can access the documentation about the type system using introspection,\nand create documentation browsers, or rich IDE experiences.\n\nThis has just scratched the surface of the introspection system; we can\nquery for enum values, what interfaces a type implements, and more. We\ncan even introspect on the introspection system itself. The specification goes\ninto more detail about this topic in the \"Introspection\" section, and the [introspection](https://github.com/graphql/graphql-js/blob/master/src/type/introspection.js)\nfile in GraphQL.js\ncontains code implementing a specification-compliant GraphQL query\nintrospection system.\n\n### Additional Content\n\nThis README walked through the GraphQL.js reference implementation's type\nsystem, query execution, validation, and introspection systems. There's more\nin both [GraphQL.js](https://github.com/graphql/graphql-js/) and specification,\nincluding a description and implementation for executing queries, how to format\na response, explaining how a type system maps to an underlying implementation,\nand how to format a GraphQL response, as well as a grammar for GraphQL.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffibjs%2Ffib-graphql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffibjs%2Ffib-graphql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffibjs%2Ffib-graphql/lists"}