musicbrainz-api 0.10.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,476 +1,481 @@
1
- [![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)
2
- [![NPM version](https://img.shields.io/npm/v/musicbrainz-api.svg)](https://npmjs.org/package/musicbrainz-api)
3
- [![npm downloads](http://img.shields.io/npm/dm/musicbrainz-api.svg)](https://npmcharts.com/compare/musicbrainz-api)
4
- [![Coverage Status](https://coveralls.io/repos/github/Borewit/musicbrainz-api/badge.svg?branch=master)](https://coveralls.io/github/Borewit/musicbrainz-api?branch=master)
5
- [![Codacy Badge](https://app.codacy.com/project/badge/Grade/2bc47b2006454bae8c737991f152e518)](https://www.codacy.com/gh/Borewit/musicbrainz-api/dashboard?utm_source=github.com&utm_medium=referral&utm_content=Borewit/musicbrainz-api&utm_campaign=Badge_Grade)
6
- [![CodeQL](https://github.com/Borewit/musicbrainz-api/actions/workflows/codeql.yml/badge.svg)](https://github.com/Borewit/musicbrainz-api/actions/workflows/codeql.yml)
7
- [![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)
8
- [![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)
9
- [![Discord](https://img.shields.io/discord/460524735235883049.svg)](https://discord.gg/958xT5X)
10
-
11
- # musicbrainz-api
12
-
13
- A MusicBrainz-API-client for reading and submitting metadata
14
-
15
- ## Features
16
- * Access metadata from MusicBrainz
17
- * Submit metadata
18
- * Smart and adjustable throttling, like MusicBrainz, it allows a bursts of requests
19
- * Build in TypeScript definitions
20
-
21
- ## Before using this library
22
-
23
- MusicBrainz asks that you [identifying 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).
24
- By passing `appName`, `appVersion`, `appMail` musicbrainz-api takes care of that.
25
-
26
- ## Submitting metadata
27
-
28
- If 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).
29
-
30
- ## Example
31
-
32
- Import the module
33
- JavaScript example, how to import 'musicbrainz-api:
34
- ```js
35
- const MusicBrainzApi = require('musicbrainz-api').MusicBrainzApi;
36
-
37
- const mbApi = new MusicBrainzApi({
38
- appName: 'my-app',
39
- appVersion: '0.1.0',
40
- appContactInfo: 'user@mail.org'
41
- });
42
- ```
43
-
44
- In TypeScript you it would look like this:
45
- ```js
46
- import {MusicBrainzApi} from 'musicbrainz-api';
47
-
48
- const mbApi = new MusicBrainzApi({
49
- appName: 'my-app',
50
- appVersion: '0.1.0',
51
- appContactInfo: 'user@mail.org' // Or URL to application home page
52
- });
53
- ```
54
-
55
- The following configuration settings can be passed
56
- ```js
57
- import {MusicBrainzApi} from '../src/musicbrainz-api';
58
-
59
- const config = {
60
- // MusicBrainz bot account username & password (optional)
61
- botAccount: {
62
- username: 'myUserName_bot',
63
- password: 'myPassword'
64
- },
65
-
66
- // API base URL, default: 'https://musicbrainz.org' (optional)
67
- baseUrl: 'https://musicbrainz.org',
68
-
69
- appName: 'my-app',
70
- appVersion: '0.1.0',
71
-
72
- // Optional, default: no proxy server
73
- proxy: {
74
- host: 'localhost',
75
- port: 8888
76
- },
77
-
78
- // Your e-mail address, required for submitting ISRCs
79
- appMail: string
80
- }
81
-
82
- const mbApi = new MusicbrainzApi(config);
83
- ```
84
-
85
- ## Lookup MusicBrainz Entities
86
-
87
- MusicBrainz API documentation: [XML Web Service/Version 2 Lookups](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Lookups)
88
-
89
- ### Generic lookup function
90
-
91
- Arguments:
92
- * entity: `'artist'` | `'label'` | `'recording'` | `'release'` | `'release-group'` | `'work'` | `'area'` | `'url'`
93
- * MBID [(MusicBrainz identifier)](https://wiki.musicbrainz.org/MusicBrainz_Identifier)
94
-
95
- ```js
96
- const artist = await mbApi.lookupEntity('artist', 'ab2528d9-719f-4261-8098-21849222a0f2');
97
- ```
98
-
99
- ### Lookup area
100
-
101
- ```js
102
- const area = await mbApi.lookupArea('ab2528d9-719f-4261-8098-21849222a0f2');
103
- ```
104
-
105
- ### Lookup artist
106
-
107
- Lookup an `artist` and include their `releases`, `release-groups` and `aliases`
108
-
109
- ```js
110
- const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2');
111
- ```
112
-
113
- ### Lookup instrument
114
-
115
- Lookup an instrument
116
-
117
- ```js
118
- const instrument = await mbApi.lookupInstrument('b3eac5f9-7859-4416-ac39-7154e2e8d348');
119
- ```
120
-
121
- ### Lookup label
122
-
123
- Lookup a label
124
-
125
- ```js
126
- const label = await mbApi.lookupLabel('25dda9f9-f069-4898-82f0-59330a106c7f');
127
- ```
128
-
129
- ### Lookup place
130
-
131
- ```js
132
- const place = await mbApi.lookupPlace('e6cfb74d-d69b-44c3-b890-1b3f509816e4');
133
- ```
134
-
135
- The second argument can be used to pass [subqueries](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Subqueries), which will return more (nested) information:
136
- ```js
137
- const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2', ['releases', 'recordings', 'url-rels']);
138
- ```
139
-
140
- ### Lookup recording
141
-
142
- The second argument can be used to pass [subqueries](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Subqueries):
143
- ```js
144
- const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c', ['artists', 'url-rels']);
145
- ```
146
-
147
- ### Lookup release
148
- ```js
149
- const release = await mbApi.lookupRelease('976e0677-a480-4a5e-a177-6a86c1900bbf', ['artists', 'url-rels']);
150
- ```
151
-
152
- ### Lookup release-group
153
- ```js
154
- const releaseGroup = await mbApi.lookupReleaseGroup('19099ea5-3600-4154-b482-2ec68815883e');
155
- ```
156
-
157
- ### Lookup work
158
- ```js
159
- const work = await mbApi.lookupWork('b2aa02f4-6c95-43be-a426-aedb9f9a3805');
160
- ```
161
-
162
- ### Lookup URL
163
- ```js
164
- const url = await mbApi.lookupUrl('c69556a6-7ded-4c54-809c-afb45a1abe7d');
165
- ```
166
-
167
- ## Browse entities
168
-
169
- ### Browse area
170
-
171
- ```js
172
- const area = await browseAreas(query);
173
- ````
174
-
175
- | Query argument | Query value |
176
- |-----------------------|-----------------|
177
- | `query.collection` | Collection MBID |
178
-
179
- ### Browse artist
180
-
181
- ```js
182
- const artist = await browseArtist(query);
183
- ````
184
-
185
- | Query argument | Query value |
186
- |-----------------------|--------------------|
187
- | `query.area` | Area MBID |
188
- | `query.collection` | Collection MBID |
189
- | `query.recording` | Recording MBID |
190
- | `query.release` | Release MBID |
191
- | `query.release-group` | Release-group MBID |
192
- | `query.work` | Work MBID |
193
-
194
- ### Browse collection
195
- ```js
196
- const artist = await browseCollection(query);
197
- ````
198
-
199
- | Query argument | Query value |
200
- |-----------------------|--------------------|
201
- | `query.area` | Area MBID |
202
- | `query.artist` | Artist MBID |
203
- | `query.editor` | Editor MBID |
204
- | `query.event` | Event MBID |
205
- | `query.label` | Label MBID |
206
- | `query.place` | Place MBID |
207
- | `query.recording` | Recording MBID |
208
- | `query.release` | Release MBID |
209
- | `query.release-group` | Release-group MBID |
210
- | `query.work` | Work MBID |
211
-
212
- ### Browse events
213
- ```js
214
- const events = await browseEvents(query);
215
- ````
216
-
217
- | Query argument | Query value |
218
- |-----------------------|-----------------|
219
- | `query.area` | Area MBID |
220
- | `query.artist` | Artist MBID |
221
- | `query.collection` | Collection MBID |
222
- | `query.place` | Place MBID |
223
-
224
- ### Browse instruments
225
- ```js
226
- const instruments = await browseEvents(query);
227
- ````
228
-
229
- | Query argument | Query value |
230
- |-----------------------|--------------------|
231
- | `query.collection` | Collection MBID |
232
-
233
- ### Browse labels
234
- ```js
235
- const labels = await browseLabels(query);
236
- ````
237
-
238
- | Query argument | Query value |
239
- |--------------------|-----------------|
240
- | `query.area` | Area MBID |
241
- | `query.collection` | Collection MBID |
242
- | `query.release` | Release MBID |
243
-
244
- ### Browse places
245
- ```js
246
- const places = await browsePlaces(query);
247
- ````
248
-
249
- | Query argument | Query value |
250
- |--------------------|-----------------|
251
- | `query.area` | Area MBID |
252
- | `query.collection` | Collection MBID |
253
-
254
- ### Browse recordings
255
- ```js
256
- const recordings = await browseRecordings(query);
257
- ````
258
-
259
- | Query argument | Query value |
260
- |--------------------|-----------------|
261
- | `query.artist` | Area MBID |
262
- | `query.collection` | Collection MBID |
263
- | `query.release` | Release MBID |
264
- | `query.work` | Work MBID |
265
-
266
- ### Browse releases
267
- ```js
268
- const places = await browseReleases(query);
269
- ````
270
-
271
- | Query argument | Query value |
272
- |-----------------------|--------------------|
273
- | `query.area` | Area MBID |
274
- | `query.artist` | Artist MBID |
275
- | `query.editor` | Editor MBID |
276
- | `query.event` | Event MBID |
277
- | `query.label` | Label MBID |
278
- | `query.place` | Place MBID |
279
- | `query.recording` | Recording MBID |
280
- | `query.release` | Release MBID |
281
- | `query.release-group` | Release-group MBID |
282
- | `query.work` | Work MBID |
283
-
284
- ### Browse release-groups
285
- ```js
286
- const places = await browseReleaseGroups(query);
287
- ```
288
-
289
- | Query argument | Query value |
290
- |--------------------|-----------------|
291
- | `query.artist` | Artist MBID |
292
- | `query.collection` | Collection MBID |
293
- | `query.release` | Release MBID |
294
-
295
- ### Browse series
296
- ```js
297
- const places = await browseSeries();
298
- ````
299
-
300
- | Query argument | Query value |
301
- |-----------------------|--------------------|
302
- | `query.area` | Area MBID |
303
- | `query.artist` | Artist MBID |
304
- | `query.editor` | Editor MBID |
305
- | `query.event` | Event MBID |
306
- | `query.label` | Label MBID |
307
- | `query.place` | Place MBID |
308
- | `query.recording` | Recording MBID |
309
- | `query.release` | Release MBID |
310
- | `query.release-group` | Release-group MBID |
311
- | `query.work` | Work MBID |
312
-
313
- ### Browse works
314
- ```js
315
- const places = await browseWorks();
316
- ````
317
-
318
- | Query argument | Query value |
319
- |--------------------|-----------------|
320
- | `query.artist` | Artist MBID |
321
- | `query.xollection` | Collection MBID |
322
-
323
- ### Browse urls
324
- ```js
325
- const urls = await browseUrls();
326
- ````
327
-
328
- | Query argument | Query value |
329
- |--------------------|-----------------|
330
- | `query.artist` | Artist MBID |
331
- | `query.xollection` | Collection MBID |
332
-
333
- ## Search (query)
334
-
335
- Implements [XML Web Service/Version 2/Search](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search).
336
-
337
- There are different search fields depending on the entity.
338
-
339
- ### Generic search function
340
-
341
- Searches can be performed using the generic search function: `query(entity: mb.EntityType, query: string | IFormData, offset?: number, limit?: number)`
342
-
343
- Arguments:
344
- * Entity type, which can be one of:
345
- * `artist`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Artist)
346
- * `label`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Label)
347
- * `recording`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Recording)
348
- * `release`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Release)
349
- * `release-group`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Release_Group)
350
- * `work`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Work)
351
- * `area`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Area)
352
- * `url`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#URL)
353
- * `query {query: string, offset: number, limit: number}`
354
- * `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.
355
- * `query.offset`: optional, return search results starting at a given offset. Used for paging through more than one page of results.
356
- * `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.
357
-
358
- For example, to find any recordings of _'We Will Rock You'_ by Queen:
359
- ```js
360
- const query = 'query="We Will Rock You" AND arid:0383dadf-2a4e-4d10-a46a-e9e041da8eb3';
361
- const result = await mbApi.query<mb.IReleaseGroupList>('release-group', {query});
362
- ```
363
-
364
- ##### Example: search Île-de-France
365
-
366
- ```js
367
- mbApi.search('area', 'Île-de-France');
368
- ````
369
-
370
- ##### Example: search release by barcode
371
-
372
- Search a release with the barcode 602537479870:
373
- ```js
374
- mbApi.search('release', {query: {barcode: 602537479870}});
375
- ````
376
-
377
- ##### Example: search by object
378
-
379
- Same as previous example, but automatically serialize parameters to search query
380
- ```js
381
- mbApi.search('release', 'barcode: 602537479870');
382
- ````
383
-
384
- ### Entity specific search functions
385
-
386
- The following entity specific search functions are available:
387
- ```TypeScript
388
- searchArtist(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IArtistList>
389
- searchReleaseGroup(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IReleaseGroupList>`
390
- ```
391
-
392
- Search artist:
393
- ```js
394
- const result = await mbApi.searchArtist({query: 'Stromae'});
395
- ```
396
-
397
- Search release-group:
398
- ```js
399
- const result = await mbApi.searchReleaseGroup({query: 'Racine carrée'});
400
- ```
401
-
402
- Search a combination of a release-group and an artist.
403
- ```js
404
- const result = await mbApi.searchReleaseGroup({artist: 'Racine carrée', releasegroup: 'Stromae'});
405
- ```
406
-
407
- # Submitting data via XML POST
408
-
409
- [Submitting data via XML POST](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Submitting_data) may be done using personal MusicBrainz credentials.
410
-
411
- ## Submit ISRC code using XML POST
412
-
413
- Using the [XML ISRC submission](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#ISRC_submission) API.
414
-
415
- ```js
416
- const mbid_Formidable = '16afa384-174e-435e-bfa3-5591accda31c';
417
- const isrc_Formidable = 'BET671300161';
418
-
419
- const xmlMetadata = new XmlMetadata();
420
- const xmlRecording = xmlMetadata.pushRecording(mbid_Formidable);
421
- xmlRecording.isrcList.pushIsrc(isrc_Formidable);
422
- await mbApi.post('recording', xmlMetadata);
423
- ```
424
-
425
- # Submitting data via user form-data
426
-
427
- For all of the following function you need to use a dedicated bot account.
428
-
429
- ## Submitting ISRC via post user form-data
430
-
431
- <img width="150" src="http://www.clker.com/cliparts/i/w/L/q/u/1/work-in-progress.svg"/>
432
- Use with caution, and only on a test server, it may clear existing metadata as side effect.
433
-
434
- ```js
435
-
436
- const mbid_Formidable = '16afa384-174e-435e-bfa3-5591accda31c';
437
- const isrc_Formidable = 'BET671300161';
438
-
439
-
440
- const recording = await mbApi.lookupRecording(mbid_Formidable);
441
-
442
- // Authentication the http-session against MusicBrainz (as defined in config.baseUrl)
443
- const succeed = await mbApi.login();
444
- assert.isTrue(succeed, 'Login successful');
445
-
446
- // To submit the ISRC, the `recording.id` and `recording.title` are required
447
- await mbApi.addIsrc(recording, isrc_Formidable);
448
- ```
449
-
450
- ### Submit recording URL
451
-
452
- ```js
453
- const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c');
454
-
455
- const succeed = await mbApi.login();
456
- assert.isTrue(succeed, 'Login successful');
457
-
458
- await mbApi.addUrlToRecording(recording, {
459
- linkTypeId: LinkType.stream_for_free,
460
- text: 'https://open.spotify.com/track/2AMysGXOe0zzZJMtH3Nizb'
461
- });
462
- ```
463
-
464
- Actually a Spotify-track-ID can be submitted easier:
465
- ```js
466
- const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c');
467
-
468
- const succeed = await mbApi.login();
469
- assert.isTrue(succeed, 'Login successful');
470
- await mbApi.addSpotifyIdToRecording(recording, '2AMysGXOe0zzZJMtH3Nizb');
471
- ```
472
-
473
- ## Compatibility
474
-
475
- The JavaScript in runtime is compliant with [ECMAScript 2017 (ES8)](https://en.wikipedia.org/wiki/ECMAScript#8th_Edition_-_ECMAScript_2017).
476
- Requires [Node.js®](https://nodejs.org/) version 6 or higher.
1
+ [![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)
2
+ [![NPM version](https://img.shields.io/npm/v/musicbrainz-api.svg)](https://npmjs.org/package/musicbrainz-api)
3
+ [![npm downloads](http://img.shields.io/npm/dm/musicbrainz-api.svg)](https://npmcharts.com/compare/musicbrainz-api?interval=30&start=365)
4
+ [![Coverage Status](https://coveralls.io/repos/github/Borewit/musicbrainz-api/badge.svg?branch=master)](https://coveralls.io/github/Borewit/musicbrainz-api?branch=master)
5
+ [![Codacy Badge](https://app.codacy.com/project/badge/Grade/2bc47b2006454bae8c737991f152e518)](https://www.codacy.com/gh/Borewit/musicbrainz-api/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=Borewit/musicbrainz-api&amp;utm_campaign=Badge_Grade)
6
+ [![CodeQL](https://github.com/Borewit/musicbrainz-api/actions/workflows/codeql.yml/badge.svg)](https://github.com/Borewit/musicbrainz-api/actions/workflows/codeql.yml)
7
+ [![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)
8
+ [![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)
9
+ [![Discord](https://img.shields.io/discord/460524735235883049.svg)](https://discord.gg/958xT5X)
10
+
11
+ # musicbrainz-api
12
+
13
+ A MusicBrainz-API-client for reading and submitting metadata
14
+
15
+ ## Features
16
+ * Access metadata from MusicBrainz
17
+ * Submit metadata
18
+ * Smart and adjustable throttling, like MusicBrainz, it allows a bursts of requests
19
+ * Build in TypeScript definitions
20
+
21
+ ### Hint
22
+
23
+ This package is currently only developed for the use in a [node.js environment](http://nodejs.org/).
24
+ We are looking into making this package usable in the browser as well.
25
+
26
+ ## Before using this library
27
+
28
+ MusicBrainz 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).
29
+ By passing `appName`, `appVersion`, `appMail` musicbrainz-api takes care of that.
30
+
31
+ ## Submitting metadata
32
+
33
+ If 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).
34
+
35
+ ## Example
36
+
37
+ Import the module
38
+ JavaScript example, how to import 'musicbrainz-api:
39
+ ```js
40
+ const MusicBrainzApi = require('musicbrainz-api').MusicBrainzApi;
41
+
42
+ const mbApi = new MusicBrainzApi({
43
+ appName: 'my-app',
44
+ appVersion: '0.1.0',
45
+ appContactInfo: 'user@mail.org'
46
+ });
47
+ ```
48
+
49
+ In TypeScript it would look like this:
50
+ ```js
51
+ import {MusicBrainzApi} from 'musicbrainz-api';
52
+
53
+ const mbApi = new MusicBrainzApi({
54
+ appName: 'my-app',
55
+ appVersion: '0.1.0',
56
+ appContactInfo: 'user@mail.org' // Or URL to application home page
57
+ });
58
+ ```
59
+
60
+ The following configuration settings can be passed
61
+ ```js
62
+ import {MusicBrainzApi} from '../src/musicbrainz-api';
63
+
64
+ const config = {
65
+ // MusicBrainz bot account username & password (optional)
66
+ botAccount: {
67
+ username: 'myUserName_bot',
68
+ password: 'myPassword'
69
+ },
70
+
71
+ // API base URL, default: 'https://musicbrainz.org' (optional)
72
+ baseUrl: 'https://musicbrainz.org',
73
+
74
+ appName: 'my-app',
75
+ appVersion: '0.1.0',
76
+
77
+ // Optional, default: no proxy server
78
+ proxy: {
79
+ host: 'localhost',
80
+ port: 8888
81
+ },
82
+
83
+ // Your e-mail address, required for submitting ISRCs
84
+ appMail: string
85
+ }
86
+
87
+ const mbApi = new MusicbrainzApi(config);
88
+ ```
89
+
90
+ ## Lookup MusicBrainz Entities
91
+
92
+ MusicBrainz API documentation: [XML Web Service/Version 2 Lookups](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Lookups)
93
+
94
+ ### Generic lookup function
95
+
96
+ Arguments:
97
+ * entity: `'artist'` | `'label'` | `'recording'` | `'release'` | `'release-group'` | `'work'` | `'area'` | `'url'`
98
+ * MBID [(MusicBrainz identifier)](https://wiki.musicbrainz.org/MusicBrainz_Identifier)
99
+
100
+ ```js
101
+ const artist = await mbApi.lookupEntity('artist', 'ab2528d9-719f-4261-8098-21849222a0f2');
102
+ ```
103
+
104
+ ### Lookup area
105
+
106
+ ```js
107
+ const area = await mbApi.lookupArea('ab2528d9-719f-4261-8098-21849222a0f2');
108
+ ```
109
+
110
+ ### Lookup artist
111
+
112
+ Lookup an `artist` and include their `releases`, `release-groups` and `aliases`
113
+
114
+ ```js
115
+ const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2');
116
+ ```
117
+
118
+ ### Lookup instrument
119
+
120
+ Lookup an instrument
121
+
122
+ ```js
123
+ const instrument = await mbApi.lookupInstrument('b3eac5f9-7859-4416-ac39-7154e2e8d348');
124
+ ```
125
+
126
+ ### Lookup label
127
+
128
+ Lookup a label
129
+
130
+ ```js
131
+ const label = await mbApi.lookupLabel('25dda9f9-f069-4898-82f0-59330a106c7f');
132
+ ```
133
+
134
+ ### Lookup place
135
+
136
+ ```js
137
+ const place = await mbApi.lookupPlace('e6cfb74d-d69b-44c3-b890-1b3f509816e4');
138
+ ```
139
+
140
+ The second argument can be used to pass [subqueries](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Subqueries), which will return more (nested) information:
141
+ ```js
142
+ const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2', ['releases', 'recordings', 'url-rels']);
143
+ ```
144
+
145
+ ### Lookup recording
146
+
147
+ The second argument can be used to pass [subqueries](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Subqueries):
148
+ ```js
149
+ const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c', ['artists', 'url-rels']);
150
+ ```
151
+
152
+ ### Lookup release
153
+ ```js
154
+ const release = await mbApi.lookupRelease('976e0677-a480-4a5e-a177-6a86c1900bbf', ['artists', 'url-rels']);
155
+ ```
156
+
157
+ ### Lookup release-group
158
+ ```js
159
+ const releaseGroup = await mbApi.lookupReleaseGroup('19099ea5-3600-4154-b482-2ec68815883e');
160
+ ```
161
+
162
+ ### Lookup work
163
+ ```js
164
+ const work = await mbApi.lookupWork('b2aa02f4-6c95-43be-a426-aedb9f9a3805');
165
+ ```
166
+
167
+ ### Lookup URL
168
+ ```js
169
+ const url = await mbApi.lookupUrl('c69556a6-7ded-4c54-809c-afb45a1abe7d');
170
+ ```
171
+
172
+ ## Browse entities
173
+
174
+ ### Browse area
175
+
176
+ ```js
177
+ const area = await browseAreas(query);
178
+ ````
179
+
180
+ | Query argument | Query value |
181
+ |-----------------------|-----------------|
182
+ | `query.collection` | Collection MBID |
183
+
184
+ ### Browse artist
185
+
186
+ ```js
187
+ const artist = await browseArtist(query);
188
+ ````
189
+
190
+ | Query argument | Query value |
191
+ |-----------------------|--------------------|
192
+ | `query.area` | Area MBID |
193
+ | `query.collection` | Collection MBID |
194
+ | `query.recording` | Recording MBID |
195
+ | `query.release` | Release MBID |
196
+ | `query.release-group` | Release-group MBID |
197
+ | `query.work` | Work MBID |
198
+
199
+ ### Browse collection
200
+ ```js
201
+ const artist = await browseCollection(query);
202
+ ````
203
+
204
+ | Query argument | Query value |
205
+ |-----------------------|--------------------|
206
+ | `query.area` | Area MBID |
207
+ | `query.artist` | Artist MBID |
208
+ | `query.editor` | Editor MBID |
209
+ | `query.event` | Event MBID |
210
+ | `query.label` | Label MBID |
211
+ | `query.place` | Place MBID |
212
+ | `query.recording` | Recording MBID |
213
+ | `query.release` | Release MBID |
214
+ | `query.release-group` | Release-group MBID |
215
+ | `query.work` | Work MBID |
216
+
217
+ ### Browse events
218
+ ```js
219
+ const events = await browseEvents(query);
220
+ ````
221
+
222
+ | Query argument | Query value |
223
+ |-----------------------|-----------------|
224
+ | `query.area` | Area MBID |
225
+ | `query.artist` | Artist MBID |
226
+ | `query.collection` | Collection MBID |
227
+ | `query.place` | Place MBID |
228
+
229
+ ### Browse instruments
230
+ ```js
231
+ const instruments = await browseEvents(query);
232
+ ````
233
+
234
+ | Query argument | Query value |
235
+ |-----------------------|--------------------|
236
+ | `query.collection` | Collection MBID |
237
+
238
+ ### Browse labels
239
+ ```js
240
+ const labels = await browseLabels(query);
241
+ ````
242
+
243
+ | Query argument | Query value |
244
+ |--------------------|-----------------|
245
+ | `query.area` | Area MBID |
246
+ | `query.collection` | Collection MBID |
247
+ | `query.release` | Release MBID |
248
+
249
+ ### Browse places
250
+ ```js
251
+ const places = await browsePlaces(query);
252
+ ````
253
+
254
+ | Query argument | Query value |
255
+ |--------------------|-----------------|
256
+ | `query.area` | Area MBID |
257
+ | `query.collection` | Collection MBID |
258
+
259
+ ### Browse recordings
260
+ ```js
261
+ const recordings = await browseRecordings(query);
262
+ ````
263
+
264
+ | Query argument | Query value |
265
+ |--------------------|-----------------|
266
+ | `query.artist` | Area MBID |
267
+ | `query.collection` | Collection MBID |
268
+ | `query.release` | Release MBID |
269
+ | `query.work` | Work MBID |
270
+
271
+ ### Browse releases
272
+ ```js
273
+ const places = await browseReleases(query);
274
+ ````
275
+
276
+ | Query argument | Query value |
277
+ |-----------------------|--------------------|
278
+ | `query.area` | Area MBID |
279
+ | `query.artist` | Artist MBID |
280
+ | `query.editor` | Editor MBID |
281
+ | `query.event` | Event MBID |
282
+ | `query.label` | Label MBID |
283
+ | `query.place` | Place MBID |
284
+ | `query.recording` | Recording MBID |
285
+ | `query.release` | Release MBID |
286
+ | `query.release-group` | Release-group MBID |
287
+ | `query.work` | Work MBID |
288
+
289
+ ### Browse release-groups
290
+ ```js
291
+ const places = await browseReleaseGroups(query);
292
+ ```
293
+
294
+ | Query argument | Query value |
295
+ |--------------------|-----------------|
296
+ | `query.artist` | Artist MBID |
297
+ | `query.collection` | Collection MBID |
298
+ | `query.release` | Release MBID |
299
+
300
+ ### Browse series
301
+ ```js
302
+ const places = await browseSeries();
303
+ ````
304
+
305
+ | Query argument | Query value |
306
+ |-----------------------|--------------------|
307
+ | `query.area` | Area MBID |
308
+ | `query.artist` | Artist MBID |
309
+ | `query.editor` | Editor MBID |
310
+ | `query.event` | Event MBID |
311
+ | `query.label` | Label MBID |
312
+ | `query.place` | Place MBID |
313
+ | `query.recording` | Recording MBID |
314
+ | `query.release` | Release MBID |
315
+ | `query.release-group` | Release-group MBID |
316
+ | `query.work` | Work MBID |
317
+
318
+ ### Browse works
319
+ ```js
320
+ const places = await browseWorks();
321
+ ````
322
+
323
+ | Query argument | Query value |
324
+ |--------------------|-----------------|
325
+ | `query.artist` | Artist MBID |
326
+ | `query.xollection` | Collection MBID |
327
+
328
+ ### Browse urls
329
+ ```js
330
+ const urls = await browseUrls();
331
+ ````
332
+
333
+ | Query argument | Query value |
334
+ |--------------------|-----------------|
335
+ | `query.artist` | Artist MBID |
336
+ | `query.xollection` | Collection MBID |
337
+
338
+ ## Search (query)
339
+
340
+ Implements [XML Web Service/Version 2/Search](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search).
341
+
342
+ There are different search fields depending on the entity.
343
+
344
+ ### Generic search function
345
+
346
+ Searches can be performed using the generic search function: `query(entity: mb.EntityType, query: string | IFormData, offset?: number, limit?: number)`
347
+
348
+ Arguments:
349
+ * Entity type, which can be one of:
350
+ * `artist`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Artist)
351
+ * `label`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Label)
352
+ * `recording`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Recording)
353
+ * `release`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Release)
354
+ * `release-group`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Release_Group)
355
+ * `work`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Work)
356
+ * `area`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#Area)
357
+ * `url`: [search fields](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2/Search#URL)
358
+ * `query {query: string, offset: number, limit: number}`
359
+ * `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.
360
+ * `query.offset`: optional, return search results starting at a given offset. Used for paging through more than one page of results.
361
+ * `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.
362
+
363
+ For example, to find any recordings of _'We Will Rock You'_ by Queen:
364
+ ```js
365
+ const query = 'query="We Will Rock You" AND arid:0383dadf-2a4e-4d10-a46a-e9e041da8eb3';
366
+ const result = await mbApi.query<mb.IReleaseGroupList>('release-group', {query});
367
+ ```
368
+
369
+ ##### Example: search Île-de-France
370
+
371
+ ```js
372
+ mbApi.search('area', 'Île-de-France');
373
+ ````
374
+
375
+ ##### Example: search release by barcode
376
+
377
+ Search a release with the barcode 602537479870:
378
+ ```js
379
+ mbApi.search('release', {query: {barcode: 602537479870}});
380
+ ````
381
+
382
+ ##### Example: search by object
383
+
384
+ Same as previous example, but automatically serialize parameters to search query
385
+ ```js
386
+ mbApi.search('release', 'barcode: 602537479870');
387
+ ````
388
+
389
+ ### Entity specific search functions
390
+
391
+ The following entity specific search functions are available:
392
+ ```TypeScript
393
+ searchArtist(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IArtistList>
394
+ searchReleaseGroup(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IReleaseGroupList>`
395
+ ```
396
+
397
+ Search artist:
398
+ ```js
399
+ const result = await mbApi.searchArtist({query: 'Stromae'});
400
+ ```
401
+
402
+ Search release-group:
403
+ ```js
404
+ const result = await mbApi.searchReleaseGroup({query: 'Racine carrée'});
405
+ ```
406
+
407
+ Search a combination of a release-group and an artist.
408
+ ```js
409
+ const result = await mbApi.searchReleaseGroup({artist: 'Racine carrée', releasegroup: 'Stromae'});
410
+ ```
411
+
412
+ # Submitting data via XML POST
413
+
414
+ [Submitting data via XML POST](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Submitting_data) may be done using personal MusicBrainz credentials.
415
+
416
+ ## Submit ISRC code using XML POST
417
+
418
+ Using the [XML ISRC submission](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#ISRC_submission) API.
419
+
420
+ ```js
421
+ const mbid_Formidable = '16afa384-174e-435e-bfa3-5591accda31c';
422
+ const isrc_Formidable = 'BET671300161';
423
+
424
+ const xmlMetadata = new XmlMetadata();
425
+ const xmlRecording = xmlMetadata.pushRecording(mbid_Formidable);
426
+ xmlRecording.isrcList.pushIsrc(isrc_Formidable);
427
+ await mbApi.post('recording', xmlMetadata);
428
+ ```
429
+
430
+ # Submitting data via user form-data
431
+
432
+ For all of the following function you need to use a dedicated bot account.
433
+
434
+ ## Submitting ISRC via post user form-data
435
+
436
+ <img width="150" src="http://www.clker.com/cliparts/i/w/L/q/u/1/work-in-progress.svg"/>
437
+ Use with caution, and only on a test server, it may clear existing metadata as side effect.
438
+
439
+ ```js
440
+
441
+ const mbid_Formidable = '16afa384-174e-435e-bfa3-5591accda31c';
442
+ const isrc_Formidable = 'BET671300161';
443
+
444
+
445
+ const recording = await mbApi.lookupRecording(mbid_Formidable);
446
+
447
+ // Authentication the http-session against MusicBrainz (as defined in config.baseUrl)
448
+ const succeed = await mbApi.login();
449
+ assert.isTrue(succeed, 'Login successful');
450
+
451
+ // To submit the ISRC, the `recording.id` and `recording.title` are required
452
+ await mbApi.addIsrc(recording, isrc_Formidable);
453
+ ```
454
+
455
+ ### Submit recording URL
456
+
457
+ ```js
458
+ const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c');
459
+
460
+ const succeed = await mbApi.login();
461
+ assert.isTrue(succeed, 'Login successful');
462
+
463
+ await mbApi.addUrlToRecording(recording, {
464
+ linkTypeId: LinkType.stream_for_free,
465
+ text: 'https://open.spotify.com/track/2AMysGXOe0zzZJMtH3Nizb'
466
+ });
467
+ ```
468
+
469
+ Actually a Spotify-track-ID can be submitted easier:
470
+ ```js
471
+ const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c');
472
+
473
+ const succeed = await mbApi.login();
474
+ assert.isTrue(succeed, 'Login successful');
475
+ await mbApi.addSpotifyIdToRecording(recording, '2AMysGXOe0zzZJMtH3Nizb');
476
+ ```
477
+
478
+ ## Compatibility
479
+
480
+ The JavaScript in runtime is compliant with [ECMAScript 2017 (ES8)](https://en.wikipedia.org/wiki/ECMAScript#8th_Edition_-_ECMAScript_2017).
481
+ Requires [Node.js®](https://nodejs.org/) version 6 or higher.