graphbrainz/src/types/scalars.js
Brian Beck 01b305dd50 Support browsing by Disc ID, ISRC, ISWC (#10)
* Browse queries for releases, recordings, and works now support
  browsing by Disc ID, ISRC, and ISWC, respectively
* Add `DiscID`, `ISRC`, and `ISWC` scalars
* Add missing `isrcs` field to `Recording`

Fixes #7.
2016-12-11 13:09:28 -08:00

176 lines
5.2 KiB
JavaScript

import { Kind } from 'graphql/language'
import { GraphQLScalarType } from 'graphql/type'
function createScalar (config) {
return new GraphQLScalarType({
serialize: value => value,
parseValue: value => value,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return ast.value
}
return null
},
...config
})
}
const uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
const locale = /^([a-z]{2})(_[A-Z]{2})?(\.[A-Z0-9-]+)?$/
// Be extremely lenient; just prevent major input errors.
const url = /^\w+:\/\/[\w-]+\.\w+/
function validateMBID (value) {
if (typeof value === 'string' && uuid.test(value)) {
return value
}
throw new TypeError(`Malformed MBID: ${value}`)
}
function validatePositive (value) {
if (value >= 0) {
return value
}
throw new TypeError(`Expected positive value: ${value}`)
}
function validateLocale (value) {
if (typeof value === 'string' && locale.test(value)) {
return value
}
throw new TypeError(`Malformed locale: ${value}`)
}
function validateURL (value) {
if (typeof value === 'string' && url.test(value)) {
return value
}
throw new TypeError(`Malformed URL: ${value}`)
}
export const ASIN = createScalar({
name: 'ASIN',
description: `An [Amazon Standard Identification Number](https://musicbrainz.org/doc/ASIN)
(ASIN) is a 10-character alphanumeric unique identifier assigned by Amazon.com
and its partners for product identification within the Amazon organization.`
})
export const DateType = createScalar({
name: 'Date',
description: 'Year, month (optional), and day (optional) in YYYY-MM-DD format.'
})
export const Degrees = createScalar({
name: 'Degrees',
description: 'Decimal degrees, used for latitude and longitude.'
})
export const DiscID = createScalar({
name: 'DiscID',
description: `[Disc ID](https://musicbrainz.org/doc/Disc_ID) is the code
number which MusicBrainz uses to link a physical CD to a [release](https://musicbrainz.org/doc/Release)
listing.
A release may have any number of disc IDs, and a disc ID may be linked to
multiple releases. This is because disc ID calculation involves a hash of the
frame offsets of the CD tracks.
Different pressing of a CD often have slightly different frame offsets, and
hence different disc IDs.
Conversely, two different CDs may happen to have exactly the same set of frame
offsets and hence the same disc ID.`
})
export const Duration = createScalar({
name: 'Duration',
description: 'A length of time, in milliseconds.',
serialize: validatePositive,
parseValue: validatePositive,
parseLiteral (ast) {
if (ast.kind === Kind.INT) {
return validatePositive(parseInt(ast.value, 10))
}
return null
}
})
export const IPI = createScalar({
name: 'IPI',
description: `An [Interested Parties Information](https://musicbrainz.org/doc/IPI)
(IPI) code is an identifying number assigned by the CISAC database for musical
rights management.`
})
export const ISNI = createScalar({
name: 'ISNI',
description: `The [International Standard Name Identifier](https://musicbrainz.org/doc/ISNI)
(ISNI) is an ISO standard for uniquely identifying the public identities of
contributors to media content.`
})
export const ISRC = createScalar({
name: 'ISRC',
description: `The [International Standard Recording Code](https://musicbrainz.org/doc/ISRC)
(ISRC) is an identification system for audio and music video recordings. It is
standarized by the [IFPI](http://www.ifpi.org/) in ISO 3901:2001 and used by
IFPI members to assign a unique identifier to every distinct sound recording
they release. An ISRC identifies a particular [sound recording](https://musicbrainz.org/doc/Recording),
not the song itself. Therefore, different recordings, edits, remixes and
remasters of the same song will each be assigned their own ISRC. However, note
that same recording should carry the same ISRC in all countries/territories.
Songs are identified by analogous [International Standard Musical Work Codes](https://musicbrainz.org/doc/ISWC)
(ISWCs).`
})
export const ISWC = createScalar({
name: 'ISWC',
description: `The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC)
(ISWC) is an ISO standard similar to ISBNs for identifying musical works /
compositions.`
})
export const Locale = createScalar({
name: 'Locale',
description: 'Language code, optionally with country and encoding.',
serialize: validateLocale,
parseValue: validateLocale,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return validateLocale(ast.value)
}
return null
}
})
export const MBID = createScalar({
name: 'MBID',
description: `The MBID scalar represents MusicBrainz identifiers, which are
36-character UUIDs.`,
serialize: validateMBID,
parseValue: validateMBID,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return validateMBID(ast.value)
}
return null
}
})
export const Time = createScalar({
name: 'Time',
description: 'A time of day, in 24-hour hh:mm notation.'
})
export const URLString = createScalar({
name: 'URLString',
description: 'A web address.',
serialize: validateURL,
parseValue: validateURL,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return validateURL(ast.value)
}
return null
}
})