{"_id":"@acal11/musicbrainz-api","name":"@acal11/musicbrainz-api","dist-tags":{"latest":"0.15.0"},"versions":{"0.15.0":{"name":"@acal11/musicbrainz-api","version":"0.15.0","description":"MusicBrainz API client for reading and submitting metadata","exports":"./lib/index.js","types":"lib/index.d.ts","type":"module","author":{"name":"Borewit","url":"https://github.com/Borewit"},"keywords":["MusicBrainz","metadata","meta","tag","tags","Picard","json","xml","web","service","submit","metabrainz","Cover Art Archive","coverartarchive","coverartarchive.org","album art","covers","download covers"],"license":"MIT","private":false,"engines":{"node":"^14.13.1 || >=16.0.0"},"repository":{"type":"git","url":"git+https://github.com/Borewit/musicbrainz-api.git"},"bugs":{"url":"https://github.com/Borewit/musicbrainz-api/issues"},"dependencies":{"@types/caseless":"^0.12.1","@types/request-promise-native":"^1.0.17","@types/uuid":"^9.0.0","caseless":"^0.12.0","debug":"^4.3.4","got":"^13.0.0","http-status-codes":"^2.1.4","json-stringify-safe":"^5.0.1","jsontoxml":"^1.0.1","rate-limit-threshold":"^0.1.5","source-map-support":"^0.5.16","tough-cookie":"^4.1.3","uuid":"^9.0.0"},"devDependencies":{"@types/chai":"^4.3.0","@types/jsontoxml":"^1.0.5","@types/mocha":"^10.0.4","@types/node":"^20.8.10","@typescript-eslint/eslint-plugin":"^5.13.0","@typescript-eslint/parser":"^5.13.0","c8":"^8.0.1","chai":"^4.2.0","del-cli":"^5.0.0","eslint":"^8.10.0","eslint-config-prettier":"^9.0.0","eslint-import-resolver-typescript":"^3.3.0","eslint-plugin-import":"^2.25.4","eslint-plugin-jsdoc":"^46.8.2","eslint-plugin-node":"^11.1.0","eslint-plugin-unicorn":"^49.0.0","mocha":"^10.1.0","remark-cli":"^12.0.0","remark-preset-lint-recommended":"^6.1.2","ts-node":"^10.0.0","typescript":"^5.0.2"},"scripts":{"clean":"del-cli lib/**/*.js lib/**/*.js.map lib/**/*.d.ts test/**/*.js test/**/*.js.map","compile-lib":"tsc -p lib","compile-test":"tsc -p test","compile":"npm run compile-lib && npm run compile-test","eslint":"eslint lib/**/*.ts --ignore-pattern lib/**/*.d.ts test/**/*.ts","lint-md":"remark -u preset-lint-recommended .","lint":"npm run lint-md && npm run eslint","test":"mocha","build":"npm run clean && npm run compile","start":"npm-run-all compile lint cover-test","test-coverage":"c8 npm run test","send-codacy":"nyc report --reporter=text-lcov | codacy-coverage"},"nyc":{"exclude":["test/**/*.ts"],"extension":[".ts"],"sourceMap":true,"instrument":true,"reporter":["lcov","text"],"report-dir":"coverage"},"_id":"@acal11/musicbrainz-api@0.15.0","gitHead":"4bcf15e81585c46c7ee4d84e22111a74dd2e0822","homepage":"https://github.com/Borewit/musicbrainz-api#readme","_nodeVersion":"20.10.0","_npmVersion":"10.2.3","dist":{"integrity":"sha512-BIx4YGKJgpoOR/1F75ora2NyrNVJPdMLiFV9uO9Ktatc27bB1IunO2CPUATpOQYT2AQh5b6Kf+pt8QsomQndqA==","shasum":"43bbc9618d33f57b1e0e9bcb9481d6194a93993d","tarball":"https://registry.npmjs.org/@acal11/musicbrainz-api/-/musicbrainz-api-0.15.0.tgz","fileCount":20,"unpackedSize":64975,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDexJ+SWo+ELgf/okXAn+G1k6qiMTOOWqC414DgGF0TogIhAKJA+ikCrUy5kdTc+ZRu/aD+24E5zuZBHLac30aQBtHX"}]},"_npmUser":{"name":"andrecallus","email":"andrecallus@outlook.com"},"directories":{},"maintainers":[{"name":"andrecallus","email":"andrecallus@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/musicbrainz-api_0.15.0_1702970597643_0.5789021584199243"},"_hasShrinkwrap":false}},"time":{"created":"2023-12-19T07:23:17.571Z","0.15.0":"2023-12-19T07:23:17.828Z","modified":"2023-12-19T07:23:18.131Z"},"maintainers":[{"name":"andrecallus","email":"andrecallus@outlook.com"}],"description":"MusicBrainz API client for reading and submitting metadata","homepage":"https://github.com/Borewit/musicbrainz-api#readme","keywords":["MusicBrainz","metadata","meta","tag","tags","Picard","json","xml","web","service","submit","metabrainz","Cover Art Archive","coverartarchive","coverartarchive.org","album art","covers","download covers"],"repository":{"type":"git","url":"git+https://github.com/Borewit/musicbrainz-api.git"},"author":{"name":"Borewit","url":"https://github.com/Borewit"},"bugs":{"url":"https://github.com/Borewit/musicbrainz-api/issues"},"license":"MIT","readme":"[![Node.js CI](https://github.com/Borewit/musicbrainz-api/actions/workflows/nodejs-ci.yml/badge.svg)](https://github.com/Borewit/musicbrainz-api/actions/workflows/nodejs-ci.yml)\n[![NPM version](https://img.shields.io/npm/v/musicbrainz-api.svg)](https://npmjs.org/package/musicbrainz-api)\n[![npm downloads](http://img.shields.io/npm/dm/musicbrainz-api.svg)](https://npmcharts.com/compare/musicbrainz-api?interval=30&start=365)\n[![Coverage Status](https://coveralls.io/repos/github/Borewit/musicbrainz-api/badge.svg?branch=master)](https://coveralls.io/github/Borewit/musicbrainz-api?branch=master)\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/2bc47b2006454bae8c737991f152e518)](https://app.codacy.com/gh/Borewit/musicbrainz-api/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)\n[![CodeQL](https://github.com/Borewit/musicbrainz-api/actions/workflows/codeql.yml/badge.svg)](https://github.com/Borewit/musicbrainz-api/actions/workflows/codeql.yml)\n[![Known Vulnerabilities](https://snyk.io/test/github/Borewit/musicbrainz-api/badge.svg?targetFile=package.json)](https://snyk.io/test/github/Borewit/musicbrainz-api?targetFile=package.json)\n[![DeepScan grade](https://deepscan.io/api/teams/5165/projects/6991/branches/63373/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=5165&pid=6991&bid=63373)\n[![Discord](https://img.shields.io/discord/460524735235883049.svg)](https://discord.gg/958xT5X)\n\n# musicbrainz-api\n\nA MusicBrainz-API-client for reading and submitting metadata\n\n## Features\n*   Access metadata from MusicBrainz\n*   Submit metadata \n*   Smart and adjustable throttling, like MusicBrainz, it allows a bursts of requests\n*   Build in TypeScript definitions\n\n### Hint\n\nThis package is currently only developed for the use in a [node.js environment](http://nodejs.org/).\nWe are looking into making this package usable in the browser as well.\n\n## Before using this library\n\nMusicBrainz asks that you to [identify your application](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#User%20Data) by filling in the ['User-Agent' Header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent).\nBy passing `appName`, `appVersion`, `appMail` musicbrainz-api takes care of that.\n\n## Submitting metadata\n\nIf you plan to use this module for submitting metadata, please ensure you comply with [the MusicBrainz Code of conduct/Bots](https://wiki.musicbrainz.org/Code_of_Conduct/Bots).\n\n## Example\n\nExample, how to import 'musicbrainz-api:\n```js\nimport {MusicBrainzApi} from 'musicbrainz-api';\n\nconst mbApi = new MusicBrainzApi({\n  appName: 'my-app',\n  appVersion: '0.1.0',\n  appContactInfo: 'user@mail.org'\n});\n```\n\nThe following configuration settings can be passed \n```js\nimport {MusicBrainzApi} from 'musicbrainz-api';\n\nconst config = {\n  // MusicBrainz bot account username & password (optional)\n  botAccount: { \n    username: 'myUserName_bot',\n    password: 'myPassword' \n  },\n  \n  // API base URL, default: 'https://musicbrainz.org' (optional)\n  baseUrl: 'https://musicbrainz.org',\n\n  appName: 'my-app',\n  appVersion: '0.1.0',\n\n  // Optional, default: no proxy server\n  proxy: {\n    host: 'localhost',\n    port: 8888\n   },\n\n  // Your e-mail address, required for submitting ISRCs\n  appMail: string\n}\n\nconst mbApi = new MusicbrainzApi(config);\n```\n\n## Lookup MusicBrainz Entities\n\nMusicBrainz API documentation: [XML Web Service/Version 2 Lookups](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Lookups)\n\n### Generic lookup function\n\nArguments:\n*   entity: `'area'` | `'artist'` | `'collection'` | `'instrument'` | `'label'` | `'place'` | `'release'` | `'release-group'` | `'recording'` | `'series'` | `'work'` | `'url'` | `'event'`\n*   MBID [(MusicBrainz identifier)](https://wiki.musicbrainz.org/MusicBrainz_Identifier)\n*   query\n\n```js\nconst artist = await mbApi.lookup('artist', 'ab2528d9-719f-4261-8098-21849222a0f2');\n```\n\n\n| Query argument        | Query value     | \n|-----------------------|-----------------|  \n| `query.collection`    | Collection MBID |\n\n### Browse artist\n\n```js\nconst artists = await mbApi.browse('artist', query);\n````\n\n| Query argument        | Query value        | \n|-----------------------|--------------------|  \n| `query.area`          | Area MBID          |\n| `query.collection`    | Collection MBID    |\n| `query.recording`     | Recording MBID     |\n| `query.release`       | Release MBID       |\n| `query.release-group` | Release-group MBID |\n| `query.work`          | Work MBID          |\n\n### Browse collection\n```js\nconst collections = await mbApi.browse('collection', query);\n````\n\n| Query argument        | Query value        | \n|-----------------------|--------------------|  \n| `query.area`          | Area MBID          |\n| `query.artist`        | Artist MBID        |\n| `query.editor`        | Editor MBID        |\n| `query.event`         | Event MBID         |\n| `query.label`         | Label MBID         |\n| `query.place`         | Place MBID         |\n| `query.recording`     | Recording MBID     |\n| `query.release`       | Release MBID       |\n| `query.release-group` | Release-group MBID |\n| `query.work`          | Work MBID          |\n\n### Browse events\n```js\nconst events = await mbApi.browse('event', query);\n````\n\n| Query argument        | Query value     | \n|-----------------------|-----------------|  \n| `query.area`          | Area MBID       |\n| `query.artist`        | Artist MBID     |\n| `query.collection`    | Collection MBID |\n| `query.place`         | Place MBID      |\n\n### Browse instruments\n```js\nconst instruments = await mbApi.browse('event', query);\n````\n\n| Query argument        | Query value        | \n|-----------------------|--------------------|  \n| `query.collection`    | Collection MBID    |\n\n### Browse labels\n```js\nconst labels = await mbApi.browse('label', query);\n````\n\n| Query argument     | Query value     | \n|--------------------|-----------------|  \n| `query.area`       | Area MBID       |\n| `query.collection` | Collection MBID |\n| `query.release`    | Release MBID    |\n\n### Browse places\n```js\nconst places = await mbApi.browse('place', query);\n````\n\n| Query argument     | Query value     | \n|--------------------|-----------------|  \n| `query.area`       | Area MBID       |\n| `query.collection` | Collection MBID |\n\n### Browse recordings\n```js\nconst recordings = await mbApi.browse('recording', query);\n````\n\n| Query argument     | Query value     | \n|--------------------|-----------------|  \n| `query.artist`     | Area MBID       |\n| `query.collection` | Collection MBID |\n| `query.release`    | Release MBID    |\n| `query.work`       | Work MBID       |\n\n### Browse releases\n```js\nconst releases = await mbApi.browse('release', query);\n````\n\n| Query argument        | Query value        | \n|-----------------------|--------------------|  \n| `query.area`          | Area MBID          |\n| `query.artist`        | Artist MBID        |\n| `query.editor`        | Editor MBID        |\n| `query.event`         | Event MBID         |\n| `query.label`         | Label MBID         |\n| `query.place`         | Place MBID         |\n| `query.recording`     | Recording MBID     |\n| `query.release`       | Release MBID       |\n| `query.release-group` | Release-group MBID |\n| `query.work`          | Work MBID          |\n\n### Browse release-groups\n```js\nconst releaseGroups = await mbApi.browse('release-group',query);\n```\n\n| Query argument     | Query value     | \n|--------------------|-----------------|  \n| `query.artist`     | Artist MBID     |\n| `query.collection` | Collection MBID |\n| `query.release`    | Release MBID    |\n\n### Browse series\n```js\nconst series = await mbApi.browse('series');\n````\n\n| Query argument        | Query value        | \n|-----------------------|--------------------|  \n| `query.area`          | Area MBID          |\n| `query.artist`        | Artist MBID        |\n| `query.editor`        | Editor MBID        |\n| `query.event`         | Event MBID         |\n| `query.label`         | Label MBID         |\n| `query.place`         | Place MBID         |\n| `query.recording`     | Recording MBID     |\n| `query.release`       | Release MBID       |\n| `query.release-group` | Release-group MBID |\n| `query.work`          | Work MBID          |\n\n### Browse works\n```js\nconst works = await mbApi.browse('work');\n````\n\n| Query argument     | Query value     | \n|--------------------|-----------------|  \n| `query.artist`     | Artist MBID     |\n| `query.xollection` | Collection MBID |\n\n### Browse urls\n```js\nconst urls = await mbApi.browse('url');\n````\n\n| Query argument     | Query value     | \n|--------------------|-----------------|  \n| `query.artist`     | Artist MBID     |\n| `query.xollection` | Collection MBID |\n\n## Search (query)\n\nImplements [XML Web Service/Version 2/Search](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search).\n\nThere are different search fields depending on the entity.\n\n### Search function\n\nSearches can be performed using the generic search function: `query(entity: mb.EntityType, query: string | IFormData, offset?: number, limit?: number): Promise<entity>`\n\nArguments:\n*   Entity type, which can be one of:\n    *   `artist`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Artist)\n    *   `label`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Label)\n    *   `recording`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Recording)\n    *   `release`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Release)\n    *   `release-group`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Release_Group)\n    *   `work`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Work)\n    *   `area`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Area)\n    *   `url`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#URL)\n*   `query {query: string, offset: number, limit: number}`\n    *   `query.query`: supports the full Lucene Search syntax; you can find a detailed guide at [Lucene Search Syntax](https://lucene.apache.org/core/4_3_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description). For example, you can set conditions while searching for a name with the AND operator.\n    *   `query.offset`: optional, return search results starting at a given offset. Used for paging through more than one page of results.\n    *   `limit.query`: optional, an integer value defining how many entries should be returned. Only values between 1 and 100 (both inclusive) are allowed. If not given, this defaults to 25.\n\nFor example, to find any recordings of _'We Will Rock You'_ by Queen:\n```js\nconst query = 'query=\"We Will Rock You\" AND arid:0383dadf-2a4e-4d10-a46a-e9e041da8eb3';\nconst result = await mbApi.search('release-group', {query});\n```\n\n##### Example: search Île-de-France\n\n```js\n mbApi.search('area', 'Île-de-France');\n````\n\n##### Example: search release by barcode\n\nSearch a release with the barcode 602537479870:\n```js\n mbApi.search('release', {query: {barcode: 602537479870}});\n````\n\n##### Example: search by object\n\nSame as previous example, but automatically serialize parameters to search query\n```js\n mbApi.search('release', 'barcode: 602537479870');\n````\n\n##### Example: search artist by artist name\n\nSearch artist:\n```js\nconst result = await mbApi.search('artist', {query: 'Stromae'});\n```\n\n##### Example: search release-group by artist name\n\nSearch release-group:\n```js\nconst result = await mbApi.search('release-group', {query: 'Racine carrée'});\n```\n\n##### Example: search release-group by release-group and an artist\n\nSearch a combination of a release-group and an artist.\n```js\nconst result = await mbApi.search('release-group', {artist: 'Racine carrée', releasegroup: 'Stromae'});\n```\n\n# Submitting data via XML POST\n\n[Submitting data via XML POST](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Submitting_data) may be done using personal MusicBrainz credentials. \n\n## Submit ISRC code using XML POST\n\nUsing the [XML ISRC submission](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#ISRC_submission) API.\n\n```js\nconst mbid_Formidable = '16afa384-174e-435e-bfa3-5591accda31c';\nconst isrc_Formidable = 'BET671300161';\n\nconst xmlMetadata = new XmlMetadata();\nconst xmlRecording = xmlMetadata.pushRecording(mbid_Formidable);\nxmlRecording.isrcList.pushIsrc(isrc_Formidable);\nawait mbApi.post('recording', xmlMetadata);\n```    \n    \n# Submitting data via user form-data\n\nFor all of the following function you need to use a dedicated bot account. \n\n## Submitting ISRC via post user form-data\n\n<img width=\"150\" src=\"http://www.clker.com/cliparts/i/w/L/q/u/1/work-in-progress.svg\" alt=\"Work in progress\"/>\nUse with caution, and only on a test server, it may clear existing metadata as side effect.\n      \n```js\n\nconst mbid_Formidable = '16afa384-174e-435e-bfa3-5591accda31c';\nconst isrc_Formidable = 'BET671300161';\n\n    \nconst recording = await mbApi.lookup('recording', mbid_Formidable);\n\n// Authentication the http-session against MusicBrainz (as defined in config.baseUrl)\nconst succeed = await mbApi.login();\nassert.isTrue(succeed, 'Login successful');\n\n// To submit the ISRC, the `recording.id` and `recording.title` are required\nawait mbApi.addIsrc(recording, isrc_Formidable);\n```\n\n### Submit recording URL\n\n```js\nconst recording = await mbApi.lookup('recording', '16afa384-174e-435e-bfa3-5591accda31c');\n\nconst succeed = await mbApi.login();\nassert.isTrue(succeed, 'Login successful');\n\nawait mbApi.addUrlToRecording(recording, {\n  linkTypeId: LinkType.stream_for_free,\n  text: 'https://open.spotify.com/track/2AMysGXOe0zzZJMtH3Nizb'\n});\n```\n\nActually a Spotify-track-ID can be submitted easier: \n```js\nconst recording = await mbApi.lookup('recording', '16afa384-174e-435e-bfa3-5591accda31c');\n\nconst succeed = await mbApi.login();\nassert.isTrue(succeed, 'Login successful');\nawait mbApi.addSpotifyIdToRecording(recording, '2AMysGXOe0zzZJMtH3Nizb');\n```\n\n## Cover Art Archive API\n\nImplementation of the [Cover Art Archive API](https://musicbrainz.org/doc/Cover_Art_Archive/API).\n\n```js\nimport {CoverArtArchiveApi} from 'musicbrainz-api';\n\ncoverArtArchiveApiClient.getReleaseCovers(releaseMbid).then(releaseCoverInfo => {\n    console.log('Release cover info', releaseCoverInfo);\n});\n\ncoverArtArchiveApiClient.getReleaseCovers(releaseMbid, 'front').then(releaseCoverInfo => {\n    console.log('Get best front cover', releaseCoverInfo);\n});\n\ncoverArtArchiveApiClient.getReleaseCovers(releaseMbid, 'back').then(releaseCoverInfo => {\n    console.log('Get best back cover', releaseCoverInfo);\n});\n\n```\n\n## Compatibility\n\nThe JavaScript in runtime is compliant with [ECMAScript 2017 (ES8)](https://en.wikipedia.org/wiki/ECMAScript#8th_Edition_-_ECMAScript_2017).\nRequires [Node.js®](https://nodejs.org/) version 6 or higher.\n","readmeFilename":"README.md"}