├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .husky └── pre-commit ├── .prettierrc.js ├── .travis.yml ├── LICENSE ├── README.md ├── jest.config.js ├── package.json ├── src ├── diffSchema.js ├── index.js ├── loadSchemaJSON.js ├── renderSchema.js └── updateSchema.js ├── test ├── __snapshots__ │ └── index.test.js.snap ├── fixtures │ ├── cover-art-archive.js │ ├── cover-art-archive.md │ ├── graphbrainz-updateSchema-initial.md │ ├── graphbrainz-updateSchema-updated.md │ ├── graphbrainz-updateSchema.js │ ├── graphbrainz.graphql │ ├── graphbrainz.md │ ├── input-objects.graphql │ ├── input-objects.md │ ├── no-toc.md │ ├── toc-fields.md │ ├── union-test-2.graphql │ ├── union-test-2.md │ ├── union-test.graphql │ └── union-test.md └── index.test.js └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | /.nyc_output 2 | /coverage 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['standard', 'prettier'], 3 | env: { 4 | es6: true, 5 | node: true, 6 | jest: true, 7 | }, 8 | parserOptions: { 9 | ecmaVersion: 2018, 10 | }, 11 | plugins: ['prettier'], 12 | rules: { 13 | 'prettier/prettier': [ 14 | 'warn', 15 | { 16 | singleQuote: true, 17 | semi: false, 18 | }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | lint-staged 5 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | proseWrap: "always" 3 | }; 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - '10' 5 | - '12' 6 | - '14' 7 | - '15' 8 | 9 | # Use container-based Travis infrastructure. 10 | sudo: false 11 | 12 | branches: 13 | only: 14 | - master 15 | - /^greenkeeper/.*$/ 16 | 17 | script: 18 | - yarn test 19 | 20 | after_success: 21 | - yarn run coverage 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016–2018 Brian Beck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # graphql-markdown 4 | 5 | **The easiest way to document your GraphQL schema.** 6 | 7 | [![npm version](https://img.shields.io/npm/v/graphql-markdown.svg)](https://www.npmjs.com/package/graphql-markdown) 8 | 9 |
10 | 11 | --- 12 | 13 | This package will generate Markdown that beautifully renders your GraphQL schema 14 | in an easily explorable document. 15 | 16 | ```console 17 | $ yarn add graphql-markdown --dev 18 | $ npm install graphql-markdown --save-dev 19 | ``` 20 | 21 | **[See an example][example]** generated from the [GraphBrainz][] schema. 22 | 23 | ## Support 24 | 25 | Did this project bring you joy? Want to support updates? Check out 26 | [my GitHub Sponsors page](https://github.com/sponsors/exogen). 27 | 28 | Alternatively… 29 | 30 | Buy Me A Coffee 31 | 32 | ## Usage 33 | 34 | ### Command Line API 35 | 36 | Installing the package adds a `graphql-markdown` script via the standard package.json 37 | [`bin`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#bin) field – see 38 | npm’s [Executables](https://docs.npmjs.com/cli/v10/configuring-npm/folders#executables) 39 | documentation to learn where this will be on your system. For local installs, 40 | this is typically `node_modules/.bin`. When referencing the executable in 41 | your package.json’s `scripts`, you may simply call `graphql-markdown`. 42 | 43 | Point the `graphql-markdown` script at a schema and the output will be written 44 | to stdout. You must install `graphql` alongside this package according to the 45 | [compatible versions specified in `peerDependencies`](./package.json). 46 | 47 | The schema may be retrieved from a GraphQL endpoint: 48 | 49 | ```console 50 | $ graphql-markdown http://your-server.com/graphql > schema.md 51 | ``` 52 | 53 | …or a module exporting an instance of `GraphQLSchema`: 54 | 55 | ```console 56 | $ graphql-markdown ./path/to/schema.js > schema.md 57 | ``` 58 | 59 | …or a file containing GraphQL syntax: 60 | 61 | ```console 62 | $ graphql-markdown ./path/to/schema.graphql > schema.md 63 | ``` 64 | 65 | …or a file containing the JSON output of an introspection query: 66 | 67 | ```console 68 | $ graphql-markdown ./path/to/schema.json > schema.md 69 | ``` 70 | 71 | If `--update-file` is given, the generated Markdown will be output to the given 72 | file between the `` and 73 | `` comment markers instead of printed to STDOUT. If 74 | the file does not exist, it will be created (and will include the comment 75 | markers for future updates). Use this if you’d like to embed the rendered 76 | Markdown as just one part of a larger document (see also the `--heading-level` 77 | option). 78 | 79 | #### Options 80 | 81 | ```console 82 | $ graphql-markdown --help 83 | 84 | Usage: graphql-markdown [options] 85 | 86 | Output a Markdown document with rendered descriptions and links between types. 87 | The schema may be specified as: 88 | 89 | - a URL to the GraphQL endpoint (the introspection query will be run) 90 | - a GraphQL document containing the schema (.graphql or .gql) 91 | - a JSON document containing the schema (as returned by the introspection query) 92 | - an importable module with the schema as its default export (either an instance 93 | of GraphQLSchema or a JSON object) 94 | 95 | Options: 96 | 97 | --title Change the top heading title (default: 'Schema Types') 98 | --no-title Do not print a default title 99 | --no-toc Do not print table of contents 100 | --toc-fields Expand the table of contents for the listed types 101 | (comma-separated) to link to fields within those types 102 | (e.g. --toc-fields "Query,Mutation,Subscription") or use 103 | the string "*" to link to fields for all types 104 | --prologue Include custom Markdown after the title 105 | --epilogue Include custom Markdown after everything else 106 | --heading-level Heading level to begin at, useful if you are embedding the 107 | output in a document with other sections (default: 1) 108 | --update-file Markdown document to update (between comment markers) or 109 | create (if the file does not exist) 110 | --require If importing the schema from a module, require the specified 111 | module first (useful for e.g. babel-register) 112 | --header Additional header(s) to use in GraphQL request 113 | e.g. --header "Authorization=Bearer ey..." 114 | --version Print version and exit 115 | ``` 116 | 117 | ### Node API 118 | 119 | The following functions are exported from the `graphql-markdown` module for 120 | programmatic use. 121 | 122 | #### loadSchemaJSON(schemaPath: string, options: object) 123 | 124 | Given a string pointing to a GraphQL schema (URL, module, or file path), get the 125 | result of the introspection query, suitable for use as input to `renderSchema`. 126 | 127 | #### renderSchema(schema: object, options: object) 128 | 129 | Given a schema JSON object (the output of the introspection query, an object 130 | with a `__schema` property), render the schema to the console or the provided 131 | `printer` function. 132 | 133 | ##### Options 134 | 135 | - **`title`**: The title of the document, defaults to “Schema Types”. 136 | - **`prologue`**: Markdown content to include after the title. 137 | - **`epilogue`**: Markdown content to include after everything else. 138 | - **`printer`**: A function to handle each line of output, defaults to 139 | `console.log`. 140 | - **`skipTableOfContents`**: When set, rendering of "Table of contents" section 141 | is skipped. 142 | - **`tocFieldTypes`**: An array of type names whose table of contents entry will 143 | be expanded to link to individual fields in a nested list. Include the special 144 | name `*` in the array to match all types. 145 | - **`headingLevel`**: The initial level at which to render Markdown headings in 146 | the output, defaults to 1. Use this if you are using `updateSchema` to embed 147 | the output in a larger document with other sections. 148 | - **`unknownTypeURL`**: A string or function to determine the URL for linking to 149 | types that aren’t found in the schema being rendered. This may be the case if 150 | you’re rendering the result of `diffSchema()`, for example. String values will 151 | have `#${type.name.toLowerCase()}` appended, and function values will be 152 | called with the type object for full control. 153 | 154 | #### updateSchema(path: string, schema: object, options: object) 155 | 156 | Given a path to a Markdown document, inject the output of `renderSchema` (with 157 | the given schema and options) into the document between the comment markers 158 | `` and ``. Returns a 159 | Promise. 160 | 161 | If the file does not exist, it will be created. If the document is empty, the 162 | necessary comment markers will automatically be inserted, but if there is 163 | existing content and no comment markers, the Promise will be rejected with an 164 | error. 165 | 166 | #### diffSchema(oldSchema: object, newSchema: object, options: object) 167 | 168 | Given two schema JSON objects (the results of the introspection query on two 169 | schemas), return a new schema JSON object containing only the added or updated 170 | types and fields. You can use this to document a schema update, or to document 171 | the effects of a schema extension (e.g. `extend type` definitions). 172 | 173 | ##### Options 174 | 175 | - **`processTypeDiff`**: A function to add or modify fields on each type that 176 | will be output. 177 | 178 | ## Output 179 | 180 | Output is optimized for display on GitHub, using GitHub Flavored Markdown. Due 181 | to the complexity of the tables in the generated document, much of the table 182 | output is raw HTML (as allowed by Markdown). 183 | 184 | [example]: https://github.com/exogen/graphbrainz/blob/master/docs/types.md 185 | [graphbrainz]: https://github.com/exogen/graphbrainz 186 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collectCoverageFrom: ['src/**'], 3 | } 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-markdown", 3 | "version": "7.3.0", 4 | "description": "Generate documentation for your GraphQL schema in Markdown", 5 | "main": "src/index.js", 6 | "bin": "src/index.js", 7 | "repository": "git@github.com:exogen/graphql-markdown.git", 8 | "author": "Brian Beck ", 9 | "license": "MIT", 10 | "engines": { 11 | "node": ">=14.0.0" 12 | }, 13 | "files": [ 14 | "src", 15 | "yarn.lock" 16 | ], 17 | "scripts": { 18 | "coverage": "cat coverage/lcov.info | coveralls", 19 | "format": "npm run lint:fix || true", 20 | "lint": "eslint .", 21 | "lint:fix": "eslint --fix .", 22 | "prepare": "husky install", 23 | "test": "npm run lint && npm run test:coverage", 24 | "test:coverage": "jest --coverage", 25 | "test:only": "jest" 26 | }, 27 | "lint-staged": { 28 | "*.js": [ 29 | "eslint --fix" 30 | ] 31 | }, 32 | "peerDependencies": { 33 | "graphql": "^14.0.2 || ^15.0.0 || ^16.0.0" 34 | }, 35 | "dependencies": { 36 | "deep-diff": "^1.0.2", 37 | "lodash.isplainobject": "^4.0.6", 38 | "minimist": "^1.2.6", 39 | "node-fetch": "^2.0.0", 40 | "resolve-from": "^5.0.0" 41 | }, 42 | "devDependencies": { 43 | "coveralls": "^3.1.1", 44 | "eslint": "^8.24.0", 45 | "eslint-config-prettier": "^8.5.0", 46 | "eslint-config-standard": "^17.0.0", 47 | "eslint-plugin-import": "^2.26.0", 48 | "eslint-plugin-n": "^15.3.0", 49 | "eslint-plugin-node": "^11.1.0", 50 | "eslint-plugin-prettier": "^4.2.1", 51 | "eslint-plugin-promise": "^6.0.1", 52 | "eslint-plugin-standard": "^5.0.0", 53 | "graphbrainz": "^8.0.0", 54 | "graphql": "^16.0.0", 55 | "husky": "^8.0.1", 56 | "jest": "^29.1.2", 57 | "lint-staged": "^13.0.3", 58 | "prettier": "^2.7.1", 59 | "tempy": "^1.0.0" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/diffSchema.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const diff = require('deep-diff') 3 | 4 | function toNamedObject(arr, modifier = (obj) => obj) { 5 | if (!arr) { 6 | return {} 7 | } 8 | return arr.reduce((obj, value) => { 9 | obj[value.name] = modifier(value) 10 | return obj 11 | }, {}) 12 | } 13 | 14 | function toNamedArray(obj, modifier = (obj) => obj) { 15 | if (!obj) { 16 | return [] 17 | } 18 | return Object.entries(obj).map(([key, value]) => { 19 | return modifier(Object.assign({}, value, { name: key })) 20 | }) 21 | } 22 | 23 | function toDiffableSchema(schema) { 24 | const types = toNamedObject(schema.__schema.types, (type) => { 25 | if (type.fields) { 26 | type = Object.assign({}, type, { 27 | fields: toNamedObject(type.fields), 28 | }) 29 | } 30 | if (type.enumValues) { 31 | type = Object.assign({}, type, { 32 | enumValues: toNamedObject(type.enumValues), 33 | }) 34 | } 35 | return type 36 | }) 37 | 38 | const directives = toNamedObject(schema.__schema.directives) 39 | 40 | return Object.assign({}, schema, { 41 | __schema: Object.assign({}, schema.__schema, { 42 | types, 43 | directives, 44 | }), 45 | }) 46 | } 47 | 48 | function fromDiffableSchema(schema) { 49 | const types = toNamedArray(schema.__schema.types, (type) => { 50 | if (type.fields) { 51 | type = Object.assign({}, type, { 52 | fields: toNamedArray(type.fields), 53 | }) 54 | } 55 | if (type.enumValues) { 56 | type = Object.assign({}, type, { 57 | enumValues: toNamedArray(type.enumValues), 58 | }) 59 | } 60 | return type 61 | }) 62 | 63 | const directives = toNamedArray(schema.__schema.directives) 64 | 65 | return Object.assign({}, schema, { 66 | __schema: Object.assign({}, schema.__schema, { 67 | types, 68 | directives, 69 | }), 70 | }) 71 | } 72 | 73 | function diffSchema(oldSchema, newSchema, options = {}) { 74 | const oldDiffableSchema = toDiffableSchema(oldSchema) 75 | const newDiffableSchema = toDiffableSchema(newSchema) 76 | const changes = diff(oldDiffableSchema, newDiffableSchema) 77 | const diffSchema = changes.reduce((schema, change) => { 78 | diff.applyChange(schema, newDiffableSchema, change) 79 | return schema 80 | }, {}) 81 | const schema = fromDiffableSchema(diffSchema) 82 | const newTypes = newDiffableSchema.__schema.types 83 | schema.__schema.types = schema.__schema.types.map((type) => { 84 | if (options.processTypeDiff) { 85 | type = options.processTypeDiff(type) 86 | } 87 | type = Object.assign({}, newTypes[type.name], type) 88 | if (type.fields) { 89 | const newFields = newTypes[type.name].fields 90 | type.fields = type.fields.map((field) => newFields[field.name]) 91 | } 92 | if (type.enumValues) { 93 | const newEnumValues = newTypes[type.name].enumValues 94 | type.enumValues = type.enumValues.map( 95 | (enumValue) => newEnumValues[enumValue.name] 96 | ) 97 | } 98 | return type 99 | }) 100 | return schema 101 | } 102 | 103 | module.exports = diffSchema 104 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict' 3 | const parseArgs = require('minimist') 4 | const resolveFrom = require('resolve-from') 5 | const { loadSchemaJSON, schemaToJSON } = require('./loadSchemaJSON') 6 | const renderSchema = require('./renderSchema') 7 | const updateSchema = require('./updateSchema') 8 | const diffSchema = require('./diffSchema') 9 | 10 | function safeExit(code) { 11 | process.on('exit', function () { 12 | process.exit(code) 13 | }) 14 | } 15 | 16 | function printHelp(console) { 17 | const name = require('../package.json').name 18 | console.log(` 19 | Usage: ${name} [options] 20 | 21 | Output a Markdown document with rendered descriptions and links between types. 22 | The schema may be specified as: 23 | 24 | - a URL to the GraphQL endpoint (the introspection query will be run) 25 | - a GraphQL document containing the schema (.graphql or .gql) 26 | - a JSON document containing the schema (as returned by the introspection query) 27 | - an importable module with the schema as its default export (either an instance 28 | of GraphQLSchema or a JSON object) 29 | 30 | Options: 31 | 32 | --title Change the top heading title (default: 'Schema Types') 33 | --no-title Do not print a default title 34 | --no-toc Do not print table of contents 35 | --toc-fields Expand the table of contents for the listed types 36 | (comma-separated) to link to fields within those types 37 | (e.g. --toc-fields "Query,Mutation,Subscription") or use 38 | the string "*" to link to fields for all types 39 | --prologue Include custom Markdown after the title 40 | --epilogue Include custom Markdown after everything else 41 | --heading-level Heading level to begin at, useful if you are embedding the 42 | output in a document with other sections (default: 1) 43 | --update-file Markdown document to update (between comment markers) or 44 | create (if the file does not exist) 45 | --require If importing the schema from a module, require the specified 46 | module first (useful for e.g. babel-register) 47 | --header Additional header(s) to use in GraphQL request 48 | e.g. --header "Authorization=Bearer ey..." 49 | --version Print version and exit 50 | `) 51 | } 52 | 53 | function run( 54 | argv = process.argv.slice(2), 55 | { console = global.console, exit = true } = {} 56 | ) { 57 | const args = parseArgs(argv) 58 | 59 | if (args.help) { 60 | printHelp(console) 61 | } else if (args.version) { 62 | console.log(require('../package.json').version) 63 | } else if (args._.length === 1) { 64 | if (args.require) { 65 | const requirePath = resolveFrom('.', args.require) 66 | if (requirePath) { 67 | require(requirePath) 68 | } else { 69 | throw new Error(`Could not resolve --require module: ${args.require}`) 70 | } 71 | } 72 | const schemaPath = args._[0] 73 | const headers = [].concat(args.header || []).reduce((obj, header) => { 74 | const [key, ...value] = String(header).split('=') 75 | obj[key] = value.join('=') 76 | return obj 77 | }, {}) 78 | const tocFieldTypes = args['toc-fields'] 79 | ? args['toc-fields'].split(',') 80 | : [] 81 | const loadOptions = { headers } 82 | loadSchemaJSON(schemaPath, loadOptions).then((schema) => { 83 | const options = { 84 | title: args.title, 85 | skipTitle: false, 86 | prologue: args.prologue, 87 | epilogue: args.epilogue, 88 | skipTableOfContents: args.toc === false, 89 | headingLevel: args['heading-level'], 90 | tocFieldTypes, 91 | } 92 | if (options.title === false) { 93 | options.title = '' 94 | options.skipTitle = true 95 | } else if (Array.isArray(options.title)) { 96 | options.title.forEach((value) => { 97 | if (typeof value === 'string') { 98 | options.title = value 99 | } else if (value === false) { 100 | options.skipTitle = true 101 | } 102 | }) 103 | } 104 | const updateFile = args['update-file'] 105 | if (updateFile) { 106 | updateSchema(updateFile, schema, options) 107 | .then(() => { 108 | if (exit) { 109 | safeExit(0) 110 | } 111 | }) 112 | .catch((err) => { 113 | console.error(err) 114 | if (exit) { 115 | safeExit(1) 116 | } 117 | }) 118 | } else { 119 | renderSchema(schema, options) 120 | if (exit) { 121 | safeExit(0) 122 | } 123 | } 124 | }) 125 | } else { 126 | printHelp(console) 127 | if (exit) { 128 | safeExit(1) 129 | } 130 | } 131 | } 132 | 133 | module.exports = { 134 | run, 135 | loadSchemaJSON, 136 | schemaToJSON, 137 | renderSchema, 138 | updateSchema, 139 | diffSchema, 140 | } 141 | 142 | if (require.main === module) { 143 | run() 144 | } 145 | -------------------------------------------------------------------------------- /src/loadSchemaJSON.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const fs = require('fs') 3 | const fetch = require('node-fetch') 4 | const graphql = require('graphql') 5 | const resolveFrom = require('resolve-from') 6 | const isPlainObject = require('lodash.isplainobject') 7 | 8 | const DEFAULT_GRAPHQL = graphql 9 | 10 | function readFile(filename) { 11 | return new Promise((resolve, reject) => { 12 | fs.readFile(filename, 'utf8', (err, data) => 13 | err ? reject(err) : resolve(data) 14 | ) 15 | }) 16 | } 17 | 18 | function schemaToJSON(schema, options) { 19 | options = options || {} 20 | const graphql = options.graphql || DEFAULT_GRAPHQL 21 | const source = graphql.getIntrospectionQuery() 22 | return graphql.graphql({ schema, source }).then((result) => { 23 | return result.data 24 | }) 25 | } 26 | 27 | function fetchSchemaJSON(url, options) { 28 | options = options || {} 29 | const graphql = options.graphql || DEFAULT_GRAPHQL 30 | return fetch(url, { 31 | method: 'POST', 32 | headers: { 33 | Accept: 'application/json', 34 | 'Content-Type': 'application/json', 35 | ...options.headers, 36 | }, 37 | body: JSON.stringify({ query: graphql.getIntrospectionQuery() }), 38 | }) 39 | .then((res) => res.json()) 40 | .then((result) => result.data) 41 | } 42 | 43 | function parseSchemaGraphQL(filename, options) { 44 | options = options || {} 45 | const graphql = options.graphql || DEFAULT_GRAPHQL 46 | return readFile(filename).then((data) => graphql.buildSchema(data)) 47 | } 48 | 49 | async function requireSchema(schemaPath) { 50 | const schemaModule = resolveFrom('.', schemaPath) 51 | if (!schemaModule) { 52 | throw new Error(`Could not resolve schema module: ${schemaPath}`) 53 | } 54 | let schema = require(schemaModule) 55 | if (schema) { 56 | if (schema.default) { 57 | schema = schema.default 58 | } 59 | // Allow modules to export a Promise that resolves to a schema. 60 | schema = await schema 61 | } 62 | // Getting `.default` and resolving a potential Promise may have resulted in 63 | // `schema` not being an object anymore. 64 | if (schema) { 65 | if (!isPlainObject(schema)) { 66 | if (schema instanceof DEFAULT_GRAPHQL.GraphQLSchema) { 67 | return schemaToJSON(schema) 68 | } 69 | const graphqlPath = resolveFrom(schemaModule, 'graphql') 70 | if (!graphqlPath) { 71 | throw new Error( 72 | 'Could not import the `graphql` instance used by the given schema' 73 | ) 74 | } 75 | const graphql = require(graphqlPath) 76 | if (schema instanceof graphql.GraphQLSchema) { 77 | return schemaToJSON(schema, { graphql }) 78 | } 79 | } else if (schema.queryType) { 80 | return { __schema: schema } 81 | } else if (schema.__schema) { 82 | return schema 83 | } else if (schema.data && schema.data.__schema) { 84 | return schema.data 85 | } 86 | } 87 | throw new Error( 88 | `Schema not found in ${schemaModule} - check that you are exporting ` + 89 | 'an instance of GraphQLSchema or the result of an introspection query' 90 | ) 91 | } 92 | 93 | function loadSchemaJSON(schemaPath, loadOptions) { 94 | if (schemaPath.indexOf('://') >= 0) { 95 | return fetchSchemaJSON(schemaPath, loadOptions) 96 | } else if (schemaPath.match(/\.g(raph)?ql$/)) { 97 | return parseSchemaGraphQL(schemaPath, loadOptions).then(schemaToJSON) 98 | } 99 | return requireSchema(schemaPath) 100 | } 101 | 102 | module.exports = { loadSchemaJSON, schemaToJSON } 103 | -------------------------------------------------------------------------------- /src/renderSchema.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | function sortBy(arr, property) { 3 | arr.sort((a, b) => { 4 | const aValue = a[property] 5 | const bValue = b[property] 6 | if (aValue > bValue) return 1 7 | if (bValue > aValue) return -1 8 | return 0 9 | }) 10 | } 11 | 12 | function renderType(type, options) { 13 | if (type.kind === 'NON_NULL') { 14 | return renderType(type.ofType, options) + '!' 15 | } 16 | if (type.kind === 'LIST') { 17 | return `[${renderType(type.ofType, options)}]` 18 | } 19 | const url = options.getTypeURL(type) 20 | return url ? `${type.name}` : type.name 21 | } 22 | 23 | function renderObject(type, options) { 24 | options = options || {} 25 | const skipTitle = options.skipTitle === true 26 | const printer = options.printer || console.log 27 | const headingLevel = options.headingLevel || 1 28 | const getTypeURL = options.getTypeURL 29 | const getFieldURL = options.getFieldURL 30 | const isInputObject = type.kind === 'INPUT_OBJECT' 31 | const isInterface = type.kind === 'INTERFACE' 32 | 33 | if (!skipTitle) { 34 | printer(`\n${'#'.repeat(headingLevel + 2)} ${type.name}\n`) 35 | } 36 | if (type.description) { 37 | printer(`${type.description}\n`) 38 | } 39 | printer('') 40 | printer('') 41 | printer('') 42 | if (isInputObject) { 43 | printer('') 44 | } else { 45 | printer('') 46 | printer('') 47 | } 48 | printer('') 49 | printer('') 50 | printer('') 51 | printer('') 52 | printer('') 53 | 54 | const fields = isInputObject ? type.inputFields : type.fields 55 | fields.forEach((field) => { 56 | const url = getFieldURL(type, field) 57 | const anchor = url && url.split('#')[1] 58 | const fieldNameMarkup = anchor 59 | ? `${field.name}` 60 | : `${field.name}` 61 | printer('') 62 | printer( 63 | `` 66 | ) 67 | printer( 68 | `` 72 | ) 73 | if (field.description || field.isDeprecated) { 74 | printer('') 87 | } else { 88 | printer('') 89 | } 90 | printer('') 91 | if (!isInputObject && field.args.length) { 92 | field.args.forEach((arg, i) => { 93 | printer('') 94 | printer(``) 95 | printer( 96 | `` 100 | ) 101 | if (arg.description) { 102 | printer('') 105 | } else { 106 | printer('') 107 | } 108 | printer('') 109 | }) 110 | } 111 | }) 112 | printer('') 113 | printer('
FieldFieldArgumentTypeDescription
${fieldNameMarkup}${ 64 | field.isDeprecated ? ' ⚠️' : '' 65 | }${renderType(field.type, { 69 | getTypeURL, 70 | getFieldURL, 71 | })}') 75 | if (field.description) { 76 | printer(`\n${field.description}\n`) 77 | } 78 | if (field.isDeprecated) { 79 | printer('

⚠️ DEPRECATED

') 80 | if (field.deprecationReason) { 81 | printer('
') 82 | printer(`\n${field.deprecationReason}\n`) 83 | printer('
') 84 | } 85 | } 86 | printer('
${arg.name}${renderType(arg.type, { 97 | getTypeURL, 98 | getFieldURL, 99 | })}') 103 | printer(`\n${arg.description}\n`) 104 | printer('
') 114 | 115 | if (isInterface && type.possibleTypes && type.possibleTypes.length) { 116 | printer( 117 | `\n**Possible Types:** ${type.possibleTypes 118 | .map((type) => `[${type.name}](${getTypeURL(type)})`) 119 | .join(', ')}` 120 | ) 121 | } 122 | } 123 | 124 | function renderSchema(schema, options) { 125 | options = options || {} 126 | const title = options.title || 'Schema Types' 127 | const skipTitle = options.skipTitle || false 128 | const skipTableOfContents = options.skipTableOfContents || false 129 | const prologue = options.prologue || '' 130 | const epilogue = options.epilogue || '' 131 | const printer = options.printer || console.log 132 | const headingLevel = options.headingLevel || 1 133 | const unknownTypeURL = options.unknownTypeURL 134 | const tocFieldTypes = options.tocFieldTypes || [] 135 | const tocFieldAllTypes = tocFieldTypes.includes('*') 136 | 137 | if (schema.__schema) { 138 | schema = schema.__schema 139 | } 140 | 141 | const types = schema.types.filter((type) => !type.name.startsWith('__')) 142 | const typeMap = schema.types.reduce((typeMap, type) => { 143 | return Object.assign(typeMap, { [type.name]: type }) 144 | }, {}) 145 | 146 | const getTypeURL = (type) => { 147 | const url = `#${type.name.toLowerCase()}` 148 | if (typeMap[type.name]) { 149 | return url 150 | } else if (typeof unknownTypeURL === 'function') { 151 | return unknownTypeURL(type) 152 | } else if (unknownTypeURL) { 153 | return unknownTypeURL + url 154 | } 155 | } 156 | 157 | const getFieldURL = (type, field) => { 158 | const url = getTypeURL(type) 159 | return url && `${url}.${field.name.toLowerCase()}` 160 | } 161 | 162 | const queryType = schema.queryType 163 | const query = 164 | queryType && types.find((type) => type.name === schema.queryType.name) 165 | const mutationType = schema.mutationType 166 | const mutation = 167 | mutationType && types.find((type) => type.name === schema.mutationType.name) 168 | const subscriptionType = schema.subscriptionType 169 | const subscription = 170 | subscriptionType && 171 | types.find((type) => type.name === schema.subscriptionType.name) 172 | 173 | const objects = types.filter( 174 | (type) => 175 | type.kind === 'OBJECT' && 176 | type !== query && 177 | type !== mutation && 178 | type !== subscription 179 | ) 180 | const inputs = types.filter((type) => type.kind === 'INPUT_OBJECT') 181 | const enums = types.filter((type) => type.kind === 'ENUM') 182 | const scalars = types.filter((type) => type.kind === 'SCALAR') 183 | const interfaces = types.filter((type) => type.kind === 'INTERFACE') 184 | const unions = types.filter((type) => type.kind === 'UNION') 185 | 186 | sortBy(objects, 'name') 187 | sortBy(inputs, 'name') 188 | sortBy(enums, 'name') 189 | sortBy(scalars, 'name') 190 | sortBy(interfaces, 'name') 191 | sortBy(unions, 'name') 192 | 193 | if (!skipTitle) { 194 | printer(`${'#'.repeat(headingLevel)} ${title}\n`) 195 | } 196 | 197 | if (prologue) { 198 | printer(`${prologue}\n`) 199 | } 200 | 201 | if (!skipTableOfContents) { 202 | printer('
') 203 | printer(' Table of Contents\n') 204 | if (query) { 205 | printer(' * [Query](#query)') 206 | if (tocFieldAllTypes || tocFieldTypes.includes(query.name)) { 207 | query.fields.forEach((field) => { 208 | printer(` * [${field.name}](${getFieldURL(query, field)})`) 209 | }) 210 | } 211 | } 212 | if (mutation) { 213 | printer(' * [Mutation](#mutation)') 214 | if (tocFieldAllTypes || tocFieldTypes.includes(mutation.name)) { 215 | mutation.fields.forEach((field) => { 216 | printer(` * [${field.name}](${getFieldURL(mutation, field)})`) 217 | }) 218 | } 219 | } 220 | if (subscription) { 221 | printer(' * [Subscription](#subscription)') 222 | if (tocFieldAllTypes || tocFieldTypes.includes(subscription.name)) { 223 | subscription.fields.forEach((field) => { 224 | printer(` * [${field.name}](${getFieldURL(subscription, field)})`) 225 | }) 226 | } 227 | } 228 | if (objects.length) { 229 | printer(' * [Objects](#objects)') 230 | objects.forEach((type) => { 231 | printer(` * [${type.name}](#${type.name.toLowerCase()})`) 232 | if (tocFieldAllTypes || tocFieldTypes.includes(type.name)) { 233 | type.fields.forEach((field) => { 234 | printer(` * [${field.name}](${getFieldURL(type, field)})`) 235 | }) 236 | } 237 | }) 238 | } 239 | if (inputs.length) { 240 | printer(' * [Inputs](#inputs)') 241 | inputs.forEach((type) => { 242 | printer(` * [${type.name}](#${type.name.toLowerCase()})`) 243 | if (tocFieldAllTypes || tocFieldTypes.includes(type.name)) { 244 | type.inputFields.forEach((field) => { 245 | printer(` * [${field.name}](${getFieldURL(type, field)})`) 246 | }) 247 | } 248 | }) 249 | } 250 | if (enums.length) { 251 | printer(' * [Enums](#enums)') 252 | enums.forEach((type) => { 253 | printer(` * [${type.name}](#${type.name.toLowerCase()})`) 254 | }) 255 | } 256 | if (scalars.length) { 257 | printer(' * [Scalars](#scalars)') 258 | scalars.forEach((type) => { 259 | printer(` * [${type.name}](#${type.name.toLowerCase()})`) 260 | }) 261 | } 262 | if (interfaces.length) { 263 | printer(' * [Interfaces](#interfaces)') 264 | interfaces.forEach((type) => { 265 | printer(` * [${type.name}](#${type.name.toLowerCase()})`) 266 | if (tocFieldAllTypes || tocFieldTypes.includes(type.name)) { 267 | type.fields.forEach((field) => { 268 | printer(` * [${field.name}](${getFieldURL(type, field)})`) 269 | }) 270 | } 271 | }) 272 | } 273 | if (unions.length) { 274 | printer(' * [Unions](#unions)') 275 | unions.forEach((type) => { 276 | printer(` * [${type.name}](#${type.name.toLowerCase()})`) 277 | }) 278 | } 279 | printer('\n
') 280 | } 281 | 282 | if (query) { 283 | printer( 284 | `\n${'#'.repeat(headingLevel + 1)} Query${ 285 | query.name === 'Query' ? '' : ' (' + query.name + ')' 286 | }` 287 | ) 288 | renderObject(query, { 289 | skipTitle: true, 290 | headingLevel, 291 | printer, 292 | getTypeURL, 293 | getFieldURL, 294 | }) 295 | } 296 | 297 | if (mutation) { 298 | printer( 299 | `\n${'#'.repeat(headingLevel + 1)} Mutation${ 300 | mutation.name === 'Mutation' ? '' : ' (' + mutation.name + ')' 301 | }` 302 | ) 303 | renderObject(mutation, { 304 | skipTitle: true, 305 | headingLevel, 306 | printer, 307 | getTypeURL, 308 | getFieldURL, 309 | }) 310 | } 311 | 312 | if (subscription) { 313 | printer( 314 | `\n${'#'.repeat(headingLevel + 1)} Subscription${ 315 | subscription.name === 'Subscription' 316 | ? '' 317 | : ' (' + subscription.name + ')' 318 | }` 319 | ) 320 | renderObject(subscription, { 321 | skipTitle: true, 322 | headingLevel, 323 | printer, 324 | getTypeURL, 325 | getFieldURL, 326 | }) 327 | } 328 | 329 | if (objects.length) { 330 | printer(`\n${'#'.repeat(headingLevel + 1)} Objects`) 331 | objects.forEach((type) => 332 | renderObject(type, { headingLevel, printer, getTypeURL, getFieldURL }) 333 | ) 334 | } 335 | 336 | if (inputs.length) { 337 | printer(`\n${'#'.repeat(headingLevel + 1)} Inputs`) 338 | inputs.forEach((type) => 339 | renderObject(type, { headingLevel, printer, getTypeURL, getFieldURL }) 340 | ) 341 | } 342 | 343 | if (enums.length) { 344 | printer(`\n${'#'.repeat(headingLevel + 1)} Enums`) 345 | enums.forEach((type) => { 346 | printer(`\n${'#'.repeat(headingLevel + 2)} ${type.name}\n`) 347 | if (type.description) { 348 | printer(`${type.description}\n`) 349 | } 350 | printer('') 351 | printer('') 352 | printer('') 353 | printer('') 354 | printer('') 355 | printer('') 356 | printer('') 357 | printer('') 358 | type.enumValues.forEach((value) => { 359 | printer('') 360 | printer( 361 | `` 364 | ) 365 | if (value.description || value.isDeprecated) { 366 | printer('') 379 | } else { 380 | printer('') 381 | } 382 | printer('') 383 | }) 384 | printer('') 385 | printer('
ValueDescription
${value.name}${ 362 | value.isDeprecated ? ' ⚠️' : '' 363 | }') 367 | if (value.description) { 368 | printer(`\n${value.description}\n`) 369 | } 370 | if (value.isDeprecated) { 371 | printer('

⚠️ DEPRECATED

') 372 | if (value.deprecationReason) { 373 | printer('
') 374 | printer(`\n${value.deprecationReason}\n`) 375 | printer('
') 376 | } 377 | } 378 | printer('
') 386 | }) 387 | } 388 | 389 | if (scalars.length) { 390 | printer(`\n${'#'.repeat(headingLevel + 1)} Scalars\n`) 391 | scalars.forEach((type) => { 392 | printer(`${'#'.repeat(headingLevel + 2)} ${type.name}\n`) 393 | if (type.description) { 394 | printer(`${type.description}\n`) 395 | } 396 | }) 397 | } 398 | 399 | if (interfaces.length) { 400 | printer(`\n${'#'.repeat(headingLevel + 1)} Interfaces\n`) 401 | interfaces.forEach((type) => 402 | renderObject(type, { headingLevel, printer, getTypeURL, getFieldURL }) 403 | ) 404 | } 405 | 406 | if (unions.length) { 407 | printer(`\n${'#'.repeat(headingLevel + 1)} Unions`) 408 | unions.forEach((type) => { 409 | printer(`\n${'#'.repeat(headingLevel + 2)} ${type.name}\n`) 410 | if (type.description) { 411 | printer(`${type.description}\n`) 412 | } 413 | printer('') 414 | printer('') 415 | printer('') 416 | printer('') 417 | printer('') 418 | printer('') 419 | printer('') 420 | printer('') 421 | type.possibleTypes.forEach((objType) => { 422 | const obj = objects.find((o) => objType.name === o.name) 423 | const desc = objType.description || (obj && obj.description) 424 | printer('') 425 | printer( 426 | `` 430 | ) 431 | if (desc) { 432 | printer('') 435 | } else { 436 | printer('') 437 | } 438 | printer('') 439 | }) 440 | printer('') 441 | printer('
TypeDescription
${renderType(objType, { 427 | getTypeURL, 428 | getFieldURL, 429 | })}') 433 | printer(`\n${desc}\n`) 434 | printer('
') 442 | }) 443 | } 444 | 445 | if (epilogue) { 446 | printer(`\n${epilogue}`) 447 | } 448 | } 449 | 450 | module.exports = renderSchema 451 | -------------------------------------------------------------------------------- /src/updateSchema.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const renderSchema = require('./renderSchema') 3 | 4 | function updateMarkdown(doc, newContent, options = {}) { 5 | const includeMarkers = options.includeMarkers !== false 6 | const startMarker = options.startMarker || '' 7 | const endMarker = options.endMarker || '' 8 | let startIndex = doc.indexOf(startMarker) 9 | let endIndex = doc.lastIndexOf(endMarker) 10 | if (startIndex !== -1 && endIndex !== -1 && startIndex < endIndex) { 11 | if (includeMarkers) { 12 | startIndex += startMarker.length 13 | } else { 14 | endIndex += endMarker.length 15 | } 16 | return doc.slice(0, startIndex) + newContent + doc.slice(endIndex) 17 | } else if (startIndex === -1) { 18 | throw new Error(`Start marker not found: ${startMarker}`) 19 | } else if (endIndex === -1) { 20 | throw new Error(`End marker not found: ${endMarker}`) 21 | } else { 22 | throw new Error('Start marker must precede end marker.') 23 | } 24 | } 25 | 26 | function updateSchema(path, schema, options) { 27 | return new Promise((resolve, reject) => { 28 | fs.readFile(path, 'utf8', (err, doc) => { 29 | if (err) { 30 | if (err.code === 'ENOENT') { 31 | doc = '' 32 | } else { 33 | return reject(err) 34 | } 35 | } 36 | let newContent = '' 37 | const printer = (line) => { 38 | newContent += `${line}\n` 39 | } 40 | renderSchema(schema, Object.assign({}, options, { printer })) 41 | if (!doc.trim()) { 42 | doc = '\n\n' 43 | } 44 | let newDoc = doc 45 | try { 46 | newDoc = updateMarkdown(doc, `\n\n${newContent}\n`) 47 | } catch (err) { 48 | return reject(err) 49 | } 50 | fs.writeFile(path, newDoc, 'utf8', (err) => { 51 | if (err) { 52 | return reject(err) 53 | } 54 | resolve() 55 | }) 56 | }) 57 | }) 58 | } 59 | 60 | module.exports = updateSchema 61 | -------------------------------------------------------------------------------- /test/__snapshots__/index.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`diffSchema() outputs a JSON schema containing only additions 1`] = ` 4 | { 5 | "__schema": { 6 | "directives": [], 7 | "types": [ 8 | { 9 | "description": "A [release](https://musicbrainz.org/doc/Release) represents the 10 | unique release (i.e. issuing) of a product on a specific date with specific 11 | release information such as the country, label, barcode, packaging, etc. If you 12 | walk into a store and purchase an album or single, they’re each represented in 13 | MusicBrainz as one release.", 14 | "enumValues": null, 15 | "fields": [ 16 | { 17 | "args": [], 18 | "deprecationReason": null, 19 | "description": "An object containing a list and summary of the cover art images that are 20 | present for this release from the [Cover Art Archive](https://musicbrainz.org/doc/Cover_Art_Archive). 21 | This field is provided by the Cover Art Archive extension.", 22 | "isDeprecated": false, 23 | "name": "coverArtArchive", 24 | "type": { 25 | "kind": "OBJECT", 26 | "name": "CoverArtArchiveRelease", 27 | "ofType": null, 28 | }, 29 | }, 30 | ], 31 | "inputFields": null, 32 | "interfaces": [ 33 | { 34 | "kind": "INTERFACE", 35 | "name": "Node", 36 | "ofType": null, 37 | }, 38 | { 39 | "kind": "INTERFACE", 40 | "name": "Entity", 41 | "ofType": null, 42 | }, 43 | ], 44 | "kind": "OBJECT", 45 | "name": "Release", 46 | "possibleTypes": null, 47 | }, 48 | { 49 | "description": "A [release group](https://musicbrainz.org/doc/Release_Group) is 50 | used to group several different releases into a single logical entity. Every 51 | release belongs to one, and only one release group. 52 | 53 | Both release groups and releases are “albums” in a general sense, but with an 54 | important difference: a release is something you can buy as media such as a CD 55 | or a vinyl record, while a release group embraces the overall concept of an 56 | album – it doesn’t matter how many CDs or editions/versions it had.", 57 | "enumValues": null, 58 | "fields": [ 59 | { 60 | "args": [], 61 | "deprecationReason": null, 62 | "description": "The cover art for a release in the release group, obtained from the 63 | [Cover Art Archive](https://musicbrainz.org/doc/Cover_Art_Archive). A 64 | release in the release group will be chosen as representative of the release 65 | group. 66 | This field is provided by the Cover Art Archive extension.", 67 | "isDeprecated": false, 68 | "name": "coverArtArchive", 69 | "type": { 70 | "kind": "OBJECT", 71 | "name": "CoverArtArchiveRelease", 72 | "ofType": null, 73 | }, 74 | }, 75 | ], 76 | "inputFields": null, 77 | "interfaces": [ 78 | { 79 | "kind": "INTERFACE", 80 | "name": "Node", 81 | "ofType": null, 82 | }, 83 | { 84 | "kind": "INTERFACE", 85 | "name": "Entity", 86 | "ofType": null, 87 | }, 88 | ], 89 | "kind": "OBJECT", 90 | "name": "ReleaseGroup", 91 | "possibleTypes": null, 92 | }, 93 | { 94 | "description": "An object containing a list of the cover art images for a release obtained 95 | from the [Cover Art Archive](https://musicbrainz.org/doc/Cover_Art_Archive), 96 | as well as a summary of what artwork is available.", 97 | "enumValues": null, 98 | "fields": [ 99 | { 100 | "args": [ 101 | { 102 | "defaultValue": "FULL", 103 | "description": "The size of the image to retrieve. By default, the returned image will 104 | have its full original dimensions, but certain thumbnail sizes may be 105 | retrieved as well.", 106 | "name": "size", 107 | "type": { 108 | "kind": "ENUM", 109 | "name": "CoverArtArchiveImageSize", 110 | "ofType": null, 111 | }, 112 | }, 113 | ], 114 | "deprecationReason": null, 115 | "description": "The URL of an image depicting the album cover or “main front” of the release, 116 | i.e. the front of the packaging of the audio recording (or in the case of a 117 | digital release, the image associated with it in a digital media store). 118 | 119 | In the MusicBrainz schema, this field is a Boolean value indicating the 120 | presence of a front image, whereas here the value is the URL for the image 121 | itself if one exists. You can check for null if you just want to determine 122 | the presence of an image.", 123 | "isDeprecated": false, 124 | "name": "front", 125 | "type": { 126 | "kind": "SCALAR", 127 | "name": "URLString", 128 | "ofType": null, 129 | }, 130 | }, 131 | { 132 | "args": [ 133 | { 134 | "defaultValue": "FULL", 135 | "description": "The size of the image to retrieve. By default, the returned image will 136 | have its full original dimensions, but certain thumbnail sizes may be 137 | retrieved as well.", 138 | "name": "size", 139 | "type": { 140 | "kind": "ENUM", 141 | "name": "CoverArtArchiveImageSize", 142 | "ofType": null, 143 | }, 144 | }, 145 | ], 146 | "deprecationReason": null, 147 | "description": "The URL of an image depicting the “main back” of the release, i.e. the back 148 | of the packaging of the audio recording. 149 | 150 | In the MusicBrainz schema, this field is a Boolean value indicating the 151 | presence of a back image, whereas here the value is the URL for the image 152 | itself. You can check for null if you just want to determine the presence of 153 | an image.", 154 | "isDeprecated": false, 155 | "name": "back", 156 | "type": { 157 | "kind": "SCALAR", 158 | "name": "URLString", 159 | "ofType": null, 160 | }, 161 | }, 162 | { 163 | "args": [], 164 | "deprecationReason": null, 165 | "description": "A list of images depicting the different sides and surfaces of a release’s 166 | media and packaging.", 167 | "isDeprecated": false, 168 | "name": "images", 169 | "type": { 170 | "kind": "NON_NULL", 171 | "name": null, 172 | "ofType": { 173 | "kind": "LIST", 174 | "name": null, 175 | "ofType": { 176 | "kind": "OBJECT", 177 | "name": "CoverArtArchiveImage", 178 | "ofType": null, 179 | }, 180 | }, 181 | }, 182 | }, 183 | { 184 | "args": [], 185 | "deprecationReason": null, 186 | "description": "Whether there is artwork present for this release.", 187 | "isDeprecated": false, 188 | "name": "artwork", 189 | "type": { 190 | "kind": "NON_NULL", 191 | "name": null, 192 | "ofType": { 193 | "kind": "SCALAR", 194 | "name": "Boolean", 195 | "ofType": null, 196 | }, 197 | }, 198 | }, 199 | { 200 | "args": [], 201 | "deprecationReason": null, 202 | "description": "The number of artwork images present for this release.", 203 | "isDeprecated": false, 204 | "name": "count", 205 | "type": { 206 | "kind": "NON_NULL", 207 | "name": null, 208 | "ofType": { 209 | "kind": "SCALAR", 210 | "name": "Int", 211 | "ofType": null, 212 | }, 213 | }, 214 | }, 215 | { 216 | "args": [], 217 | "deprecationReason": null, 218 | "description": "The particular release shown in the returned cover art.", 219 | "isDeprecated": false, 220 | "name": "release", 221 | "type": { 222 | "kind": "OBJECT", 223 | "name": "Release", 224 | "ofType": null, 225 | }, 226 | }, 227 | ], 228 | "inputFields": null, 229 | "interfaces": [], 230 | "kind": "OBJECT", 231 | "name": "CoverArtArchiveRelease", 232 | "possibleTypes": null, 233 | }, 234 | { 235 | "description": "The image sizes that may be requested at the [Cover Art Archive](https://musicbrainz.org/doc/Cover_Art_Archive).", 236 | "enumValues": [ 237 | { 238 | "deprecationReason": null, 239 | "description": "A maximum dimension of 250px.", 240 | "isDeprecated": false, 241 | "name": "SMALL", 242 | }, 243 | { 244 | "deprecationReason": null, 245 | "description": "A maximum dimension of 500px.", 246 | "isDeprecated": false, 247 | "name": "LARGE", 248 | }, 249 | { 250 | "deprecationReason": null, 251 | "description": "The image’s original dimensions, with no maximum.", 252 | "isDeprecated": false, 253 | "name": "FULL", 254 | }, 255 | ], 256 | "fields": null, 257 | "inputFields": null, 258 | "interfaces": null, 259 | "kind": "ENUM", 260 | "name": "CoverArtArchiveImageSize", 261 | "possibleTypes": null, 262 | }, 263 | { 264 | "description": "An individual piece of album artwork from the [Cover Art Archive](https://musicbrainz.org/doc/Cover_Art_Archive).", 265 | "enumValues": null, 266 | "fields": [ 267 | { 268 | "args": [], 269 | "deprecationReason": null, 270 | "description": "The Internet Archive’s internal file ID for the image.", 271 | "isDeprecated": false, 272 | "name": "fileID", 273 | "type": { 274 | "kind": "NON_NULL", 275 | "name": null, 276 | "ofType": { 277 | "kind": "SCALAR", 278 | "name": "String", 279 | "ofType": null, 280 | }, 281 | }, 282 | }, 283 | { 284 | "args": [], 285 | "deprecationReason": null, 286 | "description": "The URL at which the image can be found.", 287 | "isDeprecated": false, 288 | "name": "image", 289 | "type": { 290 | "kind": "NON_NULL", 291 | "name": null, 292 | "ofType": { 293 | "kind": "SCALAR", 294 | "name": "URLString", 295 | "ofType": null, 296 | }, 297 | }, 298 | }, 299 | { 300 | "args": [], 301 | "deprecationReason": null, 302 | "description": "A set of thumbnails for the image.", 303 | "isDeprecated": false, 304 | "name": "thumbnails", 305 | "type": { 306 | "kind": "NON_NULL", 307 | "name": null, 308 | "ofType": { 309 | "kind": "OBJECT", 310 | "name": "CoverArtArchiveImageThumbnails", 311 | "ofType": null, 312 | }, 313 | }, 314 | }, 315 | { 316 | "args": [], 317 | "deprecationReason": null, 318 | "description": "Whether this image depicts the “main front” of the release.", 319 | "isDeprecated": false, 320 | "name": "front", 321 | "type": { 322 | "kind": "NON_NULL", 323 | "name": null, 324 | "ofType": { 325 | "kind": "SCALAR", 326 | "name": "Boolean", 327 | "ofType": null, 328 | }, 329 | }, 330 | }, 331 | { 332 | "args": [], 333 | "deprecationReason": null, 334 | "description": "Whether this image depicts the “main back” of the release.", 335 | "isDeprecated": false, 336 | "name": "back", 337 | "type": { 338 | "kind": "NON_NULL", 339 | "name": null, 340 | "ofType": { 341 | "kind": "SCALAR", 342 | "name": "Boolean", 343 | "ofType": null, 344 | }, 345 | }, 346 | }, 347 | { 348 | "args": [], 349 | "deprecationReason": null, 350 | "description": "A list of [image types](https://musicbrainz.org/doc/Cover_Art/Types) 351 | describing what part(s) of the release the image includes.", 352 | "isDeprecated": false, 353 | "name": "types", 354 | "type": { 355 | "kind": "NON_NULL", 356 | "name": null, 357 | "ofType": { 358 | "kind": "LIST", 359 | "name": null, 360 | "ofType": { 361 | "kind": "SCALAR", 362 | "name": "String", 363 | "ofType": null, 364 | }, 365 | }, 366 | }, 367 | }, 368 | { 369 | "args": [], 370 | "deprecationReason": null, 371 | "description": "The MusicBrainz edit ID.", 372 | "isDeprecated": false, 373 | "name": "edit", 374 | "type": { 375 | "kind": "SCALAR", 376 | "name": "Int", 377 | "ofType": null, 378 | }, 379 | }, 380 | { 381 | "args": [], 382 | "deprecationReason": null, 383 | "description": "Whether the image was approved by the MusicBrainz edit system.", 384 | "isDeprecated": false, 385 | "name": "approved", 386 | "type": { 387 | "kind": "SCALAR", 388 | "name": "Boolean", 389 | "ofType": null, 390 | }, 391 | }, 392 | { 393 | "args": [], 394 | "deprecationReason": null, 395 | "description": "A free-text comment left for the image.", 396 | "isDeprecated": false, 397 | "name": "comment", 398 | "type": { 399 | "kind": "SCALAR", 400 | "name": "String", 401 | "ofType": null, 402 | }, 403 | }, 404 | ], 405 | "inputFields": null, 406 | "interfaces": [], 407 | "kind": "OBJECT", 408 | "name": "CoverArtArchiveImage", 409 | "possibleTypes": null, 410 | }, 411 | { 412 | "description": "URLs for thumbnails of different sizes for a particular piece of cover art.", 413 | "enumValues": null, 414 | "fields": [ 415 | { 416 | "args": [], 417 | "deprecationReason": null, 418 | "description": "The URL of a small version of the cover art, where the maximum dimension is 419 | 250px.", 420 | "isDeprecated": false, 421 | "name": "small", 422 | "type": { 423 | "kind": "SCALAR", 424 | "name": "URLString", 425 | "ofType": null, 426 | }, 427 | }, 428 | { 429 | "args": [], 430 | "deprecationReason": null, 431 | "description": "The URL of a large version of the cover art, where the maximum dimension is 432 | 500px.", 433 | "isDeprecated": false, 434 | "name": "large", 435 | "type": { 436 | "kind": "SCALAR", 437 | "name": "URLString", 438 | "ofType": null, 439 | }, 440 | }, 441 | ], 442 | "inputFields": null, 443 | "interfaces": [], 444 | "kind": "OBJECT", 445 | "name": "CoverArtArchiveImageThumbnails", 446 | "possibleTypes": null, 447 | }, 448 | ], 449 | }, 450 | } 451 | `; 452 | 453 | exports[`run() with --help arg prints the help message 1`] = ` 454 | { 455 | "stderr": "", 456 | "stdout": " 457 | Usage: graphql-markdown [options] 458 | 459 | Output a Markdown document with rendered descriptions and links between types. 460 | The schema may be specified as: 461 | 462 | - a URL to the GraphQL endpoint (the introspection query will be run) 463 | - a GraphQL document containing the schema (.graphql or .gql) 464 | - a JSON document containing the schema (as returned by the introspection query) 465 | - an importable module with the schema as its default export (either an instance 466 | of GraphQLSchema or a JSON object) 467 | 468 | Options: 469 | 470 | --title Change the top heading title (default: 'Schema Types') 471 | --no-title Do not print a default title 472 | --no-toc Do not print table of contents 473 | --toc-fields Expand the table of contents for the listed types 474 | (comma-separated) to link to fields within those types 475 | (e.g. --toc-fields "Query,Mutation,Subscription") or use 476 | the string "*" to link to fields for all types 477 | --prologue Include custom Markdown after the title 478 | --epilogue Include custom Markdown after everything else 479 | --heading-level Heading level to begin at, useful if you are embedding the 480 | output in a document with other sections (default: 1) 481 | --update-file Markdown document to update (between comment markers) or 482 | create (if the file does not exist) 483 | --require If importing the schema from a module, require the specified 484 | module first (useful for e.g. babel-register) 485 | --header Additional header(s) to use in GraphQL request 486 | e.g. --header "Authorization=Bearer ey..." 487 | --version Print version and exit 488 | 489 | ", 490 | } 491 | `; 492 | 493 | exports[`run() with no args prints the help message 1`] = ` 494 | { 495 | "stderr": "", 496 | "stdout": " 497 | Usage: graphql-markdown [options] 498 | 499 | Output a Markdown document with rendered descriptions and links between types. 500 | The schema may be specified as: 501 | 502 | - a URL to the GraphQL endpoint (the introspection query will be run) 503 | - a GraphQL document containing the schema (.graphql or .gql) 504 | - a JSON document containing the schema (as returned by the introspection query) 505 | - an importable module with the schema as its default export (either an instance 506 | of GraphQLSchema or a JSON object) 507 | 508 | Options: 509 | 510 | --title Change the top heading title (default: 'Schema Types') 511 | --no-title Do not print a default title 512 | --no-toc Do not print table of contents 513 | --toc-fields Expand the table of contents for the listed types 514 | (comma-separated) to link to fields within those types 515 | (e.g. --toc-fields "Query,Mutation,Subscription") or use 516 | the string "*" to link to fields for all types 517 | --prologue Include custom Markdown after the title 518 | --epilogue Include custom Markdown after everything else 519 | --heading-level Heading level to begin at, useful if you are embedding the 520 | output in a document with other sections (default: 1) 521 | --update-file Markdown document to update (between comment markers) or 522 | create (if the file does not exist) 523 | --require If importing the schema from a module, require the specified 524 | module first (useful for e.g. babel-register) 525 | --header Additional header(s) to use in GraphQL request 526 | e.g. --header "Authorization=Bearer ey..." 527 | --version Print version and exit 528 | 529 | ", 530 | } 531 | `; 532 | -------------------------------------------------------------------------------- /test/fixtures/cover-art-archive.js: -------------------------------------------------------------------------------- 1 | const resolveFrom = require('resolve-from') 2 | const { 3 | default: graphBrainzSchema, 4 | createSchema, 5 | } = require('graphbrainz/lib/schema') 6 | const { schemaToJSON, diffSchema } = require('../../src/index') 7 | 8 | /** 9 | * Generate a "diff" schema in order to test `diffSchema`. 10 | */ 11 | async function generateDiff() { 12 | // Get the instance of `graphql` that `graphbrainz` sees. 13 | const graphql = require(resolveFrom( 14 | require.resolve('graphbrainz'), 15 | 'graphql' 16 | )) 17 | 18 | const extendedSchema = createSchema(graphBrainzSchema, { 19 | extensions: ['graphbrainz/extensions/cover-art-archive'], 20 | }) 21 | 22 | const schemaJSON = await schemaToJSON(graphBrainzSchema, { graphql }) 23 | const extendedSchemaJSON = await schemaToJSON(extendedSchema, { graphql }) 24 | 25 | return diffSchema(schemaJSON, extendedSchemaJSON) 26 | } 27 | 28 | module.exports = generateDiff() 29 | -------------------------------------------------------------------------------- /test/fixtures/cover-art-archive.md: -------------------------------------------------------------------------------- 1 | # Schema Types 2 | 3 |
4 | Table of Contents 5 | 6 | * [Objects](#objects) 7 | * [CoverArtArchiveImage](#coverartarchiveimage) 8 | * [CoverArtArchiveImageThumbnails](#coverartarchiveimagethumbnails) 9 | * [CoverArtArchiveRelease](#coverartarchiverelease) 10 | * [Release](#release) 11 | * [ReleaseGroup](#releasegroup) 12 | * [Enums](#enums) 13 | * [CoverArtArchiveImageSize](#coverartarchiveimagesize) 14 | 15 |
16 | 17 | ## Objects 18 | 19 | ### CoverArtArchiveImage 20 | 21 | An individual piece of album artwork from the [Cover Art Archive](https://musicbrainz.org/doc/Cover_Art_Archive). 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 41 | 42 | 43 | 44 | 45 | 50 | 51 | 52 | 53 | 54 | 59 | 60 | 61 | 62 | 63 | 68 | 69 | 70 | 71 | 72 | 77 | 78 | 79 | 80 | 81 | 87 | 88 | 89 | 90 | 91 | 96 | 97 | 98 | 99 | 100 | 105 | 106 | 107 | 108 | 109 | 114 | 115 | 116 |
FieldArgumentTypeDescription
fileIDString! 37 | 38 | The Internet Archive’s internal file ID for the image. 39 | 40 |
imageURLString! 46 | 47 | The URL at which the image can be found. 48 | 49 |
thumbnailsCoverArtArchiveImageThumbnails! 55 | 56 | A set of thumbnails for the image. 57 | 58 |
frontBoolean! 64 | 65 | Whether this image depicts the “main front” of the release. 66 | 67 |
backBoolean! 73 | 74 | Whether this image depicts the “main back” of the release. 75 | 76 |
types[String]! 82 | 83 | A list of [image types](https://musicbrainz.org/doc/Cover_Art/Types) 84 | describing what part(s) of the release the image includes. 85 | 86 |
editInt 92 | 93 | The MusicBrainz edit ID. 94 | 95 |
approvedBoolean 101 | 102 | Whether the image was approved by the MusicBrainz edit system. 103 | 104 |
commentString 110 | 111 | A free-text comment left for the image. 112 | 113 |
117 | 118 | ### CoverArtArchiveImageThumbnails 119 | 120 | URLs for thumbnails of different sizes for a particular piece of cover art. 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 141 | 142 | 143 | 144 | 145 | 151 | 152 | 153 |
FieldArgumentTypeDescription
smallURLString 136 | 137 | The URL of a small version of the cover art, where the maximum dimension is 138 | 250px. 139 | 140 |
largeURLString 146 | 147 | The URL of a large version of the cover art, where the maximum dimension is 148 | 500px. 149 | 150 |
154 | 155 | ### CoverArtArchiveRelease 156 | 157 | An object containing a list of the cover art images for a release obtained 158 | from the [Cover Art Archive](https://musicbrainz.org/doc/Cover_Art_Archive), 159 | as well as a summary of what artwork is available. 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 186 | 187 | 188 | 189 | 190 | 197 | 198 | 199 | 200 | 201 | 212 | 213 | 214 | 215 | 216 | 223 | 224 | 225 | 226 | 227 | 233 | 234 | 235 | 236 | 237 | 242 | 243 | 244 | 245 | 246 | 251 | 252 | 253 | 254 | 255 | 260 | 261 | 262 |
FieldArgumentTypeDescription
frontURLString 175 | 176 | The URL of an image depicting the album cover or “main front” of the release, 177 | i.e. the front of the packaging of the audio recording (or in the case of a 178 | digital release, the image associated with it in a digital media store). 179 | 180 | In the MusicBrainz schema, this field is a Boolean value indicating the 181 | presence of a front image, whereas here the value is the URL for the image 182 | itself if one exists. You can check for null if you just want to determine 183 | the presence of an image. 184 | 185 |
sizeCoverArtArchiveImageSize 191 | 192 | The size of the image to retrieve. By default, the returned image will 193 | have its full original dimensions, but certain thumbnail sizes may be 194 | retrieved as well. 195 | 196 |
backURLString 202 | 203 | The URL of an image depicting the “main back” of the release, i.e. the back 204 | of the packaging of the audio recording. 205 | 206 | In the MusicBrainz schema, this field is a Boolean value indicating the 207 | presence of a back image, whereas here the value is the URL for the image 208 | itself. You can check for null if you just want to determine the presence of 209 | an image. 210 | 211 |
sizeCoverArtArchiveImageSize 217 | 218 | The size of the image to retrieve. By default, the returned image will 219 | have its full original dimensions, but certain thumbnail sizes may be 220 | retrieved as well. 221 | 222 |
images[CoverArtArchiveImage]! 228 | 229 | A list of images depicting the different sides and surfaces of a release’s 230 | media and packaging. 231 | 232 |
artworkBoolean! 238 | 239 | Whether there is artwork present for this release. 240 | 241 |
countInt! 247 | 248 | The number of artwork images present for this release. 249 | 250 |
releaseRelease 256 | 257 | The particular release shown in the returned cover art. 258 | 259 |
263 | 264 | ### Release 265 | 266 | A [release](https://musicbrainz.org/doc/Release) represents the 267 | unique release (i.e. issuing) of a product on a specific date with specific 268 | release information such as the country, label, barcode, packaging, etc. If you 269 | walk into a store and purchase an album or single, they’re each represented in 270 | MusicBrainz as one release. 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 292 | 293 | 294 |
FieldArgumentTypeDescription
coverArtArchiveCoverArtArchiveRelease 286 | 287 | An object containing a list and summary of the cover art images that are 288 | present for this release from the [Cover Art Archive](https://musicbrainz.org/doc/Cover_Art_Archive). 289 | This field is provided by the Cover Art Archive extension. 290 | 291 |
295 | 296 | ### ReleaseGroup 297 | 298 | A [release group](https://musicbrainz.org/doc/Release_Group) is 299 | used to group several different releases into a single logical entity. Every 300 | release belongs to one, and only one release group. 301 | 302 | Both release groups and releases are “albums” in a general sense, but with an 303 | important difference: a release is something you can buy as media such as a CD 304 | or a vinyl record, while a release group embraces the overall concept of an 305 | album – it doesn’t matter how many CDs or editions/versions it had. 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 329 | 330 | 331 |
FieldArgumentTypeDescription
coverArtArchiveCoverArtArchiveRelease 321 | 322 | The cover art for a release in the release group, obtained from the 323 | [Cover Art Archive](https://musicbrainz.org/doc/Cover_Art_Archive). A 324 | release in the release group will be chosen as representative of the release 325 | group. 326 | This field is provided by the Cover Art Archive extension. 327 | 328 |
332 | 333 | ## Enums 334 | 335 | ### CoverArtArchiveImageSize 336 | 337 | The image sizes that may be requested at the [Cover Art Archive](https://musicbrainz.org/doc/Cover_Art_Archive). 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 354 | 355 | 356 | 357 | 362 | 363 | 364 | 365 | 370 | 371 | 372 |
ValueDescription
SMALL 350 | 351 | A maximum dimension of 250px. 352 | 353 |
LARGE 358 | 359 | A maximum dimension of 500px. 360 | 361 |
FULL 366 | 367 | The image’s original dimensions, with no maximum. 368 | 369 |
373 | -------------------------------------------------------------------------------- /test/fixtures/graphbrainz-updateSchema.js: -------------------------------------------------------------------------------- 1 | const resolveFrom = require('resolve-from') 2 | const { 3 | default: graphBrainzSchema, 4 | createSchema, 5 | } = require('graphbrainz/lib/schema') 6 | const { schemaToJSON } = require('../../src/index') 7 | 8 | /** 9 | * Generate an update to the base GraphBrainz schema. 10 | */ 11 | function generateSchema() { 12 | // Get the instance of `graphql` that `graphbrainz` sees. 13 | const graphql = require(resolveFrom( 14 | require.resolve('graphbrainz'), 15 | 'graphql' 16 | )) 17 | 18 | const extendedSchema = createSchema(graphBrainzSchema, { 19 | extensions: ['graphbrainz/extensions/cover-art-archive'], 20 | }) 21 | 22 | return schemaToJSON(extendedSchema, { graphql }) 23 | } 24 | 25 | module.exports = generateSchema() 26 | -------------------------------------------------------------------------------- /test/fixtures/graphbrainz.graphql: -------------------------------------------------------------------------------- 1 | """ 2 | [Aliases](https://musicbrainz.org/doc/Aliases) are variant names 3 | that are mostly used as search help: if a search matches an entity’s alias, the 4 | entity will be given as a result – even if the actual name wouldn’t be. 5 | """ 6 | type Alias { 7 | """ 8 | The aliased name of the entity. 9 | """ 10 | name: String 11 | 12 | """ 13 | The string to use for the purpose of ordering by name (for 14 | example, by moving articles like ‘the’ to the end or a person’s last name to 15 | the front). 16 | """ 17 | sortName: String 18 | 19 | """ 20 | The locale (language and/or country) in which the alias is 21 | used. 22 | """ 23 | locale: Locale 24 | 25 | """ 26 | Whether this is the main alias for the entity in the 27 | specified locale (this could mean the most recent or the most common). 28 | """ 29 | primary: Boolean 30 | 31 | """ 32 | The type or purpose of the alias – whether it is a variant, 33 | search hint, etc. 34 | """ 35 | type: String 36 | 37 | """ 38 | The MBID associated with the value of the `type` 39 | field. 40 | """ 41 | typeID: MBID 42 | } 43 | 44 | """ 45 | [Areas](https://musicbrainz.org/doc/Area) are geographic regions 46 | or settlements (countries, cities, or the like). 47 | """ 48 | type Area implements Node & Entity { 49 | """ 50 | The ID of an object 51 | """ 52 | id: ID! 53 | 54 | """ 55 | The MBID of the entity. 56 | """ 57 | mbid: MBID! 58 | 59 | """ 60 | The official name of the entity. 61 | """ 62 | name: String 63 | 64 | """ 65 | The string to use for the purpose of ordering by name (for 66 | example, by moving articles like ‘the’ to the end or a person’s last name to 67 | the front). 68 | """ 69 | sortName: String 70 | 71 | """ 72 | A comment used to help distinguish identically named entitites. 73 | """ 74 | disambiguation: String 75 | 76 | """ 77 | [Aliases](https://musicbrainz.org/doc/Aliases) are used to store 78 | alternate names or misspellings. 79 | """ 80 | aliases: [Alias] 81 | 82 | """ 83 | [ISO 3166 codes](https://en.wikipedia.org/wiki/ISO_3166) are 84 | the codes assigned by ISO to countries and subdivisions. 85 | """ 86 | isoCodes( 87 | """ 88 | Specify the particular ISO standard codes to retrieve. 89 | Available ISO standards are 3166-1, 3166-2, and 3166-3. 90 | """ 91 | standard: String = "3166-1" 92 | ): [String] 93 | 94 | """ 95 | The type of area (country, city, etc. – see the [possible 96 | values](https://musicbrainz.org/doc/Area)). 97 | """ 98 | type: String 99 | 100 | """ 101 | The MBID associated with the value of the `type` 102 | field. 103 | """ 104 | typeID: MBID 105 | 106 | """ 107 | A list of artists linked to this entity. 108 | """ 109 | artists(after: String, first: Int): ArtistConnection 110 | 111 | """ 112 | A list of events linked to this entity. 113 | """ 114 | events(after: String, first: Int): EventConnection 115 | 116 | """ 117 | A list of labels linked to this entity. 118 | """ 119 | labels(after: String, first: Int): LabelConnection 120 | 121 | """ 122 | A list of places linked to this entity. 123 | """ 124 | places(after: String, first: Int): PlaceConnection 125 | 126 | """ 127 | A list of releases linked to this entity. 128 | """ 129 | releases( 130 | """ 131 | Filter by one or more release group types. 132 | """ 133 | type: [ReleaseGroupType] 134 | 135 | """ 136 | Filter by one or more release statuses. 137 | """ 138 | status: [ReleaseStatus] 139 | after: String 140 | first: Int 141 | ): ReleaseConnection 142 | 143 | """ 144 | Relationships between this entity and other entitites. 145 | """ 146 | relationships: Relationships 147 | 148 | """ 149 | A list of collections containing this entity. 150 | """ 151 | collections(after: String, first: Int): CollectionConnection 152 | 153 | """ 154 | A list of tags linked to this entity. 155 | """ 156 | tags(after: String, first: Int): TagConnection 157 | } 158 | 159 | """ 160 | A connection to a list of items. 161 | """ 162 | type AreaConnection { 163 | """ 164 | Information to aid in pagination. 165 | """ 166 | pageInfo: PageInfo! 167 | 168 | """ 169 | A list of edges. 170 | """ 171 | edges: [AreaEdge] 172 | 173 | """ 174 | A list of nodes in the connection (without going through the 175 | `edges` field). 176 | """ 177 | nodes: [Area] 178 | 179 | """ 180 | A count of the total number of items in this connection, 181 | ignoring pagination. 182 | """ 183 | totalCount: Int 184 | } 185 | 186 | """ 187 | An edge in a connection. 188 | """ 189 | type AreaEdge { 190 | """ 191 | The item at the end of the edge 192 | """ 193 | node: Area 194 | 195 | """ 196 | A cursor for use in pagination 197 | """ 198 | cursor: String! 199 | 200 | """ 201 | The relevancy score (0–100) assigned by the search engine, if 202 | these results were found through a search. 203 | """ 204 | score: Int 205 | } 206 | 207 | """ 208 | An [artist](https://musicbrainz.org/doc/Artist) is generally a 209 | musician, group of musicians, or other music professional (like a producer or 210 | engineer). Occasionally, it can also be a non-musical person (like a 211 | photographer, an illustrator, or a poet whose writings are set to music), or 212 | even a fictional character. 213 | """ 214 | type Artist implements Node & Entity { 215 | """ 216 | The ID of an object 217 | """ 218 | id: ID! 219 | 220 | """ 221 | The MBID of the entity. 222 | """ 223 | mbid: MBID! 224 | 225 | """ 226 | The official name of the entity. 227 | """ 228 | name: String 229 | 230 | """ 231 | The string to use for the purpose of ordering by name (for 232 | example, by moving articles like ‘the’ to the end or a person’s last name to 233 | the front). 234 | """ 235 | sortName: String 236 | 237 | """ 238 | A comment used to help distinguish identically named entitites. 239 | """ 240 | disambiguation: String 241 | 242 | """ 243 | [Aliases](https://musicbrainz.org/doc/Aliases) are used to store 244 | alternate names or misspellings. 245 | """ 246 | aliases: [Alias] 247 | 248 | """ 249 | The country with which an artist is primarily identified. It 250 | is often, but not always, its birth/formation country. 251 | """ 252 | country: String 253 | 254 | """ 255 | The area with which an artist is primarily identified. It 256 | is often, but not always, its birth/formation country. 257 | """ 258 | area: Area 259 | 260 | """ 261 | The area in which an artist began their career (or where 262 | they were born, if the artist is a person). 263 | """ 264 | beginArea: Area 265 | 266 | """ 267 | The area in which an artist ended their career (or where 268 | they died, if the artist is a person). 269 | """ 270 | endArea: Area 271 | 272 | """ 273 | The begin and end dates of the entity’s existence. Its exact 274 | meaning depends on the type of entity. 275 | """ 276 | lifeSpan: LifeSpan 277 | 278 | """ 279 | Whether a person or character identifies as male, female, or 280 | neither. Groups do not have genders. 281 | """ 282 | gender: String 283 | 284 | """ 285 | The MBID associated with the value of the `gender` 286 | field. 287 | """ 288 | genderID: MBID 289 | 290 | """ 291 | Whether an artist is a person, a group, or something else. 292 | """ 293 | type: String 294 | 295 | """ 296 | The MBID associated with the value of the `type` 297 | field. 298 | """ 299 | typeID: MBID 300 | 301 | """ 302 | List of [Interested Parties Information](https://musicbrainz.org/doc/IPI) 303 | (IPI) codes for the artist. 304 | """ 305 | ipis: [IPI] 306 | 307 | """ 308 | List of [International Standard Name Identifier](https://musicbrainz.org/doc/ISNI) 309 | (ISNI) codes for the artist. 310 | """ 311 | isnis: [ISNI] 312 | 313 | """ 314 | A list of recordings linked to this entity. 315 | """ 316 | recordings(after: String, first: Int): RecordingConnection 317 | 318 | """ 319 | A list of releases linked to this entity. 320 | """ 321 | releases( 322 | """ 323 | Filter by one or more release group types. 324 | """ 325 | type: [ReleaseGroupType] 326 | 327 | """ 328 | Filter by one or more release statuses. 329 | """ 330 | status: [ReleaseStatus] 331 | after: String 332 | first: Int 333 | ): ReleaseConnection 334 | 335 | """ 336 | A list of release groups linked to this entity. 337 | """ 338 | releaseGroups( 339 | """ 340 | Filter by one or more release group types. 341 | """ 342 | type: [ReleaseGroupType] 343 | after: String 344 | first: Int 345 | ): ReleaseGroupConnection 346 | 347 | """ 348 | A list of works linked to this entity. 349 | """ 350 | works(after: String, first: Int): WorkConnection 351 | 352 | """ 353 | Relationships between this entity and other entitites. 354 | """ 355 | relationships: Relationships 356 | 357 | """ 358 | A list of collections containing this entity. 359 | """ 360 | collections(after: String, first: Int): CollectionConnection 361 | 362 | """ 363 | The rating users have given to this entity. 364 | """ 365 | rating: Rating 366 | 367 | """ 368 | A list of tags linked to this entity. 369 | """ 370 | tags(after: String, first: Int): TagConnection 371 | } 372 | 373 | """ 374 | A connection to a list of items. 375 | """ 376 | type ArtistConnection { 377 | """ 378 | Information to aid in pagination. 379 | """ 380 | pageInfo: PageInfo! 381 | 382 | """ 383 | A list of edges. 384 | """ 385 | edges: [ArtistEdge] 386 | 387 | """ 388 | A list of nodes in the connection (without going through the 389 | `edges` field). 390 | """ 391 | nodes: [Artist] 392 | 393 | """ 394 | A count of the total number of items in this connection, 395 | ignoring pagination. 396 | """ 397 | totalCount: Int 398 | } 399 | 400 | """ 401 | [Artist credits](https://musicbrainz.org/doc/Artist_Credits) 402 | indicate who is the main credited artist (or artists) for releases, release 403 | groups, tracks, and recordings, and how they are credited. They consist of 404 | artists, with (optionally) their names as credited in the specific release, 405 | track, etc., and join phrases between them. 406 | """ 407 | type ArtistCredit { 408 | """ 409 | The entity representing the artist referenced in the 410 | credits. 411 | """ 412 | artist: Artist 413 | 414 | """ 415 | The name of the artist as credited in the specific release, 416 | track, etc. 417 | """ 418 | name: String 419 | 420 | """ 421 | Join phrases might include words and/or punctuation to 422 | separate artist names as they appear on the release, track, etc. 423 | """ 424 | joinPhrase: String 425 | } 426 | 427 | """ 428 | An edge in a connection. 429 | """ 430 | type ArtistEdge { 431 | """ 432 | The item at the end of the edge 433 | """ 434 | node: Artist 435 | 436 | """ 437 | A cursor for use in pagination 438 | """ 439 | cursor: String! 440 | 441 | """ 442 | The relevancy score (0–100) assigned by the search engine, if 443 | these results were found through a search. 444 | """ 445 | score: Int 446 | } 447 | 448 | """ 449 | An [Amazon Standard Identification Number](https://musicbrainz.org/doc/ASIN) 450 | (ASIN) is a 10-character alphanumeric unique identifier assigned by Amazon.com 451 | and its partners for product identification within the Amazon organization. 452 | """ 453 | scalar ASIN 454 | 455 | """ 456 | A query for all MusicBrainz entities directly linked to another 457 | entity. 458 | """ 459 | type BrowseQuery { 460 | """ 461 | Browse area entities linked to the given arguments. 462 | """ 463 | areas( 464 | """ 465 | The MBID of a collection in which the entity is found. 466 | """ 467 | collection: MBID 468 | after: String 469 | first: Int 470 | ): AreaConnection 471 | 472 | """ 473 | Browse artist entities linked to the given arguments. 474 | """ 475 | artists( 476 | """ 477 | The MBID of an area to which the entity is linked. 478 | """ 479 | area: MBID 480 | 481 | """ 482 | The MBID of a collection in which the entity is found. 483 | """ 484 | collection: MBID 485 | 486 | """ 487 | The MBID of a recording to which the entity is linked. 488 | """ 489 | recording: MBID 490 | 491 | """ 492 | The MBID of a release to which the entity is linked. 493 | """ 494 | release: MBID 495 | 496 | """ 497 | The MBID of a release group to which the entity is linked. 498 | """ 499 | releaseGroup: MBID 500 | 501 | """ 502 | The MBID of a work to which the entity is linked. 503 | """ 504 | work: MBID 505 | after: String 506 | first: Int 507 | ): ArtistConnection 508 | 509 | """ 510 | Browse collection entities linked to the given arguments. 511 | """ 512 | collections( 513 | """ 514 | The MBID of an area to which the entity is linked. 515 | """ 516 | area: MBID 517 | 518 | """ 519 | The MBID of an artist to which the entity is linked. 520 | """ 521 | artist: MBID 522 | 523 | """ 524 | The username of the editor who created the collection. 525 | """ 526 | editor: String 527 | 528 | """ 529 | The MBID of an event to which the entity is linked. 530 | """ 531 | event: MBID 532 | 533 | """ 534 | The MBID of a label to which the entity is linked. 535 | """ 536 | label: MBID 537 | 538 | """ 539 | The MBID of a place to which the entity is linked. 540 | """ 541 | place: MBID 542 | 543 | """ 544 | The MBID of a recording to which the entity is linked. 545 | """ 546 | recording: MBID 547 | 548 | """ 549 | The MBID of a release to which the entity is linked. 550 | """ 551 | release: MBID 552 | 553 | """ 554 | The MBID of a release group to which the entity is linked. 555 | """ 556 | releaseGroup: MBID 557 | 558 | """ 559 | The MBID of a work to which the entity is linked. 560 | """ 561 | work: MBID 562 | after: String 563 | first: Int 564 | ): CollectionConnection 565 | 566 | """ 567 | Browse event entities linked to the given arguments. 568 | """ 569 | events( 570 | """ 571 | The MBID of an area to which the entity is linked. 572 | """ 573 | area: MBID 574 | 575 | """ 576 | The MBID of an artist to which the entity is linked. 577 | """ 578 | artist: MBID 579 | 580 | """ 581 | The MBID of a collection in which the entity is found. 582 | """ 583 | collection: MBID 584 | 585 | """ 586 | The MBID of a place to which the entity is linked. 587 | """ 588 | place: MBID 589 | after: String 590 | first: Int 591 | ): EventConnection 592 | 593 | """ 594 | Browse label entities linked to the given arguments. 595 | """ 596 | labels( 597 | """ 598 | The MBID of an area to which the entity is linked. 599 | """ 600 | area: MBID 601 | 602 | """ 603 | The MBID of a collection in which the entity is found. 604 | """ 605 | collection: MBID 606 | 607 | """ 608 | The MBID of a release to which the entity is linked. 609 | """ 610 | release: MBID 611 | after: String 612 | first: Int 613 | ): LabelConnection 614 | 615 | """ 616 | Browse place entities linked to the given arguments. 617 | """ 618 | places( 619 | """ 620 | The MBID of an area to which the entity is linked. 621 | """ 622 | area: MBID 623 | 624 | """ 625 | The MBID of a collection in which the entity is found. 626 | """ 627 | collection: MBID 628 | after: String 629 | first: Int 630 | ): PlaceConnection 631 | 632 | """ 633 | Browse recording entities linked to the given arguments. 634 | """ 635 | recordings( 636 | """ 637 | The MBID of an artist to which the entity is linked. 638 | """ 639 | artist: MBID 640 | 641 | """ 642 | The MBID of a collection in which the entity is found. 643 | """ 644 | collection: MBID 645 | 646 | """ 647 | The [International Standard Recording Code](https://musicbrainz.org/doc/ISRC) 648 | (ISRC) of the recording. 649 | """ 650 | isrc: ISRC 651 | 652 | """ 653 | The MBID of a release to which the entity is linked. 654 | """ 655 | release: MBID 656 | after: String 657 | first: Int 658 | ): RecordingConnection 659 | 660 | """ 661 | Browse release entities linked to the given arguments. 662 | """ 663 | releases( 664 | """ 665 | The MBID of an area to which the entity is linked. 666 | """ 667 | area: MBID 668 | 669 | """ 670 | The MBID of an artist to which the entity is linked. 671 | """ 672 | artist: MBID 673 | 674 | """ 675 | The MBID of a collection in which the entity is found. 676 | """ 677 | collection: MBID 678 | 679 | """ 680 | A [disc ID](https://musicbrainz.org/doc/Disc_ID) 681 | associated with the release. 682 | """ 683 | discID: DiscID 684 | 685 | """ 686 | The MBID of a label to which the entity is linked. 687 | """ 688 | label: MBID 689 | 690 | """ 691 | The MBID of a recording to which the entity is linked. 692 | """ 693 | recording: MBID 694 | 695 | """ 696 | The MBID of a release group to which the entity is linked. 697 | """ 698 | releaseGroup: MBID 699 | 700 | """ 701 | The MBID of a track that is included in the release. 702 | """ 703 | track: MBID 704 | 705 | """ 706 | The MBID of an artist that appears on a track in the 707 | release, but is not included in the credits for the release itself. 708 | """ 709 | trackArtist: MBID 710 | 711 | """ 712 | Filter by one or more release group types. 713 | """ 714 | type: [ReleaseGroupType] 715 | 716 | """ 717 | Filter by one or more release statuses. 718 | """ 719 | status: [ReleaseStatus] 720 | after: String 721 | first: Int 722 | ): ReleaseConnection 723 | 724 | """ 725 | Browse release group entities linked to the given arguments. 726 | """ 727 | releaseGroups( 728 | """ 729 | The MBID of an artist to which the entity is linked. 730 | """ 731 | artist: MBID 732 | 733 | """ 734 | The MBID of a collection in which the entity is found. 735 | """ 736 | collection: MBID 737 | 738 | """ 739 | The MBID of a release to which the entity is linked. 740 | """ 741 | release: MBID 742 | 743 | """ 744 | Filter by one or more release group types. 745 | """ 746 | type: [ReleaseGroupType] 747 | after: String 748 | first: Int 749 | ): ReleaseGroupConnection 750 | 751 | """ 752 | Browse work entities linked to the given arguments. 753 | """ 754 | works( 755 | """ 756 | The MBID of an artist to which the entity is linked. 757 | """ 758 | artist: MBID 759 | 760 | """ 761 | The MBID of a collection in which the entity is found. 762 | """ 763 | collection: MBID 764 | 765 | """ 766 | The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC) 767 | (ISWC) of the work. 768 | """ 769 | iswc: ISWC 770 | after: String 771 | first: Int 772 | ): WorkConnection 773 | } 774 | 775 | """ 776 | [Collections](https://musicbrainz.org/doc/Collections) are 777 | lists of entities that users can create. 778 | """ 779 | type Collection implements Node & Entity { 780 | """ 781 | The ID of an object 782 | """ 783 | id: ID! 784 | 785 | """ 786 | The MBID of the entity. 787 | """ 788 | mbid: MBID! 789 | 790 | """ 791 | The official name of the entity. 792 | """ 793 | name: String 794 | 795 | """ 796 | The username of the editor who created the collection. 797 | """ 798 | editor: String! 799 | 800 | """ 801 | The type of entity listed in the collection. 802 | """ 803 | entityType: String! 804 | 805 | """ 806 | The type of collection. 807 | """ 808 | type: String 809 | 810 | """ 811 | The MBID associated with the value of the `type` 812 | field. 813 | """ 814 | typeID: MBID 815 | 816 | """ 817 | The list of areas found in this collection. 818 | """ 819 | areas(after: String, first: Int): AreaConnection 820 | 821 | """ 822 | The list of artists found in this collection. 823 | """ 824 | artists(after: String, first: Int): ArtistConnection 825 | 826 | """ 827 | The list of events found in this collection. 828 | """ 829 | events(after: String, first: Int): EventConnection 830 | 831 | """ 832 | The list of instruments found in this collection. 833 | """ 834 | instruments(after: String, first: Int): InstrumentConnection 835 | 836 | """ 837 | The list of labels found in this collection. 838 | """ 839 | labels(after: String, first: Int): LabelConnection 840 | 841 | """ 842 | The list of places found in this collection. 843 | """ 844 | places(after: String, first: Int): PlaceConnection 845 | 846 | """ 847 | The list of recordings found in this collection. 848 | """ 849 | recordings(after: String, first: Int): RecordingConnection 850 | 851 | """ 852 | The list of releases found in this collection. 853 | """ 854 | releases( 855 | """ 856 | Filter by one or more release group types. 857 | """ 858 | type: [ReleaseGroupType] 859 | 860 | """ 861 | Filter by one or more release statuses. 862 | """ 863 | status: [ReleaseStatus] 864 | after: String 865 | first: Int 866 | ): ReleaseConnection 867 | 868 | """ 869 | The list of release groups found in this collection. 870 | """ 871 | releaseGroups( 872 | """ 873 | Filter by one or more release group types. 874 | """ 875 | type: [ReleaseGroupType] 876 | after: String 877 | first: Int 878 | ): ReleaseGroupConnection 879 | 880 | """ 881 | The list of series found in this collection. 882 | """ 883 | series(after: String, first: Int): SeriesConnection 884 | 885 | """ 886 | The list of works found in this collection. 887 | """ 888 | works(after: String, first: Int): WorkConnection 889 | } 890 | 891 | """ 892 | A connection to a list of items. 893 | """ 894 | type CollectionConnection { 895 | """ 896 | Information to aid in pagination. 897 | """ 898 | pageInfo: PageInfo! 899 | 900 | """ 901 | A list of edges. 902 | """ 903 | edges: [CollectionEdge] 904 | 905 | """ 906 | A list of nodes in the connection (without going through the 907 | `edges` field). 908 | """ 909 | nodes: [Collection] 910 | 911 | """ 912 | A count of the total number of items in this connection, 913 | ignoring pagination. 914 | """ 915 | totalCount: Int 916 | } 917 | 918 | """ 919 | An edge in a connection. 920 | """ 921 | type CollectionEdge { 922 | """ 923 | The item at the end of the edge 924 | """ 925 | node: Collection 926 | 927 | """ 928 | A cursor for use in pagination 929 | """ 930 | cursor: String! 931 | 932 | """ 933 | The relevancy score (0–100) assigned by the search engine, if 934 | these results were found through a search. 935 | """ 936 | score: Int 937 | } 938 | 939 | """ 940 | Geographic coordinates described with latitude and longitude. 941 | """ 942 | type Coordinates { 943 | """ 944 | The north–south position of a point on the Earth’s surface. 945 | """ 946 | latitude: Degrees 947 | 948 | """ 949 | The east–west position of a point on the Earth’s surface. 950 | """ 951 | longitude: Degrees 952 | } 953 | 954 | """ 955 | Year, month (optional), and day (optional) in YYYY-MM-DD format. 956 | """ 957 | scalar Date 958 | 959 | """ 960 | Decimal degrees, used for latitude and longitude. 961 | """ 962 | scalar Degrees 963 | 964 | """ 965 | Information about the physical CD and releases associated with a 966 | particular [disc ID](https://musicbrainz.org/doc/Disc_ID). 967 | """ 968 | type Disc implements Node { 969 | """ 970 | The ID of an object 971 | """ 972 | id: ID! 973 | 974 | """ 975 | The [disc ID](https://musicbrainz.org/doc/Disc_ID) of this disc. 976 | """ 977 | discID: DiscID! 978 | 979 | """ 980 | The number of offsets (tracks) on the disc. 981 | """ 982 | offsetCount: Int! 983 | 984 | """ 985 | The sector offset of each track on the disc. 986 | """ 987 | offsets: [Int] 988 | 989 | """ 990 | The sector offset of the lead-out (the end of the disc). 991 | """ 992 | sectors: Int! 993 | 994 | """ 995 | The list of releases linked to this disc ID. 996 | """ 997 | releases(after: String, first: Int): ReleaseConnection 998 | } 999 | 1000 | """ 1001 | [Disc ID](https://musicbrainz.org/doc/Disc_ID) is the code 1002 | number which MusicBrainz uses to link a physical CD to a [release](https://musicbrainz.org/doc/Release) 1003 | listing. 1004 | 1005 | A release may have any number of disc IDs, and a disc ID may be linked to 1006 | multiple releases. This is because disc ID calculation involves a hash of the 1007 | frame offsets of the CD tracks. 1008 | 1009 | Different pressing of a CD often have slightly different frame offsets, and 1010 | hence different disc IDs. 1011 | 1012 | Conversely, two different CDs may happen to have exactly the same set of frame 1013 | offsets and hence the same disc ID. 1014 | """ 1015 | scalar DiscID 1016 | 1017 | """ 1018 | A length of time, in milliseconds. 1019 | """ 1020 | scalar Duration 1021 | 1022 | """ 1023 | An entity in the MusicBrainz schema. 1024 | """ 1025 | interface Entity { 1026 | """ 1027 | The MBID of the entity. 1028 | """ 1029 | mbid: MBID! 1030 | } 1031 | 1032 | """ 1033 | An [event](https://musicbrainz.org/doc/Event) refers to an 1034 | organised event which people can attend, and is relevant to MusicBrainz. 1035 | Generally this means live performances, like concerts and festivals. 1036 | """ 1037 | type Event implements Node & Entity { 1038 | """ 1039 | The ID of an object 1040 | """ 1041 | id: ID! 1042 | 1043 | """ 1044 | The MBID of the entity. 1045 | """ 1046 | mbid: MBID! 1047 | 1048 | """ 1049 | The official name of the entity. 1050 | """ 1051 | name: String 1052 | 1053 | """ 1054 | A comment used to help distinguish identically named entitites. 1055 | """ 1056 | disambiguation: String 1057 | 1058 | """ 1059 | [Aliases](https://musicbrainz.org/doc/Aliases) are used to store 1060 | alternate names or misspellings. 1061 | """ 1062 | aliases: [Alias] 1063 | 1064 | """ 1065 | The begin and end dates of the entity’s existence. Its exact 1066 | meaning depends on the type of entity. 1067 | """ 1068 | lifeSpan: LifeSpan 1069 | 1070 | """ 1071 | The start time of the event. 1072 | """ 1073 | time: Time 1074 | 1075 | """ 1076 | Whether or not the event took place. 1077 | """ 1078 | cancelled: Boolean 1079 | 1080 | """ 1081 | A list of songs performed, optionally including links to 1082 | artists and works. See the [setlist documentation](https://musicbrainz.org/doc/Event/Setlist) 1083 | for syntax and examples. 1084 | """ 1085 | setlist: String 1086 | 1087 | """ 1088 | What kind of event the event is, e.g. concert, festival, etc. 1089 | """ 1090 | type: String 1091 | 1092 | """ 1093 | The MBID associated with the value of the `type` 1094 | field. 1095 | """ 1096 | typeID: MBID 1097 | 1098 | """ 1099 | Relationships between this entity and other entitites. 1100 | """ 1101 | relationships: Relationships 1102 | 1103 | """ 1104 | A list of collections containing this entity. 1105 | """ 1106 | collections(after: String, first: Int): CollectionConnection 1107 | 1108 | """ 1109 | The rating users have given to this entity. 1110 | """ 1111 | rating: Rating 1112 | 1113 | """ 1114 | A list of tags linked to this entity. 1115 | """ 1116 | tags(after: String, first: Int): TagConnection 1117 | } 1118 | 1119 | """ 1120 | A connection to a list of items. 1121 | """ 1122 | type EventConnection { 1123 | """ 1124 | Information to aid in pagination. 1125 | """ 1126 | pageInfo: PageInfo! 1127 | 1128 | """ 1129 | A list of edges. 1130 | """ 1131 | edges: [EventEdge] 1132 | 1133 | """ 1134 | A list of nodes in the connection (without going through the 1135 | `edges` field). 1136 | """ 1137 | nodes: [Event] 1138 | 1139 | """ 1140 | A count of the total number of items in this connection, 1141 | ignoring pagination. 1142 | """ 1143 | totalCount: Int 1144 | } 1145 | 1146 | """ 1147 | An edge in a connection. 1148 | """ 1149 | type EventEdge { 1150 | """ 1151 | The item at the end of the edge 1152 | """ 1153 | node: Event 1154 | 1155 | """ 1156 | A cursor for use in pagination 1157 | """ 1158 | cursor: String! 1159 | 1160 | """ 1161 | The relevancy score (0–100) assigned by the search engine, if 1162 | these results were found through a search. 1163 | """ 1164 | score: Int 1165 | } 1166 | 1167 | """ 1168 | [Instruments](https://musicbrainz.org/doc/Instrument) are 1169 | devices created or adapted to make musical sounds. Instruments are primarily 1170 | used in relationships between two other entities. 1171 | """ 1172 | type Instrument implements Node & Entity { 1173 | """ 1174 | The ID of an object 1175 | """ 1176 | id: ID! 1177 | 1178 | """ 1179 | The MBID of the entity. 1180 | """ 1181 | mbid: MBID! 1182 | 1183 | """ 1184 | The official name of the entity. 1185 | """ 1186 | name: String 1187 | 1188 | """ 1189 | A comment used to help distinguish identically named entitites. 1190 | """ 1191 | disambiguation: String 1192 | 1193 | """ 1194 | [Aliases](https://musicbrainz.org/doc/Aliases) are used to store 1195 | alternate names or misspellings. 1196 | """ 1197 | aliases: [Alias] 1198 | 1199 | """ 1200 | A brief description of the main characteristics of the 1201 | instrument. 1202 | """ 1203 | description: String 1204 | 1205 | """ 1206 | The type categorises the instrument by the way the sound is 1207 | created, similar to the [Hornbostel-Sachs](https://en.wikipedia.org/wiki/Hornbostel%E2%80%93Sachs) 1208 | classification. 1209 | """ 1210 | type: String 1211 | 1212 | """ 1213 | The MBID associated with the value of the `type` 1214 | field. 1215 | """ 1216 | typeID: MBID 1217 | 1218 | """ 1219 | Relationships between this entity and other entitites. 1220 | """ 1221 | relationships: Relationships 1222 | 1223 | """ 1224 | A list of collections containing this entity. 1225 | """ 1226 | collections(after: String, first: Int): CollectionConnection 1227 | 1228 | """ 1229 | A list of tags linked to this entity. 1230 | """ 1231 | tags(after: String, first: Int): TagConnection 1232 | } 1233 | 1234 | """ 1235 | A connection to a list of items. 1236 | """ 1237 | type InstrumentConnection { 1238 | """ 1239 | Information to aid in pagination. 1240 | """ 1241 | pageInfo: PageInfo! 1242 | 1243 | """ 1244 | A list of edges. 1245 | """ 1246 | edges: [InstrumentEdge] 1247 | 1248 | """ 1249 | A list of nodes in the connection (without going through the 1250 | `edges` field). 1251 | """ 1252 | nodes: [Instrument] 1253 | 1254 | """ 1255 | A count of the total number of items in this connection, 1256 | ignoring pagination. 1257 | """ 1258 | totalCount: Int 1259 | } 1260 | 1261 | """ 1262 | An edge in a connection. 1263 | """ 1264 | type InstrumentEdge { 1265 | """ 1266 | The item at the end of the edge 1267 | """ 1268 | node: Instrument 1269 | 1270 | """ 1271 | A cursor for use in pagination 1272 | """ 1273 | cursor: String! 1274 | 1275 | """ 1276 | The relevancy score (0–100) assigned by the search engine, if 1277 | these results were found through a search. 1278 | """ 1279 | score: Int 1280 | } 1281 | 1282 | """ 1283 | An [Interested Parties Information](https://musicbrainz.org/doc/IPI) 1284 | (IPI) code is an identifying number assigned by the CISAC database for musical 1285 | rights management. 1286 | """ 1287 | scalar IPI 1288 | 1289 | """ 1290 | The [International Standard Name Identifier](https://musicbrainz.org/doc/ISNI) 1291 | (ISNI) is an ISO standard for uniquely identifying the public identities of 1292 | contributors to media content. 1293 | """ 1294 | scalar ISNI 1295 | 1296 | """ 1297 | The [International Standard Recording Code](https://musicbrainz.org/doc/ISRC) 1298 | (ISRC) is an identification system for audio and music video recordings. It is 1299 | standarized by the [IFPI](http://www.ifpi.org/) in ISO 3901:2001 and used by 1300 | IFPI members to assign a unique identifier to every distinct sound recording 1301 | they release. An ISRC identifies a particular [sound recording](https://musicbrainz.org/doc/Recording), 1302 | not the song itself. Therefore, different recordings, edits, remixes and 1303 | remasters of the same song will each be assigned their own ISRC. However, note 1304 | that same recording should carry the same ISRC in all countries/territories. 1305 | Songs are identified by analogous [International Standard Musical Work Codes](https://musicbrainz.org/doc/ISWC) 1306 | (ISWCs). 1307 | """ 1308 | scalar ISRC 1309 | 1310 | """ 1311 | The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC) 1312 | (ISWC) is an ISO standard similar to ISBNs for identifying musical works / 1313 | compositions. 1314 | """ 1315 | scalar ISWC 1316 | 1317 | """ 1318 | [Labels](https://musicbrainz.org/doc/Label) represent mostly 1319 | (but not only) imprints. To a lesser extent, a label entity may be created to 1320 | represent a record company. 1321 | """ 1322 | type Label implements Node & Entity { 1323 | """ 1324 | The ID of an object 1325 | """ 1326 | id: ID! 1327 | 1328 | """ 1329 | The MBID of the entity. 1330 | """ 1331 | mbid: MBID! 1332 | 1333 | """ 1334 | The official name of the entity. 1335 | """ 1336 | name: String 1337 | 1338 | """ 1339 | The string to use for the purpose of ordering by name (for 1340 | example, by moving articles like ‘the’ to the end or a person’s last name to 1341 | the front). 1342 | """ 1343 | sortName: String 1344 | 1345 | """ 1346 | A comment used to help distinguish identically named entitites. 1347 | """ 1348 | disambiguation: String 1349 | 1350 | """ 1351 | [Aliases](https://musicbrainz.org/doc/Aliases) are used to store 1352 | alternate names or misspellings. 1353 | """ 1354 | aliases: [Alias] 1355 | 1356 | """ 1357 | The country of origin for the label. 1358 | """ 1359 | country: String 1360 | 1361 | """ 1362 | The area in which the label is based. 1363 | """ 1364 | area: Area 1365 | 1366 | """ 1367 | The begin and end dates of the entity’s existence. Its exact 1368 | meaning depends on the type of entity. 1369 | """ 1370 | lifeSpan: LifeSpan 1371 | 1372 | """ 1373 | The [“LC” code](https://musicbrainz.org/doc/Label/Label_Code) 1374 | of the label. 1375 | """ 1376 | labelCode: Int 1377 | 1378 | """ 1379 | List of [Interested Parties Information](https://musicbrainz.org/doc/IPI) 1380 | codes for the label. 1381 | """ 1382 | ipis: [IPI] 1383 | 1384 | """ 1385 | A type describing the main activity of the label, e.g. 1386 | imprint, production, distributor, rights society, etc. 1387 | """ 1388 | type: String 1389 | 1390 | """ 1391 | The MBID associated with the value of the `type` 1392 | field. 1393 | """ 1394 | typeID: MBID 1395 | 1396 | """ 1397 | A list of releases linked to this entity. 1398 | """ 1399 | releases( 1400 | """ 1401 | Filter by one or more release group types. 1402 | """ 1403 | type: [ReleaseGroupType] 1404 | 1405 | """ 1406 | Filter by one or more release statuses. 1407 | """ 1408 | status: [ReleaseStatus] 1409 | after: String 1410 | first: Int 1411 | ): ReleaseConnection 1412 | 1413 | """ 1414 | Relationships between this entity and other entitites. 1415 | """ 1416 | relationships: Relationships 1417 | 1418 | """ 1419 | A list of collections containing this entity. 1420 | """ 1421 | collections(after: String, first: Int): CollectionConnection 1422 | 1423 | """ 1424 | The rating users have given to this entity. 1425 | """ 1426 | rating: Rating 1427 | 1428 | """ 1429 | A list of tags linked to this entity. 1430 | """ 1431 | tags(after: String, first: Int): TagConnection 1432 | } 1433 | 1434 | """ 1435 | A connection to a list of items. 1436 | """ 1437 | type LabelConnection { 1438 | """ 1439 | Information to aid in pagination. 1440 | """ 1441 | pageInfo: PageInfo! 1442 | 1443 | """ 1444 | A list of edges. 1445 | """ 1446 | edges: [LabelEdge] 1447 | 1448 | """ 1449 | A list of nodes in the connection (without going through the 1450 | `edges` field). 1451 | """ 1452 | nodes: [Label] 1453 | 1454 | """ 1455 | A count of the total number of items in this connection, 1456 | ignoring pagination. 1457 | """ 1458 | totalCount: Int 1459 | } 1460 | 1461 | """ 1462 | An edge in a connection. 1463 | """ 1464 | type LabelEdge { 1465 | """ 1466 | The item at the end of the edge 1467 | """ 1468 | node: Label 1469 | 1470 | """ 1471 | A cursor for use in pagination 1472 | """ 1473 | cursor: String! 1474 | 1475 | """ 1476 | The relevancy score (0–100) assigned by the search engine, if 1477 | these results were found through a search. 1478 | """ 1479 | score: Int 1480 | } 1481 | 1482 | """ 1483 | Fields indicating the begin and end date of an entity’s 1484 | lifetime, including whether it has ended (even if the date is unknown). 1485 | """ 1486 | type LifeSpan { 1487 | """ 1488 | The start date of the entity’s life span. 1489 | """ 1490 | begin: Date 1491 | 1492 | """ 1493 | The end date of the entity’s life span. 1494 | """ 1495 | end: Date 1496 | 1497 | """ 1498 | Whether or not the entity’s life span has ended. 1499 | """ 1500 | ended: Boolean 1501 | } 1502 | 1503 | """ 1504 | Language code, optionally with country and encoding. 1505 | """ 1506 | scalar Locale 1507 | 1508 | """ 1509 | A lookup of an individual MusicBrainz entity by its MBID. 1510 | """ 1511 | type LookupQuery { 1512 | """ 1513 | Look up a specific area by its MBID. 1514 | """ 1515 | area( 1516 | """ 1517 | The MBID of the entity. 1518 | """ 1519 | mbid: MBID! 1520 | ): Area 1521 | 1522 | """ 1523 | Look up a specific artist by its MBID. 1524 | """ 1525 | artist( 1526 | """ 1527 | The MBID of the entity. 1528 | """ 1529 | mbid: MBID! 1530 | ): Artist 1531 | 1532 | """ 1533 | Look up a specific collection by its MBID. 1534 | """ 1535 | collection( 1536 | """ 1537 | The MBID of the entity. 1538 | """ 1539 | mbid: MBID! 1540 | ): Collection 1541 | 1542 | """ 1543 | Look up a specific physical disc by its disc ID. 1544 | """ 1545 | disc( 1546 | """ 1547 | The [disc ID](https://musicbrainz.org/doc/Disc_ID) 1548 | of the disc. 1549 | """ 1550 | discID: DiscID! 1551 | ): Disc 1552 | 1553 | """ 1554 | Look up a specific event by its MBID. 1555 | """ 1556 | event( 1557 | """ 1558 | The MBID of the entity. 1559 | """ 1560 | mbid: MBID! 1561 | ): Event 1562 | 1563 | """ 1564 | Look up a specific instrument by its MBID. 1565 | """ 1566 | instrument( 1567 | """ 1568 | The MBID of the entity. 1569 | """ 1570 | mbid: MBID! 1571 | ): Instrument 1572 | 1573 | """ 1574 | Look up a specific label by its MBID. 1575 | """ 1576 | label( 1577 | """ 1578 | The MBID of the entity. 1579 | """ 1580 | mbid: MBID! 1581 | ): Label 1582 | 1583 | """ 1584 | Look up a specific place by its MBID. 1585 | """ 1586 | place( 1587 | """ 1588 | The MBID of the entity. 1589 | """ 1590 | mbid: MBID! 1591 | ): Place 1592 | 1593 | """ 1594 | Look up a specific recording by its MBID. 1595 | """ 1596 | recording( 1597 | """ 1598 | The MBID of the entity. 1599 | """ 1600 | mbid: MBID! 1601 | ): Recording 1602 | 1603 | """ 1604 | Look up a specific release by its MBID. 1605 | """ 1606 | release( 1607 | """ 1608 | The MBID of the entity. 1609 | """ 1610 | mbid: MBID! 1611 | ): Release 1612 | 1613 | """ 1614 | Look up a specific release group by its MBID. 1615 | """ 1616 | releaseGroup( 1617 | """ 1618 | The MBID of the entity. 1619 | """ 1620 | mbid: MBID! 1621 | ): ReleaseGroup 1622 | 1623 | """ 1624 | Look up a specific series by its MBID. 1625 | """ 1626 | series( 1627 | """ 1628 | The MBID of the entity. 1629 | """ 1630 | mbid: MBID! 1631 | ): Series 1632 | 1633 | """ 1634 | Look up a specific URL by its MBID. 1635 | """ 1636 | url( 1637 | """ 1638 | The MBID of the entity. 1639 | """ 1640 | mbid: MBID 1641 | 1642 | """ 1643 | The web address of the URL entity to look up. 1644 | """ 1645 | resource: URLString 1646 | ): URL 1647 | 1648 | """ 1649 | Look up a specific work by its MBID. 1650 | """ 1651 | work( 1652 | """ 1653 | The MBID of the entity. 1654 | """ 1655 | mbid: MBID! 1656 | ): Work 1657 | } 1658 | 1659 | """ 1660 | The MBID scalar represents MusicBrainz identifiers, which are 1661 | 36-character UUIDs. 1662 | """ 1663 | scalar MBID 1664 | 1665 | """ 1666 | A medium is the actual physical medium the audio content is 1667 | stored upon. This means that each CD in a multi-disc release will be entered as 1668 | separate mediums within the release, and that both sides of a vinyl record or 1669 | cassette will exist on one medium. Mediums have a format (e.g. CD, DVD, vinyl, 1670 | cassette) and can optionally also have a title. 1671 | """ 1672 | type Medium { 1673 | """ 1674 | The title of this particular medium. 1675 | """ 1676 | title: String 1677 | 1678 | """ 1679 | The [format](https://musicbrainz.org/doc/Release/Format) of 1680 | the medium (e.g. CD, DVD, vinyl, cassette). 1681 | """ 1682 | format: String 1683 | 1684 | """ 1685 | The MBID associated with the value of the `format` 1686 | field. 1687 | """ 1688 | formatID: MBID 1689 | 1690 | """ 1691 | The order of this medium in the release (for example, in a 1692 | multi-disc release). 1693 | """ 1694 | position: Int 1695 | 1696 | """ 1697 | The number of audio tracks on this medium. 1698 | """ 1699 | trackCount: Int 1700 | 1701 | """ 1702 | A list of physical discs and their disc IDs for this medium. 1703 | """ 1704 | discs: [Disc] 1705 | 1706 | """ 1707 | The list of tracks on the given media. 1708 | """ 1709 | tracks: [Track] 1710 | } 1711 | 1712 | """ 1713 | An object with an ID 1714 | """ 1715 | interface Node { 1716 | """ 1717 | The id of the object. 1718 | """ 1719 | id: ID! 1720 | } 1721 | 1722 | """ 1723 | Information about pagination in a connection. 1724 | """ 1725 | type PageInfo { 1726 | """ 1727 | When paginating forwards, are there more items? 1728 | """ 1729 | hasNextPage: Boolean! 1730 | 1731 | """ 1732 | When paginating backwards, are there more items? 1733 | """ 1734 | hasPreviousPage: Boolean! 1735 | 1736 | """ 1737 | When paginating backwards, the cursor to continue. 1738 | """ 1739 | startCursor: String 1740 | 1741 | """ 1742 | When paginating forwards, the cursor to continue. 1743 | """ 1744 | endCursor: String 1745 | } 1746 | 1747 | """ 1748 | A [place](https://musicbrainz.org/doc/Place) is a venue, studio, 1749 | or other place where music is performed, recorded, engineered, etc. 1750 | """ 1751 | type Place implements Node & Entity { 1752 | """ 1753 | The ID of an object 1754 | """ 1755 | id: ID! 1756 | 1757 | """ 1758 | The MBID of the entity. 1759 | """ 1760 | mbid: MBID! 1761 | 1762 | """ 1763 | The official name of the entity. 1764 | """ 1765 | name: String 1766 | 1767 | """ 1768 | A comment used to help distinguish identically named entitites. 1769 | """ 1770 | disambiguation: String 1771 | 1772 | """ 1773 | [Aliases](https://musicbrainz.org/doc/Aliases) are used to store 1774 | alternate names or misspellings. 1775 | """ 1776 | aliases: [Alias] 1777 | 1778 | """ 1779 | The address describes the location of the place using the 1780 | standard addressing format for the country it is located in. 1781 | """ 1782 | address: String 1783 | 1784 | """ 1785 | The area entity representing the area, such as the city, in 1786 | which the place is located. 1787 | """ 1788 | area: Area 1789 | 1790 | """ 1791 | The geographic coordinates of the place. 1792 | """ 1793 | coordinates: Coordinates 1794 | 1795 | """ 1796 | The begin and end dates of the entity’s existence. Its exact 1797 | meaning depends on the type of entity. 1798 | """ 1799 | lifeSpan: LifeSpan 1800 | 1801 | """ 1802 | The type categorises the place based on its primary 1803 | function. 1804 | """ 1805 | type: String 1806 | 1807 | """ 1808 | The MBID associated with the value of the `type` 1809 | field. 1810 | """ 1811 | typeID: MBID 1812 | 1813 | """ 1814 | A list of events linked to this entity. 1815 | """ 1816 | events(after: String, first: Int): EventConnection 1817 | 1818 | """ 1819 | Relationships between this entity and other entitites. 1820 | """ 1821 | relationships: Relationships 1822 | 1823 | """ 1824 | A list of collections containing this entity. 1825 | """ 1826 | collections(after: String, first: Int): CollectionConnection 1827 | 1828 | """ 1829 | A list of tags linked to this entity. 1830 | """ 1831 | tags(after: String, first: Int): TagConnection 1832 | } 1833 | 1834 | """ 1835 | A connection to a list of items. 1836 | """ 1837 | type PlaceConnection { 1838 | """ 1839 | Information to aid in pagination. 1840 | """ 1841 | pageInfo: PageInfo! 1842 | 1843 | """ 1844 | A list of edges. 1845 | """ 1846 | edges: [PlaceEdge] 1847 | 1848 | """ 1849 | A list of nodes in the connection (without going through the 1850 | `edges` field). 1851 | """ 1852 | nodes: [Place] 1853 | 1854 | """ 1855 | A count of the total number of items in this connection, 1856 | ignoring pagination. 1857 | """ 1858 | totalCount: Int 1859 | } 1860 | 1861 | """ 1862 | An edge in a connection. 1863 | """ 1864 | type PlaceEdge { 1865 | """ 1866 | The item at the end of the edge 1867 | """ 1868 | node: Place 1869 | 1870 | """ 1871 | A cursor for use in pagination 1872 | """ 1873 | cursor: String! 1874 | 1875 | """ 1876 | The relevancy score (0–100) assigned by the search engine, if 1877 | these results were found through a search. 1878 | """ 1879 | score: Int 1880 | } 1881 | 1882 | """ 1883 | The query root, from which multiple types of MusicBrainz 1884 | requests can be made. 1885 | """ 1886 | type Query { 1887 | """ 1888 | Perform a lookup of a MusicBrainz entity by its MBID. 1889 | """ 1890 | lookup: LookupQuery 1891 | 1892 | """ 1893 | Browse all MusicBrainz entities directly linked to another entity. 1894 | """ 1895 | browse: BrowseQuery 1896 | 1897 | """ 1898 | Search for MusicBrainz entities using Lucene query syntax. 1899 | """ 1900 | search: SearchQuery 1901 | 1902 | """ 1903 | Fetches an object given its ID 1904 | """ 1905 | node( 1906 | """ 1907 | The ID of an object 1908 | """ 1909 | id: ID! 1910 | ): Node 1911 | } 1912 | 1913 | """ 1914 | [Ratings](https://musicbrainz.org/doc/Rating_System) allow users 1915 | to rate MusicBrainz entities. User may assign a value between 1 and 5; these 1916 | values are then aggregated by the server to compute an average community rating 1917 | for the entity. 1918 | """ 1919 | type Rating { 1920 | """ 1921 | The number of votes that have contributed to the rating. 1922 | """ 1923 | voteCount: Int! 1924 | 1925 | """ 1926 | The average rating value based on the aggregated votes. 1927 | """ 1928 | value: Float 1929 | } 1930 | 1931 | """ 1932 | A [recording](https://musicbrainz.org/doc/Recording) is an 1933 | entity in MusicBrainz which can be linked to tracks on releases. Each track must 1934 | always be associated with a single recording, but a recording can be linked to 1935 | any number of tracks. 1936 | 1937 | A recording represents distinct audio that has been used to produce at least one 1938 | released track through copying or mastering. A recording itself is never 1939 | produced solely through copying or mastering. 1940 | 1941 | Generally, the audio represented by a recording corresponds to the audio at a 1942 | stage in the production process before any final mastering but after any editing 1943 | or mixing. 1944 | """ 1945 | type Recording implements Node & Entity { 1946 | """ 1947 | The ID of an object 1948 | """ 1949 | id: ID! 1950 | 1951 | """ 1952 | The MBID of the entity. 1953 | """ 1954 | mbid: MBID! 1955 | 1956 | """ 1957 | The official title of the entity. 1958 | """ 1959 | title: String 1960 | 1961 | """ 1962 | A comment used to help distinguish identically named entitites. 1963 | """ 1964 | disambiguation: String 1965 | 1966 | """ 1967 | [Aliases](https://musicbrainz.org/doc/Aliases) are used to store 1968 | alternate names or misspellings. 1969 | """ 1970 | aliases: [Alias] 1971 | 1972 | """ 1973 | The main credited artist(s). 1974 | """ 1975 | artistCredit: [ArtistCredit] 1976 | @deprecated( 1977 | reason: "The `artistCredit` field has been renamed to\n`artistCredits`, since it is a list of credits and is referred to in the\nplural form throughout the MusicBrainz documentation. This field is deprecated\nand will be removed in a major release in the future. Use the equivalent\n`artistCredits` field." 1978 | ) 1979 | 1980 | """ 1981 | The main credited artist(s). 1982 | """ 1983 | artistCredits: [ArtistCredit] 1984 | 1985 | """ 1986 | A list of [International Standard Recording Codes](https://musicbrainz.org/doc/ISRC) 1987 | (ISRCs) for this recording. 1988 | """ 1989 | isrcs: [ISRC] 1990 | 1991 | """ 1992 | An approximation to the length of the recording, calculated 1993 | from the lengths of the tracks using it. 1994 | """ 1995 | length: Duration 1996 | 1997 | """ 1998 | Whether this is a video recording. 1999 | """ 2000 | video: Boolean 2001 | 2002 | """ 2003 | A list of artists linked to this entity. 2004 | """ 2005 | artists(after: String, first: Int): ArtistConnection 2006 | 2007 | """ 2008 | A list of releases linked to this entity. 2009 | """ 2010 | releases( 2011 | """ 2012 | Filter by one or more release group types. 2013 | """ 2014 | type: [ReleaseGroupType] 2015 | 2016 | """ 2017 | Filter by one or more release statuses. 2018 | """ 2019 | status: [ReleaseStatus] 2020 | after: String 2021 | first: Int 2022 | ): ReleaseConnection 2023 | 2024 | """ 2025 | Relationships between this entity and other entitites. 2026 | """ 2027 | relationships: Relationships 2028 | 2029 | """ 2030 | A list of collections containing this entity. 2031 | """ 2032 | collections(after: String, first: Int): CollectionConnection 2033 | 2034 | """ 2035 | The rating users have given to this entity. 2036 | """ 2037 | rating: Rating 2038 | 2039 | """ 2040 | A list of tags linked to this entity. 2041 | """ 2042 | tags(after: String, first: Int): TagConnection 2043 | } 2044 | 2045 | """ 2046 | A connection to a list of items. 2047 | """ 2048 | type RecordingConnection { 2049 | """ 2050 | Information to aid in pagination. 2051 | """ 2052 | pageInfo: PageInfo! 2053 | 2054 | """ 2055 | A list of edges. 2056 | """ 2057 | edges: [RecordingEdge] 2058 | 2059 | """ 2060 | A list of nodes in the connection (without going through the 2061 | `edges` field). 2062 | """ 2063 | nodes: [Recording] 2064 | 2065 | """ 2066 | A count of the total number of items in this connection, 2067 | ignoring pagination. 2068 | """ 2069 | totalCount: Int 2070 | } 2071 | 2072 | """ 2073 | An edge in a connection. 2074 | """ 2075 | type RecordingEdge { 2076 | """ 2077 | The item at the end of the edge 2078 | """ 2079 | node: Recording 2080 | 2081 | """ 2082 | A cursor for use in pagination 2083 | """ 2084 | cursor: String! 2085 | 2086 | """ 2087 | The relevancy score (0–100) assigned by the search engine, if 2088 | these results were found through a search. 2089 | """ 2090 | score: Int 2091 | } 2092 | 2093 | """ 2094 | [Relationships](https://musicbrainz.org/doc/Relationships) are a 2095 | way to represent all the different ways in which entities are connected to each 2096 | other and to URLs outside MusicBrainz. 2097 | """ 2098 | type Relationship { 2099 | """ 2100 | The target entity. 2101 | """ 2102 | target: Entity! 2103 | 2104 | """ 2105 | The direction of the relationship. 2106 | """ 2107 | direction: String! 2108 | 2109 | """ 2110 | The type of entity on the receiving end of the relationship. 2111 | """ 2112 | targetType: String! 2113 | 2114 | """ 2115 | How the source entity was actually credited, if different 2116 | from its main (performance) name. 2117 | """ 2118 | sourceCredit: String 2119 | 2120 | """ 2121 | How the target entity was actually credited, if different 2122 | from its main (performance) name. 2123 | """ 2124 | targetCredit: String 2125 | 2126 | """ 2127 | The date on which the relationship became applicable. 2128 | """ 2129 | begin: Date 2130 | 2131 | """ 2132 | The date on which the relationship became no longer applicable. 2133 | """ 2134 | end: Date 2135 | 2136 | """ 2137 | Whether the relationship still applies. 2138 | """ 2139 | ended: Boolean 2140 | 2141 | """ 2142 | Attributes which modify the relationship. There is a [list 2143 | of all attributes](https://musicbrainz.org/relationship-attributes), but the 2144 | attributes which are available, and how they should be used, depends on the 2145 | relationship type. 2146 | """ 2147 | attributes: [String] 2148 | 2149 | """ 2150 | The type of relationship. 2151 | """ 2152 | type: String 2153 | 2154 | """ 2155 | The MBID associated with the value of the `type` 2156 | field. 2157 | """ 2158 | typeID: MBID 2159 | } 2160 | 2161 | """ 2162 | A connection to a list of items. 2163 | """ 2164 | type RelationshipConnection { 2165 | """ 2166 | Information to aid in pagination. 2167 | """ 2168 | pageInfo: PageInfo! 2169 | 2170 | """ 2171 | A list of edges. 2172 | """ 2173 | edges: [RelationshipEdge] 2174 | 2175 | """ 2176 | A list of nodes in the connection (without going through the 2177 | `edges` field). 2178 | """ 2179 | nodes: [Relationship] 2180 | 2181 | """ 2182 | A count of the total number of items in this connection, 2183 | ignoring pagination. 2184 | """ 2185 | totalCount: Int 2186 | } 2187 | 2188 | """ 2189 | An edge in a connection. 2190 | """ 2191 | type RelationshipEdge { 2192 | """ 2193 | The item at the end of the edge 2194 | """ 2195 | node: Relationship 2196 | 2197 | """ 2198 | A cursor for use in pagination 2199 | """ 2200 | cursor: String! 2201 | 2202 | """ 2203 | The relevancy score (0–100) assigned by the search engine, if 2204 | these results were found through a search. 2205 | """ 2206 | score: Int 2207 | } 2208 | 2209 | """ 2210 | Lists of entity relationships for each entity type. 2211 | """ 2212 | type Relationships { 2213 | """ 2214 | A list of relationships between these two entity types. 2215 | """ 2216 | areas( 2217 | """ 2218 | Filter by the relationship direction. 2219 | """ 2220 | direction: String 2221 | 2222 | """ 2223 | Filter by the relationship type. 2224 | """ 2225 | type: String 2226 | 2227 | """ 2228 | The MBID associated with the value of the `type` 2229 | field. 2230 | """ 2231 | typeID: MBID 2232 | after: String 2233 | first: Int 2234 | before: String 2235 | last: Int 2236 | ): RelationshipConnection 2237 | 2238 | """ 2239 | A list of relationships between these two entity types. 2240 | """ 2241 | artists( 2242 | """ 2243 | Filter by the relationship direction. 2244 | """ 2245 | direction: String 2246 | 2247 | """ 2248 | Filter by the relationship type. 2249 | """ 2250 | type: String 2251 | 2252 | """ 2253 | The MBID associated with the value of the `type` 2254 | field. 2255 | """ 2256 | typeID: MBID 2257 | after: String 2258 | first: Int 2259 | before: String 2260 | last: Int 2261 | ): RelationshipConnection 2262 | 2263 | """ 2264 | A list of relationships between these two entity types. 2265 | """ 2266 | events( 2267 | """ 2268 | Filter by the relationship direction. 2269 | """ 2270 | direction: String 2271 | 2272 | """ 2273 | Filter by the relationship type. 2274 | """ 2275 | type: String 2276 | 2277 | """ 2278 | The MBID associated with the value of the `type` 2279 | field. 2280 | """ 2281 | typeID: MBID 2282 | after: String 2283 | first: Int 2284 | before: String 2285 | last: Int 2286 | ): RelationshipConnection 2287 | 2288 | """ 2289 | A list of relationships between these two entity types. 2290 | """ 2291 | instruments( 2292 | """ 2293 | Filter by the relationship direction. 2294 | """ 2295 | direction: String 2296 | 2297 | """ 2298 | Filter by the relationship type. 2299 | """ 2300 | type: String 2301 | 2302 | """ 2303 | The MBID associated with the value of the `type` 2304 | field. 2305 | """ 2306 | typeID: MBID 2307 | after: String 2308 | first: Int 2309 | before: String 2310 | last: Int 2311 | ): RelationshipConnection 2312 | 2313 | """ 2314 | A list of relationships between these two entity types. 2315 | """ 2316 | labels( 2317 | """ 2318 | Filter by the relationship direction. 2319 | """ 2320 | direction: String 2321 | 2322 | """ 2323 | Filter by the relationship type. 2324 | """ 2325 | type: String 2326 | 2327 | """ 2328 | The MBID associated with the value of the `type` 2329 | field. 2330 | """ 2331 | typeID: MBID 2332 | after: String 2333 | first: Int 2334 | before: String 2335 | last: Int 2336 | ): RelationshipConnection 2337 | 2338 | """ 2339 | A list of relationships between these two entity types. 2340 | """ 2341 | places( 2342 | """ 2343 | Filter by the relationship direction. 2344 | """ 2345 | direction: String 2346 | 2347 | """ 2348 | Filter by the relationship type. 2349 | """ 2350 | type: String 2351 | 2352 | """ 2353 | The MBID associated with the value of the `type` 2354 | field. 2355 | """ 2356 | typeID: MBID 2357 | after: String 2358 | first: Int 2359 | before: String 2360 | last: Int 2361 | ): RelationshipConnection 2362 | 2363 | """ 2364 | A list of relationships between these two entity types. 2365 | """ 2366 | recordings( 2367 | """ 2368 | Filter by the relationship direction. 2369 | """ 2370 | direction: String 2371 | 2372 | """ 2373 | Filter by the relationship type. 2374 | """ 2375 | type: String 2376 | 2377 | """ 2378 | The MBID associated with the value of the `type` 2379 | field. 2380 | """ 2381 | typeID: MBID 2382 | after: String 2383 | first: Int 2384 | before: String 2385 | last: Int 2386 | ): RelationshipConnection 2387 | 2388 | """ 2389 | A list of relationships between these two entity types. 2390 | """ 2391 | releases( 2392 | """ 2393 | Filter by the relationship direction. 2394 | """ 2395 | direction: String 2396 | 2397 | """ 2398 | Filter by the relationship type. 2399 | """ 2400 | type: String 2401 | 2402 | """ 2403 | The MBID associated with the value of the `type` 2404 | field. 2405 | """ 2406 | typeID: MBID 2407 | after: String 2408 | first: Int 2409 | before: String 2410 | last: Int 2411 | ): RelationshipConnection 2412 | 2413 | """ 2414 | A list of relationships between these two entity types. 2415 | """ 2416 | releaseGroups( 2417 | """ 2418 | Filter by the relationship direction. 2419 | """ 2420 | direction: String 2421 | 2422 | """ 2423 | Filter by the relationship type. 2424 | """ 2425 | type: String 2426 | 2427 | """ 2428 | The MBID associated with the value of the `type` 2429 | field. 2430 | """ 2431 | typeID: MBID 2432 | after: String 2433 | first: Int 2434 | before: String 2435 | last: Int 2436 | ): RelationshipConnection 2437 | 2438 | """ 2439 | A list of relationships between these two entity types. 2440 | """ 2441 | series( 2442 | """ 2443 | Filter by the relationship direction. 2444 | """ 2445 | direction: String 2446 | 2447 | """ 2448 | Filter by the relationship type. 2449 | """ 2450 | type: String 2451 | 2452 | """ 2453 | The MBID associated with the value of the `type` 2454 | field. 2455 | """ 2456 | typeID: MBID 2457 | after: String 2458 | first: Int 2459 | before: String 2460 | last: Int 2461 | ): RelationshipConnection 2462 | 2463 | """ 2464 | A list of relationships between these two entity types. 2465 | """ 2466 | urls( 2467 | """ 2468 | Filter by the relationship direction. 2469 | """ 2470 | direction: String 2471 | 2472 | """ 2473 | Filter by the relationship type. 2474 | """ 2475 | type: String 2476 | 2477 | """ 2478 | The MBID associated with the value of the `type` 2479 | field. 2480 | """ 2481 | typeID: MBID 2482 | after: String 2483 | first: Int 2484 | before: String 2485 | last: Int 2486 | ): RelationshipConnection 2487 | 2488 | """ 2489 | A list of relationships between these two entity types. 2490 | """ 2491 | works( 2492 | """ 2493 | Filter by the relationship direction. 2494 | """ 2495 | direction: String 2496 | 2497 | """ 2498 | Filter by the relationship type. 2499 | """ 2500 | type: String 2501 | 2502 | """ 2503 | The MBID associated with the value of the `type` 2504 | field. 2505 | """ 2506 | typeID: MBID 2507 | after: String 2508 | first: Int 2509 | before: String 2510 | last: Int 2511 | ): RelationshipConnection 2512 | } 2513 | 2514 | """ 2515 | A [release](https://musicbrainz.org/doc/Release) represents the 2516 | unique release (i.e. issuing) of a product on a specific date with specific 2517 | release information such as the country, label, barcode, packaging, etc. If you 2518 | walk into a store and purchase an album or single, they’re each represented in 2519 | MusicBrainz as one release. 2520 | """ 2521 | type Release implements Node & Entity { 2522 | """ 2523 | The ID of an object 2524 | """ 2525 | id: ID! 2526 | 2527 | """ 2528 | The MBID of the entity. 2529 | """ 2530 | mbid: MBID! 2531 | 2532 | """ 2533 | The official title of the entity. 2534 | """ 2535 | title: String 2536 | 2537 | """ 2538 | A comment used to help distinguish identically named entitites. 2539 | """ 2540 | disambiguation: String 2541 | 2542 | """ 2543 | [Aliases](https://musicbrainz.org/doc/Aliases) are used to store 2544 | alternate names or misspellings. 2545 | """ 2546 | aliases: [Alias] 2547 | 2548 | """ 2549 | The main credited artist(s). 2550 | """ 2551 | artistCredit: [ArtistCredit] 2552 | @deprecated( 2553 | reason: "The `artistCredit` field has been renamed to\n`artistCredits`, since it is a list of credits and is referred to in the\nplural form throughout the MusicBrainz documentation. This field is deprecated\nand will be removed in a major release in the future. Use the equivalent\n`artistCredits` field." 2554 | ) 2555 | 2556 | """ 2557 | The main credited artist(s). 2558 | """ 2559 | artistCredits: [ArtistCredit] 2560 | 2561 | """ 2562 | The release events for this release. 2563 | """ 2564 | releaseEvents: [ReleaseEvent] 2565 | 2566 | """ 2567 | The [release date](https://musicbrainz.org/doc/Release/Date) 2568 | is the date in which a release was made available through some sort of 2569 | distribution mechanism. 2570 | """ 2571 | date: Date 2572 | 2573 | """ 2574 | The country in which the release was issued. 2575 | """ 2576 | country: String 2577 | 2578 | """ 2579 | The [Amazon Standard Identification Number](https://musicbrainz.org/doc/ASIN) 2580 | of the release. 2581 | """ 2582 | asin: ASIN 2583 | 2584 | """ 2585 | The [barcode](https://en.wikipedia.org/wiki/Barcode), if the 2586 | release has one. The most common types found on releases are 12-digit 2587 | [UPCs](https://en.wikipedia.org/wiki/Universal_Product_Code) and 13-digit 2588 | [EANs](https://en.wikipedia.org/wiki/International_Article_Number). 2589 | """ 2590 | barcode: String 2591 | 2592 | """ 2593 | The status describes how “official” a release is. 2594 | """ 2595 | status: ReleaseStatus 2596 | 2597 | """ 2598 | The MBID associated with the value of the `status` 2599 | field. 2600 | """ 2601 | statusID: MBID 2602 | 2603 | """ 2604 | The physical packaging that accompanies the release. See 2605 | the [list of packaging](https://musicbrainz.org/doc/Release/Packaging) for more 2606 | information. 2607 | """ 2608 | packaging: String 2609 | 2610 | """ 2611 | The MBID associated with the value of the `packaging` 2612 | field. 2613 | """ 2614 | packagingID: MBID 2615 | 2616 | """ 2617 | Data quality indicates how good the data for a release is. 2618 | It is not a mark of how good or bad the music itself is – for that, use 2619 | [ratings](https://musicbrainz.org/doc/Rating_System). 2620 | """ 2621 | quality: String 2622 | 2623 | """ 2624 | The media on which the release was distributed. 2625 | """ 2626 | media: [Medium] 2627 | 2628 | """ 2629 | A list of artists linked to this entity. 2630 | """ 2631 | artists(after: String, first: Int): ArtistConnection 2632 | 2633 | """ 2634 | A list of labels linked to this entity. 2635 | """ 2636 | labels(after: String, first: Int): LabelConnection 2637 | 2638 | """ 2639 | A list of recordings linked to this entity. 2640 | """ 2641 | recordings(after: String, first: Int): RecordingConnection 2642 | 2643 | """ 2644 | A list of release groups linked to this entity. 2645 | """ 2646 | releaseGroups( 2647 | """ 2648 | Filter by one or more release group types. 2649 | """ 2650 | type: [ReleaseGroupType] 2651 | after: String 2652 | first: Int 2653 | ): ReleaseGroupConnection 2654 | 2655 | """ 2656 | Relationships between this entity and other entitites. 2657 | """ 2658 | relationships: Relationships 2659 | 2660 | """ 2661 | A list of collections containing this entity. 2662 | """ 2663 | collections(after: String, first: Int): CollectionConnection 2664 | 2665 | """ 2666 | A list of tags linked to this entity. 2667 | """ 2668 | tags(after: String, first: Int): TagConnection 2669 | } 2670 | 2671 | """ 2672 | A connection to a list of items. 2673 | """ 2674 | type ReleaseConnection { 2675 | """ 2676 | Information to aid in pagination. 2677 | """ 2678 | pageInfo: PageInfo! 2679 | 2680 | """ 2681 | A list of edges. 2682 | """ 2683 | edges: [ReleaseEdge] 2684 | 2685 | """ 2686 | A list of nodes in the connection (without going through the 2687 | `edges` field). 2688 | """ 2689 | nodes: [Release] 2690 | 2691 | """ 2692 | A count of the total number of items in this connection, 2693 | ignoring pagination. 2694 | """ 2695 | totalCount: Int 2696 | } 2697 | 2698 | """ 2699 | An edge in a connection. 2700 | """ 2701 | type ReleaseEdge { 2702 | """ 2703 | The item at the end of the edge 2704 | """ 2705 | node: Release 2706 | 2707 | """ 2708 | A cursor for use in pagination 2709 | """ 2710 | cursor: String! 2711 | 2712 | """ 2713 | The relevancy score (0–100) assigned by the search engine, if 2714 | these results were found through a search. 2715 | """ 2716 | score: Int 2717 | } 2718 | 2719 | """ 2720 | The date on which a release was issued in a country/region with 2721 | a particular label, catalog number, barcode, and format. 2722 | """ 2723 | type ReleaseEvent { 2724 | area: Area 2725 | date: Date 2726 | } 2727 | 2728 | """ 2729 | A [release group](https://musicbrainz.org/doc/Release_Group) is 2730 | used to group several different releases into a single logical entity. Every 2731 | release belongs to one, and only one release group. 2732 | 2733 | Both release groups and releases are “albums” in a general sense, but with an 2734 | important difference: a release is something you can buy as media such as a CD 2735 | or a vinyl record, while a release group embraces the overall concept of an 2736 | album – it doesn’t matter how many CDs or editions/versions it had. 2737 | """ 2738 | type ReleaseGroup implements Node & Entity { 2739 | """ 2740 | The ID of an object 2741 | """ 2742 | id: ID! 2743 | 2744 | """ 2745 | The MBID of the entity. 2746 | """ 2747 | mbid: MBID! 2748 | 2749 | """ 2750 | The official title of the entity. 2751 | """ 2752 | title: String 2753 | 2754 | """ 2755 | A comment used to help distinguish identically named entitites. 2756 | """ 2757 | disambiguation: String 2758 | 2759 | """ 2760 | [Aliases](https://musicbrainz.org/doc/Aliases) are used to store 2761 | alternate names or misspellings. 2762 | """ 2763 | aliases: [Alias] 2764 | 2765 | """ 2766 | The main credited artist(s). 2767 | """ 2768 | artistCredit: [ArtistCredit] 2769 | @deprecated( 2770 | reason: "The `artistCredit` field has been renamed to\n`artistCredits`, since it is a list of credits and is referred to in the\nplural form throughout the MusicBrainz documentation. This field is deprecated\nand will be removed in a major release in the future. Use the equivalent\n`artistCredits` field." 2771 | ) 2772 | 2773 | """ 2774 | The main credited artist(s). 2775 | """ 2776 | artistCredits: [ArtistCredit] 2777 | 2778 | """ 2779 | The date of the earliest release in the group. 2780 | """ 2781 | firstReleaseDate: Date 2782 | 2783 | """ 2784 | The [type](https://musicbrainz.org/doc/Release_Group/Type) 2785 | of a release group describes what kind of releases the release group represents, 2786 | e.g. album, single, soundtrack, compilation, etc. A release group can have a 2787 | “main” type and an unspecified number of additional types. 2788 | """ 2789 | primaryType: ReleaseGroupType 2790 | 2791 | """ 2792 | The MBID associated with the value of the `primaryType` 2793 | field. 2794 | """ 2795 | primaryTypeID: MBID 2796 | 2797 | """ 2798 | Additional [types](https://musicbrainz.org/doc/Release_Group/Type) 2799 | that apply to this release group. 2800 | """ 2801 | secondaryTypes: [ReleaseGroupType] 2802 | 2803 | """ 2804 | The MBIDs associated with the values of the `secondaryTypes` 2805 | field. 2806 | """ 2807 | secondaryTypeIDs: [MBID] 2808 | 2809 | """ 2810 | A list of artists linked to this entity. 2811 | """ 2812 | artists(after: String, first: Int): ArtistConnection 2813 | 2814 | """ 2815 | A list of releases linked to this entity. 2816 | """ 2817 | releases( 2818 | """ 2819 | Filter by one or more release group types. 2820 | """ 2821 | type: [ReleaseGroupType] 2822 | 2823 | """ 2824 | Filter by one or more release statuses. 2825 | """ 2826 | status: [ReleaseStatus] 2827 | after: String 2828 | first: Int 2829 | ): ReleaseConnection 2830 | 2831 | """ 2832 | Relationships between this entity and other entitites. 2833 | """ 2834 | relationships: Relationships 2835 | 2836 | """ 2837 | A list of collections containing this entity. 2838 | """ 2839 | collections(after: String, first: Int): CollectionConnection 2840 | 2841 | """ 2842 | The rating users have given to this entity. 2843 | """ 2844 | rating: Rating 2845 | 2846 | """ 2847 | A list of tags linked to this entity. 2848 | """ 2849 | tags(after: String, first: Int): TagConnection 2850 | } 2851 | 2852 | """ 2853 | A connection to a list of items. 2854 | """ 2855 | type ReleaseGroupConnection { 2856 | """ 2857 | Information to aid in pagination. 2858 | """ 2859 | pageInfo: PageInfo! 2860 | 2861 | """ 2862 | A list of edges. 2863 | """ 2864 | edges: [ReleaseGroupEdge] 2865 | 2866 | """ 2867 | A list of nodes in the connection (without going through the 2868 | `edges` field). 2869 | """ 2870 | nodes: [ReleaseGroup] 2871 | 2872 | """ 2873 | A count of the total number of items in this connection, 2874 | ignoring pagination. 2875 | """ 2876 | totalCount: Int 2877 | } 2878 | 2879 | """ 2880 | An edge in a connection. 2881 | """ 2882 | type ReleaseGroupEdge { 2883 | """ 2884 | The item at the end of the edge 2885 | """ 2886 | node: ReleaseGroup 2887 | 2888 | """ 2889 | A cursor for use in pagination 2890 | """ 2891 | cursor: String! 2892 | 2893 | """ 2894 | The relevancy score (0–100) assigned by the search engine, if 2895 | these results were found through a search. 2896 | """ 2897 | score: Int 2898 | } 2899 | 2900 | """ 2901 | A type used to describe release groups, e.g. album, single, EP, 2902 | etc. 2903 | """ 2904 | enum ReleaseGroupType { 2905 | """ 2906 | An album, perhaps better defined as a “Long Play” (LP) 2907 | release, generally consists of previously unreleased material (unless this type 2908 | is combined with secondary types which change that, such as “Compilation”). This 2909 | includes album re-issues, with or without bonus tracks. 2910 | """ 2911 | ALBUM 2912 | 2913 | """ 2914 | A single typically has one main song and possibly a handful 2915 | of additional tracks or remixes of the main track. A single is usually named 2916 | after its main song. 2917 | """ 2918 | SINGLE 2919 | 2920 | """ 2921 | An EP is a so-called “Extended Play” release and often 2922 | contains the letters EP in the title. Generally an EP will be shorter than a 2923 | full length release (an LP or “Long Play”) and the tracks are usually exclusive 2924 | to the EP, in other words the tracks don’t come from a previously issued 2925 | release. EP is fairly difficult to define; usually it should only be assumed 2926 | that a release is an EP if the artist defines it as such. 2927 | """ 2928 | EP 2929 | 2930 | """ 2931 | Any release that does not fit any of the other categories. 2932 | """ 2933 | OTHER 2934 | 2935 | """ 2936 | An episodic release that was originally broadcast via radio, 2937 | television, or the Internet, including podcasts. 2938 | """ 2939 | BROADCAST 2940 | 2941 | """ 2942 | A compilation is a collection of previously released tracks 2943 | by one or more artists. 2944 | """ 2945 | COMPILATION 2946 | 2947 | """ 2948 | A soundtrack is the musical score to a movie, TV series, 2949 | stage show, computer game, etc. 2950 | """ 2951 | SOUNDTRACK 2952 | 2953 | """ 2954 | A non-music spoken word release. 2955 | """ 2956 | SPOKENWORD 2957 | 2958 | """ 2959 | An interview release contains an interview, generally with 2960 | an artist. 2961 | """ 2962 | INTERVIEW 2963 | 2964 | """ 2965 | An audiobook is a book read by a narrator without music. 2966 | """ 2967 | AUDIOBOOK 2968 | 2969 | """ 2970 | A release that was recorded live. 2971 | """ 2972 | LIVE 2973 | 2974 | """ 2975 | A release that was (re)mixed from previously released 2976 | material. 2977 | """ 2978 | REMIX 2979 | 2980 | """ 2981 | A DJ-mix is a sequence of several recordings played one 2982 | after the other, each one modified so that they blend together into a continuous 2983 | flow of music. A DJ mix release requires that the recordings be modified in some 2984 | manner, and the DJ who does this modification is usually (although not always) 2985 | credited in a fairly prominent way. 2986 | """ 2987 | DJMIX 2988 | 2989 | """ 2990 | Promotional in nature (but not necessarily free), mixtapes 2991 | and street albums are often released by artists to promote new artists, or 2992 | upcoming studio albums by prominent artists. They are also sometimes used to 2993 | keep fans’ attention between studio releases and are most common in rap & hip 2994 | hop genres. They are often not sanctioned by the artist’s label, may lack proper 2995 | sample or song clearances and vary widely in production and recording quality. 2996 | While mixtapes are generally DJ-mixed, they are distinct from commercial DJ 2997 | mixes (which are usually deemed compilations) and are defined by having a 2998 | significant proportion of new material, including original production or 2999 | original vocals over top of other artists’ instrumentals. They are distinct from 3000 | demos in that they are designed for release directly to the public and fans, not 3001 | to labels. 3002 | """ 3003 | MIXTAPE 3004 | 3005 | """ 3006 | A release that was recorded for limited circulation or 3007 | reference use rather than for general public release. 3008 | """ 3009 | DEMO 3010 | 3011 | """ 3012 | A non-album track (special case). 3013 | """ 3014 | NAT 3015 | } 3016 | 3017 | """ 3018 | A type used to describe the status of releases, e.g. official, 3019 | bootleg, etc. 3020 | """ 3021 | enum ReleaseStatus { 3022 | """ 3023 | Any release officially sanctioned by the artist and/or their 3024 | record company. (Most releases will fit into this category.) 3025 | """ 3026 | OFFICIAL 3027 | 3028 | """ 3029 | A giveaway release or a release intended to promote an 3030 | upcoming official release, e.g. prerelease albums or releases included with a 3031 | magazine. 3032 | """ 3033 | PROMOTION 3034 | 3035 | """ 3036 | An unofficial/underground release that was not sanctioned by 3037 | the artist and/or the record company. 3038 | """ 3039 | BOOTLEG 3040 | 3041 | """ 3042 | A pseudo-release is a duplicate release for 3043 | translation/transliteration purposes. 3044 | """ 3045 | PSEUDORELEASE 3046 | } 3047 | 3048 | """ 3049 | A search for MusicBrainz entities using Lucene query syntax. 3050 | """ 3051 | type SearchQuery { 3052 | """ 3053 | Search for area entities matching the given query. 3054 | """ 3055 | areas( 3056 | """ 3057 | The query terms, in Lucene search syntax. See [examples 3058 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3059 | """ 3060 | query: String! 3061 | after: String 3062 | first: Int 3063 | ): AreaConnection 3064 | 3065 | """ 3066 | Search for artist entities matching the given query. 3067 | """ 3068 | artists( 3069 | """ 3070 | The query terms, in Lucene search syntax. See [examples 3071 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3072 | """ 3073 | query: String! 3074 | after: String 3075 | first: Int 3076 | ): ArtistConnection 3077 | 3078 | """ 3079 | Search for event entities matching the given query. 3080 | """ 3081 | events( 3082 | """ 3083 | The query terms, in Lucene search syntax. See [examples 3084 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3085 | """ 3086 | query: String! 3087 | after: String 3088 | first: Int 3089 | ): EventConnection 3090 | 3091 | """ 3092 | Search for instrument entities matching the given query. 3093 | """ 3094 | instruments( 3095 | """ 3096 | The query terms, in Lucene search syntax. See [examples 3097 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3098 | """ 3099 | query: String! 3100 | after: String 3101 | first: Int 3102 | ): InstrumentConnection 3103 | 3104 | """ 3105 | Search for label entities matching the given query. 3106 | """ 3107 | labels( 3108 | """ 3109 | The query terms, in Lucene search syntax. See [examples 3110 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3111 | """ 3112 | query: String! 3113 | after: String 3114 | first: Int 3115 | ): LabelConnection 3116 | 3117 | """ 3118 | Search for place entities matching the given query. 3119 | """ 3120 | places( 3121 | """ 3122 | The query terms, in Lucene search syntax. See [examples 3123 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3124 | """ 3125 | query: String! 3126 | after: String 3127 | first: Int 3128 | ): PlaceConnection 3129 | 3130 | """ 3131 | Search for recording entities matching the given query. 3132 | """ 3133 | recordings( 3134 | """ 3135 | The query terms, in Lucene search syntax. See [examples 3136 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3137 | """ 3138 | query: String! 3139 | after: String 3140 | first: Int 3141 | ): RecordingConnection 3142 | 3143 | """ 3144 | Search for release entities matching the given query. 3145 | """ 3146 | releases( 3147 | """ 3148 | The query terms, in Lucene search syntax. See [examples 3149 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3150 | """ 3151 | query: String! 3152 | after: String 3153 | first: Int 3154 | ): ReleaseConnection 3155 | 3156 | """ 3157 | Search for release group entities matching the given query. 3158 | """ 3159 | releaseGroups( 3160 | """ 3161 | The query terms, in Lucene search syntax. See [examples 3162 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3163 | """ 3164 | query: String! 3165 | after: String 3166 | first: Int 3167 | ): ReleaseGroupConnection 3168 | 3169 | """ 3170 | Search for series entities matching the given query. 3171 | """ 3172 | series( 3173 | """ 3174 | The query terms, in Lucene search syntax. See [examples 3175 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3176 | """ 3177 | query: String! 3178 | after: String 3179 | first: Int 3180 | ): SeriesConnection 3181 | 3182 | """ 3183 | Search for work entities matching the given query. 3184 | """ 3185 | works( 3186 | """ 3187 | The query terms, in Lucene search syntax. See [examples 3188 | and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search). 3189 | """ 3190 | query: String! 3191 | after: String 3192 | first: Int 3193 | ): WorkConnection 3194 | } 3195 | 3196 | """ 3197 | A [series](https://musicbrainz.org/doc/Series) is a sequence of 3198 | separate release groups, releases, recordings, works or events with a common 3199 | theme. 3200 | """ 3201 | type Series implements Node & Entity { 3202 | """ 3203 | The ID of an object 3204 | """ 3205 | id: ID! 3206 | 3207 | """ 3208 | The MBID of the entity. 3209 | """ 3210 | mbid: MBID! 3211 | 3212 | """ 3213 | The official name of the entity. 3214 | """ 3215 | name: String 3216 | 3217 | """ 3218 | A comment used to help distinguish identically named entitites. 3219 | """ 3220 | disambiguation: String 3221 | 3222 | """ 3223 | The type primarily describes what type of entity the series 3224 | contains. 3225 | """ 3226 | type: String 3227 | 3228 | """ 3229 | The MBID associated with the value of the `type` 3230 | field. 3231 | """ 3232 | typeID: MBID 3233 | 3234 | """ 3235 | Relationships between this entity and other entitites. 3236 | """ 3237 | relationships: Relationships 3238 | 3239 | """ 3240 | A list of collections containing this entity. 3241 | """ 3242 | collections(after: String, first: Int): CollectionConnection 3243 | 3244 | """ 3245 | A list of tags linked to this entity. 3246 | """ 3247 | tags(after: String, first: Int): TagConnection 3248 | } 3249 | 3250 | """ 3251 | A connection to a list of items. 3252 | """ 3253 | type SeriesConnection { 3254 | """ 3255 | Information to aid in pagination. 3256 | """ 3257 | pageInfo: PageInfo! 3258 | 3259 | """ 3260 | A list of edges. 3261 | """ 3262 | edges: [SeriesEdge] 3263 | 3264 | """ 3265 | A list of nodes in the connection (without going through the 3266 | `edges` field). 3267 | """ 3268 | nodes: [Series] 3269 | 3270 | """ 3271 | A count of the total number of items in this connection, 3272 | ignoring pagination. 3273 | """ 3274 | totalCount: Int 3275 | } 3276 | 3277 | """ 3278 | An edge in a connection. 3279 | """ 3280 | type SeriesEdge { 3281 | """ 3282 | The item at the end of the edge 3283 | """ 3284 | node: Series 3285 | 3286 | """ 3287 | A cursor for use in pagination 3288 | """ 3289 | cursor: String! 3290 | 3291 | """ 3292 | The relevancy score (0–100) assigned by the search engine, if 3293 | these results were found through a search. 3294 | """ 3295 | score: Int 3296 | } 3297 | 3298 | """ 3299 | [Tags](https://musicbrainz.org/tags) are a way to mark entities 3300 | with extra information – for example, the genres that apply to an artist, 3301 | release, or recording. 3302 | """ 3303 | type Tag { 3304 | """ 3305 | The tag label. 3306 | """ 3307 | name: String! 3308 | 3309 | """ 3310 | How many times this tag has been applied to the entity. 3311 | """ 3312 | count: Int 3313 | } 3314 | 3315 | """ 3316 | A connection to a list of items. 3317 | """ 3318 | type TagConnection { 3319 | """ 3320 | Information to aid in pagination. 3321 | """ 3322 | pageInfo: PageInfo! 3323 | 3324 | """ 3325 | A list of edges. 3326 | """ 3327 | edges: [TagEdge] 3328 | 3329 | """ 3330 | A list of nodes in the connection (without going through the 3331 | `edges` field). 3332 | """ 3333 | nodes: [Tag] 3334 | 3335 | """ 3336 | A count of the total number of items in this connection, 3337 | ignoring pagination. 3338 | """ 3339 | totalCount: Int 3340 | } 3341 | 3342 | """ 3343 | An edge in a connection. 3344 | """ 3345 | type TagEdge { 3346 | """ 3347 | The item at the end of the edge 3348 | """ 3349 | node: Tag 3350 | 3351 | """ 3352 | A cursor for use in pagination 3353 | """ 3354 | cursor: String! 3355 | 3356 | """ 3357 | The relevancy score (0–100) assigned by the search engine, if 3358 | these results were found through a search. 3359 | """ 3360 | score: Int 3361 | } 3362 | 3363 | """ 3364 | A time of day, in 24-hour hh:mm notation. 3365 | """ 3366 | scalar Time 3367 | 3368 | """ 3369 | A track is the way a recording is represented on a particular 3370 | release (or, more exactly, on a particular medium). Every track has a title 3371 | (see the guidelines for titles) and is credited to one or more artists. 3372 | """ 3373 | type Track implements Entity { 3374 | """ 3375 | The MBID of the entity. 3376 | """ 3377 | mbid: MBID! 3378 | 3379 | """ 3380 | The official title of the entity. 3381 | """ 3382 | title: String 3383 | 3384 | """ 3385 | The track’s position on the overall release (including all 3386 | tracks from all discs). 3387 | """ 3388 | position: Int 3389 | 3390 | """ 3391 | The track number, which may include information about the 3392 | disc or side it appears on, e.g. “A1” or “B3”. 3393 | """ 3394 | number: String 3395 | 3396 | """ 3397 | The length of the track. 3398 | """ 3399 | length: Duration 3400 | 3401 | """ 3402 | The recording that appears on the track. 3403 | """ 3404 | recording: Recording 3405 | } 3406 | 3407 | """ 3408 | A [URL](https://musicbrainz.org/doc/URL) pointing to a resource 3409 | external to MusicBrainz, i.e. an official homepage, a site where music can be 3410 | acquired, an entry in another database, etc. 3411 | """ 3412 | type URL implements Node & Entity { 3413 | """ 3414 | The ID of an object 3415 | """ 3416 | id: ID! 3417 | 3418 | """ 3419 | The MBID of the entity. 3420 | """ 3421 | mbid: MBID! 3422 | 3423 | """ 3424 | The actual URL string. 3425 | """ 3426 | resource: URLString! 3427 | 3428 | """ 3429 | Relationships between this entity and other entitites. 3430 | """ 3431 | relationships: Relationships 3432 | } 3433 | 3434 | """ 3435 | A web address. 3436 | """ 3437 | scalar URLString 3438 | 3439 | """ 3440 | A [work](https://musicbrainz.org/doc/Work) is a distinct 3441 | intellectual or artistic creation, which can be expressed in the form of one or 3442 | more audio recordings. 3443 | """ 3444 | type Work implements Node & Entity { 3445 | """ 3446 | The ID of an object 3447 | """ 3448 | id: ID! 3449 | 3450 | """ 3451 | The MBID of the entity. 3452 | """ 3453 | mbid: MBID! 3454 | 3455 | """ 3456 | The official title of the entity. 3457 | """ 3458 | title: String 3459 | 3460 | """ 3461 | A comment used to help distinguish identically named entitites. 3462 | """ 3463 | disambiguation: String 3464 | 3465 | """ 3466 | [Aliases](https://musicbrainz.org/doc/Aliases) are used to store 3467 | alternate names or misspellings. 3468 | """ 3469 | aliases: [Alias] 3470 | 3471 | """ 3472 | A list of [ISWCs](https://musicbrainz.org/doc/ISWC) assigned 3473 | to the work by copyright collecting agencies. 3474 | """ 3475 | iswcs: [String] 3476 | 3477 | """ 3478 | The language in which the work was originally written. 3479 | """ 3480 | language: String 3481 | 3482 | """ 3483 | The type of work. 3484 | """ 3485 | type: String 3486 | 3487 | """ 3488 | The MBID associated with the value of the `type` 3489 | field. 3490 | """ 3491 | typeID: MBID 3492 | 3493 | """ 3494 | A list of artists linked to this entity. 3495 | """ 3496 | artists(after: String, first: Int): ArtistConnection 3497 | 3498 | """ 3499 | Relationships between this entity and other entitites. 3500 | """ 3501 | relationships: Relationships 3502 | 3503 | """ 3504 | A list of collections containing this entity. 3505 | """ 3506 | collections(after: String, first: Int): CollectionConnection 3507 | 3508 | """ 3509 | The rating users have given to this entity. 3510 | """ 3511 | rating: Rating 3512 | 3513 | """ 3514 | A list of tags linked to this entity. 3515 | """ 3516 | tags(after: String, first: Int): TagConnection 3517 | } 3518 | 3519 | """ 3520 | A connection to a list of items. 3521 | """ 3522 | type WorkConnection { 3523 | """ 3524 | Information to aid in pagination. 3525 | """ 3526 | pageInfo: PageInfo! 3527 | 3528 | """ 3529 | A list of edges. 3530 | """ 3531 | edges: [WorkEdge] 3532 | 3533 | """ 3534 | A list of nodes in the connection (without going through the 3535 | `edges` field). 3536 | """ 3537 | nodes: [Work] 3538 | 3539 | """ 3540 | A count of the total number of items in this connection, 3541 | ignoring pagination. 3542 | """ 3543 | totalCount: Int 3544 | } 3545 | 3546 | """ 3547 | An edge in a connection. 3548 | """ 3549 | type WorkEdge { 3550 | """ 3551 | The item at the end of the edge 3552 | """ 3553 | node: Work 3554 | 3555 | """ 3556 | A cursor for use in pagination 3557 | """ 3558 | cursor: String! 3559 | 3560 | """ 3561 | The relevancy score (0–100) assigned by the search engine, if 3562 | these results were found through a search. 3563 | """ 3564 | score: Int 3565 | } 3566 | -------------------------------------------------------------------------------- /test/fixtures/input-objects.graphql: -------------------------------------------------------------------------------- 1 | input MessageInput { 2 | content: String 3 | author: String 4 | } 5 | 6 | type Message { 7 | id: ID! 8 | content: String 9 | author: String 10 | } 11 | 12 | type Query { 13 | getMessage(id: ID!): Message 14 | } 15 | 16 | type Mutation { 17 | createMessage(input: MessageInput): Message 18 | updateMessage(id: ID!, input: MessageInput): Message 19 | } 20 | 21 | type Subscription { 22 | """ 23 | Subscribe to new messages. 24 | """ 25 | messageSent: Message 26 | } 27 | -------------------------------------------------------------------------------- /test/fixtures/input-objects.md: -------------------------------------------------------------------------------- 1 | # Schema Types 2 | 3 |
4 | Table of Contents 5 | 6 | * [Query](#query) 7 | * [Mutation](#mutation) 8 | * [Subscription](#subscription) 9 | * [Objects](#objects) 10 | * [Message](#message) 11 | * [Inputs](#inputs) 12 | * [MessageInput](#messageinput) 13 | * [Scalars](#scalars) 14 | * [Boolean](#boolean) 15 | * [ID](#id) 16 | * [String](#string) 17 | 18 |
19 | 20 | ## Query 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
FieldArgumentTypeDescription
getMessageMessage
idID!
43 | 44 | ## Mutation 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 |
FieldArgumentTypeDescription
createMessageMessage
inputMessageInput
updateMessageMessage
idID!
inputMessageInput
82 | 83 | ## Subscription 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 102 | 103 | 104 |
FieldArgumentTypeDescription
messageSentMessage 98 | 99 | Subscribe to new messages. 100 | 101 |
105 | 106 | ## Objects 107 | 108 | ### Message 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 |
FieldArgumentTypeDescription
idID!
contentString
authorString
137 | 138 | ## Inputs 139 | 140 | ### MessageInput 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 |
FieldTypeDescription
contentString
authorString
163 | 164 | ## Scalars 165 | 166 | ### Boolean 167 | 168 | The `Boolean` scalar type represents `true` or `false`. 169 | 170 | ### ID 171 | 172 | The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. 173 | 174 | ### String 175 | 176 | The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. 177 | 178 | -------------------------------------------------------------------------------- /test/fixtures/no-toc.md: -------------------------------------------------------------------------------- 1 | # Schema Types 2 | 3 | 4 | ## Query 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
FieldArgumentTypeDescription
getMessageMessage
idID!
27 | 28 | ## Mutation 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 |
FieldArgumentTypeDescription
createMessageMessage
inputMessageInput
updateMessageMessage
idID!
inputMessageInput
66 | 67 | ## Subscription 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 86 | 87 | 88 |
FieldArgumentTypeDescription
messageSentMessage 82 | 83 | Subscribe to new messages. 84 | 85 |
89 | 90 | ## Objects 91 | 92 | ### Message 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 |
FieldArgumentTypeDescription
idID!
contentString
authorString
121 | 122 | ## Inputs 123 | 124 | ### MessageInput 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 |
FieldTypeDescription
contentString
authorString
147 | 148 | ## Scalars 149 | 150 | ### Boolean 151 | 152 | The `Boolean` scalar type represents `true` or `false`. 153 | 154 | ### ID 155 | 156 | The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. 157 | 158 | ### String 159 | 160 | The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. 161 | 162 | -------------------------------------------------------------------------------- /test/fixtures/toc-fields.md: -------------------------------------------------------------------------------- 1 | # Schema Types 2 | 3 |
4 | Table of Contents 5 | 6 | * [Query](#query) 7 | * [getMessage](#query.getmessage) 8 | * [Mutation](#mutation) 9 | * [createMessage](#mutation.createmessage) 10 | * [updateMessage](#mutation.updatemessage) 11 | * [Subscription](#subscription) 12 | * [Objects](#objects) 13 | * [Message](#message) 14 | * [Inputs](#inputs) 15 | * [MessageInput](#messageinput) 16 | * [content](#messageinput.content) 17 | * [author](#messageinput.author) 18 | * [Scalars](#scalars) 19 | * [Boolean](#boolean) 20 | * [ID](#id) 21 | * [String](#string) 22 | 23 |
24 | 25 | ## Query 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
FieldArgumentTypeDescription
getMessageMessage
idID!
48 | 49 | ## Mutation 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
FieldArgumentTypeDescription
createMessageMessage
inputMessageInput
updateMessageMessage
idID!
inputMessageInput
87 | 88 | ## Subscription 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 107 | 108 | 109 |
FieldArgumentTypeDescription
messageSentMessage 103 | 104 | Subscribe to new messages. 105 | 106 |
110 | 111 | ## Objects 112 | 113 | ### Message 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 |
FieldArgumentTypeDescription
idID!
contentString
authorString
142 | 143 | ## Inputs 144 | 145 | ### MessageInput 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 |
FieldTypeDescription
contentString
authorString
168 | 169 | ## Scalars 170 | 171 | ### Boolean 172 | 173 | The `Boolean` scalar type represents `true` or `false`. 174 | 175 | ### ID 176 | 177 | The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. 178 | 179 | ### String 180 | 181 | The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. 182 | 183 | -------------------------------------------------------------------------------- /test/fixtures/union-test-2.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | mammals: [Mammal] 3 | } 4 | 5 | """ 6 | *italic* 7 | 8 | * list item 1 9 | * list item 2 10 | * list item 3 11 | """ 12 | type Dog { 13 | legs: Int 14 | } 15 | 16 | """ 17 | abcde 18 | """ 19 | type Seal { 20 | fins: Int 21 | } 22 | 23 | union Mammal = Dog | Seal 24 | -------------------------------------------------------------------------------- /test/fixtures/union-test-2.md: -------------------------------------------------------------------------------- 1 | # Schema Types 2 | 3 |
4 | Table of Contents 5 | 6 | * [Query](#query) 7 | * [Objects](#objects) 8 | * [Dog](#dog) 9 | * [Seal](#seal) 10 | * [Scalars](#scalars) 11 | * [Boolean](#boolean) 12 | * [Int](#int) 13 | * [String](#string) 14 | * [Unions](#unions) 15 | * [Mammal](#mammal) 16 | 17 |
18 | 19 | ## Query 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
FieldArgumentTypeDescription
mammals[Mammal]
37 | 38 | ## Objects 39 | 40 | ### Dog 41 | 42 | *italic* 43 | 44 | * list item 1 45 | * list item 2 46 | * list item 3 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |
FieldArgumentTypeDescription
legsInt
65 | 66 | ### Seal 67 | 68 | abcde 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
FieldArgumentTypeDescription
finsInt
87 | 88 | ## Scalars 89 | 90 | ### Boolean 91 | 92 | The `Boolean` scalar type represents `true` or `false`. 93 | 94 | ### Int 95 | 96 | The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. 97 | 98 | ### String 99 | 100 | The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. 101 | 102 | 103 | ## Unions 104 | 105 | ### Mammal 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 126 | 127 | 128 | 129 | 134 | 135 | 136 |
TypeDescription
Dog 118 | 119 | *italic* 120 | 121 | * list item 1 122 | * list item 2 123 | * list item 3 124 | 125 |
Seal 130 | 131 | abcde 132 | 133 |
137 | -------------------------------------------------------------------------------- /test/fixtures/union-test.graphql: -------------------------------------------------------------------------------- 1 | "A human being" 2 | type Person { 3 | id: ID! 4 | firstName: String! 5 | lastName: String! 6 | email: String 7 | age: Int 8 | dob: String 9 | } 10 | 11 | """ 12 | A group of **persons** working together for a purpose 13 | 14 | This is a more elaborate description 15 | 16 | * with some 17 | * items 18 | * to see 19 | * if this markdown is properly 20 | * translated 21 | 22 | """ 23 | type Organization { 24 | "Node ID" 25 | id: ID! 26 | "Name of the organization" 27 | name: String! 28 | "Main contact email address" 29 | email: String 30 | "Date the organization was founded" 31 | founded: String 32 | "The CEO" 33 | ceo: Person 34 | } 35 | 36 | "Either a `Person` or an `Organization`" 37 | union Party = Person | Organization 38 | 39 | type Query { 40 | party(id: ID!): Party 41 | } 42 | 43 | extend type Query { 44 | "A field that was added with extend" 45 | extendo: String 46 | } 47 | -------------------------------------------------------------------------------- /test/fixtures/union-test.md: -------------------------------------------------------------------------------- 1 | # Schema Types 2 | 3 |
4 | Table of Contents 5 | 6 | * [Query](#query) 7 | * [Objects](#objects) 8 | * [Organization](#organization) 9 | * [Person](#person) 10 | * [Scalars](#scalars) 11 | * [Boolean](#boolean) 12 | * [ID](#id) 13 | * [Int](#int) 14 | * [String](#string) 15 | * [Unions](#unions) 16 | * [Party](#party) 17 | 18 |
19 | 20 | ## Query 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
FieldArgumentTypeDescription
partyParty
idID!
extendoString 45 | 46 | A field that was added with extend 47 | 48 |
52 | 53 | ## Objects 54 | 55 | ### Organization 56 | 57 | A group of **persons** working together for a purpose 58 | 59 | This is a more elaborate description 60 | 61 | * with some 62 | * items 63 | * to see 64 | * if this markdown is properly 65 | * translated 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 85 | 86 | 87 | 88 | 89 | 94 | 95 | 96 | 97 | 98 | 103 | 104 | 105 | 106 | 107 | 112 | 113 | 114 | 115 | 116 | 121 | 122 | 123 |
FieldArgumentTypeDescription
idID! 81 | 82 | Node ID 83 | 84 |
nameString! 90 | 91 | Name of the organization 92 | 93 |
emailString 99 | 100 | Main contact email address 101 | 102 |
foundedString 108 | 109 | Date the organization was founded 110 | 111 |
ceoPerson 117 | 118 | The CEO 119 | 120 |
124 | 125 | ### Person 126 | 127 | A human being 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 |
FieldArgumentTypeDescription
idID!
firstNameString!
lastNameString!
emailString
ageInt
dobString
171 | 172 | ## Scalars 173 | 174 | ### Boolean 175 | 176 | The `Boolean` scalar type represents `true` or `false`. 177 | 178 | ### ID 179 | 180 | The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. 181 | 182 | ### Int 183 | 184 | The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. 185 | 186 | ### String 187 | 188 | The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. 189 | 190 | 191 | ## Unions 192 | 193 | ### Party 194 | 195 | Either a `Person` or an `Organization` 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 212 | 213 | 214 | 215 | 228 | 229 | 230 |
TypeDescription
Person 208 | 209 | A human being 210 | 211 |
Organization 216 | 217 | A group of **persons** working together for a purpose 218 | 219 | This is a more elaborate description 220 | 221 | * with some 222 | * items 223 | * to see 224 | * if this markdown is properly 225 | * translated 226 | 227 |
231 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const tempy = require('tempy') 4 | const resolveFrom = require('resolve-from') 5 | const { 6 | run, 7 | loadSchemaJSON, 8 | renderSchema, 9 | updateSchema, 10 | } = require('../src/index') 11 | 12 | jest.mock('node-fetch') 13 | const fetch = require('node-fetch') 14 | 15 | function createPrinter() { 16 | const printer = (chunk) => { 17 | printer.output += `${chunk}\n` 18 | } 19 | printer.output = '' 20 | return printer 21 | } 22 | 23 | function createMockConsole() { 24 | return { 25 | log: createPrinter(), 26 | error: createPrinter(), 27 | } 28 | } 29 | 30 | function readFile(filename) { 31 | filename = path.resolve(__dirname, filename) 32 | return new Promise((resolve, reject) => { 33 | fs.readFile(filename, 'utf8', (err, data) => { 34 | err ? reject(err) : resolve(data) 35 | }) 36 | }) 37 | } 38 | 39 | describe('renderSchema()', () => { 40 | it('renders the GraphBrainz schema', async () => { 41 | const schema = await loadSchemaJSON('graphbrainz/schema.json') 42 | const printer = createPrinter() 43 | renderSchema(schema, { printer }) 44 | const expected = await readFile('./fixtures/graphbrainz.md') 45 | expect(printer.output).toBe(expected) 46 | }) 47 | 48 | it('supports Input Objects', async () => { 49 | const schema = await loadSchemaJSON( 50 | path.resolve(__dirname, './fixtures/input-objects.graphql') 51 | ) 52 | const printer = createPrinter() 53 | renderSchema(schema, { printer }) 54 | const expected = await readFile('./fixtures/input-objects.md') 55 | expect(printer.output).toBe(expected) 56 | }) 57 | 58 | it('supports no rendering of table of contents', async () => { 59 | const schema = await loadSchemaJSON( 60 | path.resolve(__dirname, './fixtures/input-objects.graphql') 61 | ) 62 | const printer = createPrinter() 63 | renderSchema(schema, { printer, skipTableOfContents: true }) 64 | const expected = await readFile('./fixtures/no-toc.md') 65 | expect(printer.output).toBe(expected) 66 | }) 67 | 68 | it('supports unions', async () => { 69 | const schema = await loadSchemaJSON( 70 | path.resolve(__dirname, './fixtures/union-test.graphql') 71 | ) 72 | const printer = createPrinter() 73 | renderSchema(schema, { printer }) 74 | const expected = await readFile('./fixtures/union-test.md') 75 | expect(printer.output).toBe(expected) 76 | }) 77 | 78 | it('renders markdown properly in unions', async () => { 79 | const schema = await loadSchemaJSON( 80 | path.resolve(__dirname, './fixtures/union-test-2.graphql') 81 | ) 82 | const printer = createPrinter() 83 | renderSchema(schema, { printer }) 84 | const expected = await readFile('./fixtures/union-test-2.md') 85 | expect(printer.output).toBe(expected) 86 | }) 87 | 88 | it('can link individual fields in the table of contents', async () => { 89 | const schema = await loadSchemaJSON( 90 | path.resolve(__dirname, './fixtures/input-objects.graphql') 91 | ) 92 | const printer = createPrinter() 93 | renderSchema(schema, { 94 | printer, 95 | tocFieldTypes: ['Query', 'Mutation', 'MessageInput'], 96 | }) 97 | const expected = await readFile('./fixtures/toc-fields.md') 98 | expect(printer.output).toBe(expected) 99 | }) 100 | }) 101 | 102 | describe('diffSchema()', () => { 103 | const schemaDiff = require('./fixtures/cover-art-archive') 104 | 105 | it('outputs a JSON schema containing only additions', async () => { 106 | expect(await schemaDiff).toMatchSnapshot() 107 | }) 108 | 109 | it('can be rendered', async () => { 110 | const printer = createPrinter() 111 | renderSchema(await schemaDiff, { printer }) 112 | const expected = await readFile('./fixtures/cover-art-archive.md') 113 | expect(printer.output).toBe(expected) 114 | }) 115 | }) 116 | 117 | describe('loadSchemaJSON()', () => { 118 | it('can load exported GraphQLSchema objects', async () => { 119 | const moduleSchema = await loadSchemaJSON('graphbrainz/lib/schema') 120 | expect(moduleSchema.__schema.queryType.name).toBe('Query') 121 | }) 122 | 123 | it('can load JSON schema files', async () => { 124 | const jsonFileSchema = await loadSchemaJSON('graphbrainz/schema.json') 125 | expect(jsonFileSchema.__schema.queryType.name).toBe('Query') 126 | }) 127 | 128 | it('can load GraphQL schema language files', async () => { 129 | const graphqlFileSchema = await loadSchemaJSON( 130 | path.resolve(__dirname, './fixtures/graphbrainz.graphql') 131 | ) 132 | expect(graphqlFileSchema.__schema.queryType.name).toBe('Query') 133 | }) 134 | 135 | it('can call fetch with correct parameters', async () => { 136 | fetch.mockImplementation(() => 137 | Promise.resolve({ 138 | json: () => resolveFrom('.', 'graphbrainz/schema.json'), 139 | }) 140 | ) 141 | 142 | await loadSchemaJSON('http://example.com', { 143 | headers: { key1: 'value1' }, 144 | }) 145 | expect(fetch.mock.calls[0][0]).toBe('http://example.com') 146 | expect(fetch.mock.calls[0][1].headers).toEqual({ 147 | Accept: 'application/json', 148 | 'Content-Type': 'application/json', 149 | key1: 'value1', 150 | }) 151 | }) 152 | }) 153 | 154 | describe('updateSchema()', () => { 155 | const filename = tempy.file() 156 | 157 | it('adds schema and comment markers to file if it does not exist', async () => { 158 | const initialSchema = await loadSchemaJSON('graphbrainz/schema.json') 159 | 160 | await updateSchema(filename, initialSchema) 161 | const actual = await readFile(filename) 162 | const expected = await readFile( 163 | './fixtures/graphbrainz-updateSchema-initial.md' 164 | ) 165 | expect(actual).toBe(expected) 166 | }) 167 | 168 | it('updates schema between comment markers in an existing file', async () => { 169 | const updatedSchema = await require('./fixtures/graphbrainz-updateSchema') 170 | await updateSchema(filename, updatedSchema) 171 | const actual = await readFile(filename) 172 | const expected = await readFile( 173 | './fixtures/graphbrainz-updateSchema-updated.md' 174 | ) 175 | expect(actual).toBe(expected) 176 | }) 177 | }) 178 | 179 | describe('run()', () => { 180 | describe('with no args', () => { 181 | it('prints the help message', () => { 182 | const console = createMockConsole() 183 | run([], { console, exit: false }) 184 | expect({ 185 | stdout: console.log.output, 186 | stderr: console.error.output, 187 | }).toMatchSnapshot() 188 | }) 189 | }) 190 | 191 | describe('with --help arg', () => { 192 | it('prints the help message', () => { 193 | const console = createMockConsole() 194 | run(['--help'], { console, exit: false }) 195 | expect({ 196 | stdout: console.log.output, 197 | stderr: console.error.output, 198 | }).toMatchSnapshot() 199 | }) 200 | }) 201 | }) 202 | --------------------------------------------------------------------------------