Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/exogen/graphbrainz
A fully-featured GraphQL interface for the MusicBrainz API.
https://github.com/exogen/graphbrainz
api express graphql graphql-schema middleware musicbrainz musicbrainz-api relay
Last synced: 1 day ago
JSON representation
A fully-featured GraphQL interface for the MusicBrainz API.
- Host: GitHub
- URL: https://github.com/exogen/graphbrainz
- Owner: exogen
- License: mit
- Created: 2016-08-07T19:51:35.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2024-09-19T17:32:49.000Z (4 months ago)
- Last Synced: 2025-01-13T01:30:42.684Z (8 days ago)
- Topics: api, express, graphql, graphql-schema, middleware, musicbrainz, musicbrainz-api, relay
- Language: JavaScript
- Homepage:
- Size: 4.08 MB
- Stars: 164
- Watchers: 7
- Forks: 31
- Open Issues: 24
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# GraphBrainz
[![coverage](https://img.shields.io/codecov/c/github/exogen/graphbrainz.svg)](https://codecov.io/gh/exogen/graphbrainz)
[![npm version](https://img.shields.io/npm/v/graphbrainz.svg)](https://www.npmjs.com/package/graphbrainz)
[![license](https://img.shields.io/npm/l/graphbrainz.svg)](https://github.com/exogen/graphbrainz/blob/master/LICENSE)A [GraphQL][] schema, [Express][] server, and middleware for querying the
[MusicBrainz][] API. It features an [extensible](./docs/extensions) schema to
add integration with Discogs, Spotify, Last.fm, fanart.tv, and more!**[Try out the live demo!][demo]** :bulb: Use the “Docs” sidebar, the
[schema][], or the [types][] docs to help construct your query.## Support
Did this project bring you joy? Want to support updates? Check out
[my GitHub Sponsors page](https://github.com/sponsors/exogen).Alternatively…
## Install
Install with npm:
```sh
npm install graphbrainz --save
```Install with Yarn:
```sh
yarn add graphbrainz
```_GraphBrainz is written and distributed as native ECMAScript modules
(ESM) and requires a compatible version of Node.js_## Contents
- [Usage](#usage)
- [As a standalone server](#as-a-standalone-server)
- [As middleware](#as-middleware)
- [As a client](#as-a-client)
- [Environment Variables](#environment-variables)
- [Debugging](#debugging)
- [Example Queries](#example-queries)
- [Pagination](#pagination)
- [Questions](#questions)
- [Schema](#schema)
- [Extending the schema](#extending-the-schema)## Usage
This package can be used both as a standalone GraphQL server and as Express
middleware supplying a GraphQL endpoint.### As a standalone server
Run the included `graphbrainz` executable to start the server. The server is
configured using [environment variables](#environment-variables).```sh
$ graphbrainz
Listening on port 3000.
```Development mode features like JSON pretty printing and the [GraphiQL][]
interface will be enabled unless the server is run with `NODE_ENV=production`.Note that if you are not running the standalone server within another Node
project, you may wish to install this package globally so that the `graphbrainz`
script is globally available:```sh
npm install -g graphbrainz
```### As middleware
If you have an existing Express server and want to add this GraphQL service as
an endpoint, or you just want more customization, use the middleware.```js
import express from 'express';
import { middleware as graphbrainz } from 'graphbrainz';const app = express();
// Use the default options:
app.use('/graphbrainz', graphbrainz());// or, pass some options:
app.use('/graphbrainz', graphbrainz({
client: new MusicBrainz({ ... }),
graphiql: true,
...
}));app.listen(3000);
```The `graphbrainz` middleware function accepts the following options:
- **`client`**: A custom API client instance to use. See the
[client submodule](src/api/client.js) for help with creating a custom
instance. You probably only need to do this if you want to adjust the rate
limit and retry behavior.
- Any remaining options are passed along to the standard GraphQL middleware. See
the [express-graphql][] documentation for more information.### As a client
If you just want to make queries from your app without running a separate server
or exposing a GraphQL endpoint, use the GraphBrainz schema with a library like
[GraphQL.js][graphql-js]. You just need to create the `context` object that the
GraphBrainz resolvers expect, like so:```js
import { graphql } from 'graphql';
import { MusicBrainz, createContext, baseSchema } from 'graphbrainz';const client = new MusicBrainz();
const context = createContext({ client });graphql(
schema,
`
{
lookup {
releaseGroup(mbid: "99599db8-0e36-4a93-b0e8-350e9d7502a9") {
title
}
}
}
`,
null,
context
)
.then((result) => {
const { releaseGroup } = result.data.lookup;
console.log(`The album title is “${releaseGroup.title}”.`);
})
.catch((err) => {
console.error(err);
});
```### Environment Variables
- **`MUSICBRAINZ_BASE_URL`**: The base MusicBrainz API URL to use. Change this
if you are running your own MusicBrainz mirror. Defaults to
`http://musicbrainz.org/ws/2/`.
- **`GRAPHBRAINZ_PATH`**: The URL route at which to expose the GraphQL endpoint,
if running the standalone server. Defaults to `/`.
- **`GRAPHBRAINZ_CORS_ORIGIN`**: The value of the `origin` option to pass to the
[CORS][cors] middleware. Valid values are `true` to reflect the request
origin, a specific origin string to allow, `*` to allow all origins, and
`false` to disable CORS (the default).
- **`GRAPHBRAINZ_CACHE_SIZE`**: The maximum number of REST API responses to
cache. Increasing the cache size and TTL will greatly lower query execution
time for complex queries involving frequently accessed entities. Defaults to
`8192`.
- **`GRAPHBRAINZ_CACHE_TTL`**: The maximum age of REST API responses in the
cache, in milliseconds. Responses older than this will be disposed of (and
re-requested) the next time they are accessed. Defaults to `86400000` (one
day).
- **`GRAPHBRAINZ_GRAPHIQL`**: Set this to `true` if you want to force the
[GraphiQL][] interface to be available even in production mode.
- **`GRAPHBRAINZ_EXTENSIONS`**: A JSON array of module paths to load as
[extensions](./docs/extensions).
- **`PORT`**: Port number to use, if running the standalone server.When running the standalone server, [dotenv][] is used to load these variables
from a `.env` file, if one exists in the current working directory. This just
makes it more convenient to launch the server with certain settings. See the
[dotenv][] package for more information.### Debugging
The `DEBUG` environment variable can be used to enable logging for all (or just
some) of this package’s submodules:```sh
$ DEBUG=graphbrainz:* graphbrainz
```See the [debug][] package for more information.
## Example Queries
Nirvana albums and each album’s singles
([try it]()):```graphql
query NirvanaAlbumSingles {
lookup {
artist(mbid: "5b11f4ce-a62d-471e-81fc-a69a8278c7da") {
name
releaseGroups(type: ALBUM) {
edges {
node {
title
firstReleaseDate
relationships {
releaseGroups(type: "single from") {
edges {
node {
target {
... on ReleaseGroup {
title
firstReleaseDate
}
}
}
}
}
}
}
}
}
}
}
}
```### Pagination
The first five labels with “Apple” in the name
([try it]()):```graphql
query AppleLabels {
search {
labels(query: "Apple", first: 5) {
...labelResults
}
}
}fragment labelResults on LabelConnection {
pageInfo {
endCursor
}
edges {
cursor
node {
mbid
name
type
area {
name
}
}
}
}
```…and the next five, using the `endCursor` from the previous result
([try it]()):```graphql
query AppleLabels {
search {
labels(query: "Apple", first: 5, after: "YXJyYXljb25uZWN0aW9uOjQ=") {
...labelResults
}
}
}
```Who the members of the band on an Apple Records release married, and when
([try it]()):```graphql
query AppleRecordsMarriages {
search {
labels(query: "Apple Records", first: 1) {
edges {
node {
name
disambiguation
country
releases(first: 1) {
edges {
node {
title
date
artists {
edges {
node {
name
...bandMembers
}
}
}
}
}
}
}
}
}
}
}fragment bandMembers on Artist {
relationships {
artists(direction: "backward", type: "member of band") {
edges {
node {
type
target {
... on Artist {
name
...marriages
}
}
}
}
}
}
}fragment marriages on Artist {
relationships {
artists(type: "married") {
edges {
node {
type
direction
begin
end
target {
... on Artist {
name
}
}
}
}
}
}
}
```Images of Tom Petty provided by various extensions
([try it]()):```graphql
query TomPettyImages {
lookup {
artist(mbid: "5ca3f318-d028-4151-ac73-78e2b2d6cdcc") {
name
mediaWikiImages {
url
objectName
descriptionHTML
licenseShortName
}
fanArt {
thumbnails {
url
likeCount
}
}
theAudioDB {
logo
biography
}
}
}
}
```You can find more example queries in the [schema tests][].
## Questions
**What’s with the cumbersome `edges`/`node` nesting? Why `first`/`after` instead
of `limit`/`offset`? Why `mbid` instead of `id`?**You can thank [Relay][] for that; these are properties of a Relay-compliant
schema. The schema was originally designed to be more user-friendly, but in the
end I decided that being compatible with Relay was a worthwhile feature. I
agree, it’s ugly.The GraphBrainz schema includes an extra `nodes` field on every connection type.
If you only want the nodes and no other fields on `edges`, you can use `nodes`
as a shortcut.Don’t forget that you can also use [GraphQL aliases][aliases] to rename fields
to your liking. For example, the following query renames `edges`, `node`, and
`mbid` to `results`, `releaseGroup`, and `id`, respectively:```graphql
query ChristmasAlbums {
search {
releaseGroups(query: "Christmas") {
results: edges {
releaseGroup: node {
id: mbid
title
}
}
}
}
}
```**Why does my query take so long?**
It’s likely that your query requires multiple round trips to the MusicBrainz
REST API, which is subject to [rate limiting][]. While the query resolver tries
very hard to fetch only the data necessary, and with the smallest number of API
requests, it is not 100% optimal (yet). Make sure you are only requesting the
fields you need and a reasonable level of nested entities – unless you are
willing to wait.You can also set up a [local MusicBrainz mirror][mirror] and configure
GraphBrainz to use that with no rate limiting.## Schema
The [types][] document is the easiest to browse representation of the schema, or
you can read the [schema in GraphQL syntax][schema].### Extending the schema
The GraphBrainz schema can easily be extended to add integrations with
third-party services. See the [Extensions](./docs/extensions) docs for more
info.[demo]: https://graphbrainz.fly.dev/
[express]: http://expressjs.com/
[musicbrainz]: https://musicbrainz.org/
[graphql]: http://graphql.org/
[express-graphql]: https://www.npmjs.com/package/express-graphql
[dotenv]: https://www.npmjs.com/package/dotenv
[debug]: https://www.npmjs.com/package/debug
[graphiql]: https://github.com/graphql/graphiql
[graphql-js]: https://github.com/graphql/graphql-js
[relay]: https://facebook.github.io/relay/
[schema]: docs/schema.md
[types]: docs/types.md
[rate limiting]: https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting
[mirror]: https://musicbrainz.org/doc/MusicBrainz_Server/Setup
[aliases]: http://graphql.org/learn/queries/#aliases
[schema tests]: test/_schema.js
[cors]: https://github.com/expressjs/cors