musicbrainz-api 0.13.0 → 0.14.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
@@ -2,7 +2,7 @@
2
2
  [![NPM version](https://img.shields.io/npm/v/musicbrainz-api.svg)](https://npmjs.org/package/musicbrainz-api)
3
3
  [![npm downloads](http://img.shields.io/npm/dm/musicbrainz-api.svg)](https://npmcharts.com/compare/musicbrainz-api?interval=30&start=365)
4
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)
5
+ [![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)
6
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
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
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)
@@ -82,106 +82,14 @@ MusicBrainz API documentation: [XML Web Service/Version 2 Lookups](https://wiki.
82
82
  ### Generic lookup function
83
83
 
84
84
  Arguments:
85
- * entity: `'artist'` | `'label'` | `'recording'` | `'release'` | `'release-group'` | `'work'` | `'area'` | `'url'`
85
+ * entity: `'area'` | `'artist'` | `'collection'` | `'instrument'` | `'label'` | `'place'` | `'release'` | `'release-group'` | `'recording'` | `'series'` | `'work'` | `'url'` | `'event'`
86
86
  * MBID [(MusicBrainz identifier)](https://wiki.musicbrainz.org/MusicBrainz_Identifier)
87
+ * query
87
88
 
88
89
  ```js
89
- const artist = await mbApi.lookupEntity('artist', 'ab2528d9-719f-4261-8098-21849222a0f2');
90
+ const artist = await mbApi.lookup('artist', 'ab2528d9-719f-4261-8098-21849222a0f2');
90
91
  ```
91
92
 
92
- ### Lookup area
93
-
94
- ```js
95
- const area = await mbApi.lookupArea('ab2528d9-719f-4261-8098-21849222a0f2');
96
- ```
97
-
98
- ### Lookup artist
99
-
100
- Lookup an `artist` and include their `releases`, `release-groups` and `aliases`
101
-
102
- ```js
103
- const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2');
104
- ```
105
-
106
- ### Lookup collection
107
-
108
- Lookup an instrument
109
-
110
- ```js
111
- const collection = await mbApi.lookupCollection('de4fdfc4-53aa-458a-b463-8761cc7f5af8');
112
- ```
113
-
114
- Lookup an event
115
-
116
- ```js
117
- const event = await mbApi.lookupEvent('6d32c658-151e-45ec-88c4-fb8787524d61');
118
- ```
119
-
120
- ### Lookup instrument
121
-
122
- Lookup an instrument
123
-
124
- ```js
125
- const instrument = await mbApi.lookupInstrument('b3eac5f9-7859-4416-ac39-7154e2e8d348');
126
- ```
127
-
128
- ### Lookup label
129
-
130
- Lookup a label
131
-
132
- ```js
133
- const label = await mbApi.lookupLabel('25dda9f9-f069-4898-82f0-59330a106c7f');
134
- ```
135
-
136
- ### Lookup place
137
-
138
- ```js
139
- const place = await mbApi.lookupPlace('e6cfb74d-d69b-44c3-b890-1b3f509816e4');
140
- ```
141
-
142
- ```js
143
- const place = await mbApi.lookupSeries('1ae6c9bc-2931-4d75-bee4-3dc53dfd246a');
144
- ```
145
-
146
- 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:
147
- ```js
148
- const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2', ['releases', 'recordings', 'url-rels']);
149
- ```
150
-
151
- ### Lookup recording
152
-
153
- The second argument can be used to pass [subqueries](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Subqueries):
154
- ```js
155
- const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c', ['artists', 'url-rels']);
156
- ```
157
-
158
- ### Lookup release
159
- ```js
160
- const release = await mbApi.lookupRelease('976e0677-a480-4a5e-a177-6a86c1900bbf', ['artists', 'url-rels']);
161
- ```
162
-
163
- ### Lookup release-group
164
- ```js
165
- const releaseGroup = await mbApi.lookupReleaseGroup('19099ea5-3600-4154-b482-2ec68815883e');
166
- ```
167
-
168
- ### Lookup work
169
- ```js
170
- const work = await mbApi.lookupWork('b2aa02f4-6c95-43be-a426-aedb9f9a3805');
171
- ```
172
-
173
- ### Lookup URL
174
- ```js
175
- const url = await mbApi.lookupUrl('c69556a6-7ded-4c54-809c-afb45a1abe7d');
176
- ```
177
-
178
- ## Browse entities
179
-
180
- ### Browse area
181
-
182
- ```js
183
- const area = await browseAreas(query);
184
- ````
185
93
 
186
94
  | Query argument | Query value |
187
95
  |-----------------------|-----------------|
@@ -190,7 +98,7 @@ const area = await browseAreas(query);
190
98
  ### Browse artist
191
99
 
192
100
  ```js
193
- const artist = await browseArtist(query);
101
+ const artists = await browse('artist', query);
194
102
  ````
195
103
 
196
104
  | Query argument | Query value |
@@ -204,7 +112,7 @@ const artist = await browseArtist(query);
204
112
 
205
113
  ### Browse collection
206
114
  ```js
207
- const artist = await browseCollection(query);
115
+ const collections = await browse('collection', query);
208
116
  ````
209
117
 
210
118
  | Query argument | Query value |
@@ -222,7 +130,7 @@ const artist = await browseCollection(query);
222
130
 
223
131
  ### Browse events
224
132
  ```js
225
- const events = await browseEvents(query);
133
+ const events = await browse('event', query);
226
134
  ````
227
135
 
228
136
  | Query argument | Query value |
@@ -234,7 +142,7 @@ const events = await browseEvents(query);
234
142
 
235
143
  ### Browse instruments
236
144
  ```js
237
- const instruments = await browseEvents(query);
145
+ const instruments = await browse('event', query);
238
146
  ````
239
147
 
240
148
  | Query argument | Query value |
@@ -243,7 +151,7 @@ const instruments = await browseEvents(query);
243
151
 
244
152
  ### Browse labels
245
153
  ```js
246
- const labels = await browseLabels(query);
154
+ const labels = await browse('label', query);
247
155
  ````
248
156
 
249
157
  | Query argument | Query value |
@@ -254,7 +162,7 @@ const labels = await browseLabels(query);
254
162
 
255
163
  ### Browse places
256
164
  ```js
257
- const places = await browsePlaces(query);
165
+ const places = await browse('place', query);
258
166
  ````
259
167
 
260
168
  | Query argument | Query value |
@@ -264,7 +172,7 @@ const places = await browsePlaces(query);
264
172
 
265
173
  ### Browse recordings
266
174
  ```js
267
- const recordings = await browseRecordings(query);
175
+ const recordings = await browse('recording', query);
268
176
  ````
269
177
 
270
178
  | Query argument | Query value |
@@ -276,7 +184,7 @@ const recordings = await browseRecordings(query);
276
184
 
277
185
  ### Browse releases
278
186
  ```js
279
- const places = await browseReleases(query);
187
+ const releases = await browse('release', query);
280
188
  ````
281
189
 
282
190
  | Query argument | Query value |
@@ -294,7 +202,7 @@ const places = await browseReleases(query);
294
202
 
295
203
  ### Browse release-groups
296
204
  ```js
297
- const places = await browseReleaseGroups(query);
205
+ const releaseGroups = await browse('release-group',query);
298
206
  ```
299
207
 
300
208
  | Query argument | Query value |
@@ -305,7 +213,7 @@ const places = await browseReleaseGroups(query);
305
213
 
306
214
  ### Browse series
307
215
  ```js
308
- const places = await browseSeries();
216
+ const series = await browse('series');
309
217
  ````
310
218
 
311
219
  | Query argument | Query value |
@@ -323,7 +231,7 @@ const places = await browseSeries();
323
231
 
324
232
  ### Browse works
325
233
  ```js
326
- const places = await browseWorks();
234
+ const works = await browse('work');
327
235
  ````
328
236
 
329
237
  | Query argument | Query value |
@@ -333,7 +241,7 @@ const places = await browseWorks();
333
241
 
334
242
  ### Browse urls
335
243
  ```js
336
- const urls = await browseUrls();
244
+ const urls = await browse('url');
337
245
  ````
338
246
 
339
247
  | Query argument | Query value |
@@ -347,9 +255,9 @@ Implements [XML Web Service/Version 2/Search](https://wiki.musicbrainz.org/Devel
347
255
 
348
256
  There are different search fields depending on the entity.
349
257
 
350
- ### Generic search function
258
+ ### Search function
351
259
 
352
- Searches can be performed using the generic search function: `query(entity: mb.EntityType, query: string | IFormData, offset?: number, limit?: number)`
260
+ Searches can be performed using the generic search function: `query(entity: mb.EntityType, query: string | IFormData, offset?: number, limit?: number): Promise<entity>`
353
261
 
354
262
  Arguments:
355
263
  * Entity type, which can be one of:
@@ -392,27 +300,25 @@ Same as previous example, but automatically serialize parameters to search query
392
300
  mbApi.search('release', 'barcode: 602537479870');
393
301
  ````
394
302
 
395
- ### Entity specific search functions
396
-
397
- The following entity specific search functions are available:
398
- ```TypeScript
399
- searchArtist(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IArtistList>
400
- searchReleaseGroup(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IReleaseGroupList>`
401
- ```
303
+ ##### Example: search artist by artist name
402
304
 
403
305
  Search artist:
404
306
  ```js
405
- const result = await mbApi.searchArtist({query: 'Stromae'});
307
+ const result = await mbApi.search('artist', {query: 'Stromae'});
406
308
  ```
407
309
 
310
+ ##### Example: search release-group by artist name
311
+
408
312
  Search release-group:
409
313
  ```js
410
- const result = await mbApi.searchReleaseGroup({query: 'Racine carrée'});
314
+ const result = await mbApi.search('release-group', {query: 'Racine carrée'});
411
315
  ```
412
316
 
317
+ ##### Example: search release-group by release-group and an artist
318
+
413
319
  Search a combination of a release-group and an artist.
414
320
  ```js
415
- const result = await mbApi.searchReleaseGroup({artist: 'Racine carrée', releasegroup: 'Stromae'});
321
+ const result = await mbApi.search('release-group', {artist: 'Racine carrée', releasegroup: 'Stromae'});
416
322
  ```
417
323
 
418
324
  # Submitting data via XML POST
@@ -439,7 +345,7 @@ For all of the following function you need to use a dedicated bot account.
439
345
 
440
346
  ## Submitting ISRC via post user form-data
441
347
 
442
- <img width="150" src="http://www.clker.com/cliparts/i/w/L/q/u/1/work-in-progress.svg"/>
348
+ <img width="150" src="http://www.clker.com/cliparts/i/w/L/q/u/1/work-in-progress.svg" alt="Work in progress"/>
443
349
  Use with caution, and only on a test server, it may clear existing metadata as side effect.
444
350
 
445
351
  ```js
@@ -448,7 +354,7 @@ const mbid_Formidable = '16afa384-174e-435e-bfa3-5591accda31c';
448
354
  const isrc_Formidable = 'BET671300161';
449
355
 
450
356
 
451
- const recording = await mbApi.lookupRecording(mbid_Formidable);
357
+ const recording = await mbApi.lookup('recording', mbid_Formidable);
452
358
 
453
359
  // Authentication the http-session against MusicBrainz (as defined in config.baseUrl)
454
360
  const succeed = await mbApi.login();
@@ -461,7 +367,7 @@ await mbApi.addIsrc(recording, isrc_Formidable);
461
367
  ### Submit recording URL
462
368
 
463
369
  ```js
464
- const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c');
370
+ const recording = await mbApi.lookup('recording', '16afa384-174e-435e-bfa3-5591accda31c');
465
371
 
466
372
  const succeed = await mbApi.login();
467
373
  assert.isTrue(succeed, 'Login successful');
@@ -474,7 +380,7 @@ await mbApi.addUrlToRecording(recording, {
474
380
 
475
381
  Actually a Spotify-track-ID can be submitted easier:
476
382
  ```js
477
- const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c');
383
+ const recording = await mbApi.lookup('recording', '16afa384-174e-435e-bfa3-5591accda31c');
478
384
 
479
385
  const succeed = await mbApi.login();
480
386
  assert.isTrue(succeed, 'Login successful');
@@ -37,7 +37,7 @@ export type InstrumentIncludes = MiscIncludes | RelationsIncludes;
37
37
  export type LabelIncludes = MiscIncludes | RelationsIncludes | 'releases';
38
38
  export type PlaceIncludes = MiscIncludes | RelationsIncludes;
39
39
  export type RecordingIncludes = MiscIncludes | RelationsIncludes | SubQueryIncludes | 'artists' | 'releases' | 'isrcs';
40
- export type ReleasesIncludes = MiscIncludes | SubQueryIncludes | RelationsIncludes | 'artists' | 'collections' | 'labels' | 'recordings' | 'release-groups';
40
+ export type ReleaseIncludes = MiscIncludes | SubQueryIncludes | RelationsIncludes | 'artists' | 'collections' | 'labels' | 'recordings' | 'release-groups';
41
41
  export type ReleaseGroupIncludes = MiscIncludes | SubQueryIncludes | RelationsIncludes | 'artists' | 'releases';
42
42
  export type SeriesIncludes = MiscIncludes | RelationsIncludes;
43
43
  export type WorkIncludes = MiscIncludes | RelationsIncludes;
@@ -84,162 +84,58 @@ export declare class MusicBrainzApi {
84
84
  [key: string]: any;
85
85
  }, attempt?: number): Promise<T>;
86
86
  /**
87
- * Generic lookup function
88
- * @param entity
89
- * @param mbid
90
- * @param inc
91
- */
92
- lookupEntity<T, I extends string = never>(entity: mb.EntityType, mbid: string, inc?: I[]): Promise<T>;
93
- /**
94
- * Lookup area
95
- * @param areaId Area MBID
96
- * @param inc Sub-queries
97
- */
98
- lookupArea(areaId: string, inc?: AreaIncludes[]): Promise<mb.IArea>;
99
- /**
100
- * Lookup artist
101
- * @param artistId Artist MBID
102
- * @param inc Sub-queries
103
- */
104
- lookupArtist(artistId: string, inc?: ArtistIncludes[]): Promise<mb.IArtist>;
105
- /**
106
- * Lookup collection
107
- * @param collectionId Collection MBID
108
- * @param inc List of additional information to be included about the entity. Any of the entities directly linked to the entity can be included.
109
- */
110
- lookupCollection(collectionId: string, inc?: ArtistIncludes[]): Promise<mb.ICollection>;
111
- /**
112
- * Lookup instrument
113
- * @param artistId Instrument MBID
114
- * @param inc Sub-queries
115
- */
116
- lookupInstrument(instrumentId: string, inc?: InstrumentIncludes[]): Promise<mb.IInstrument>;
117
- /**
118
- * Lookup label
119
- * @param labelId Area MBID
120
- * @param inc Sub-queries
121
- */
122
- lookupLabel(labelId: string, inc?: LabelIncludes[]): Promise<mb.ILabel>;
123
- /**
124
- * Lookup place
125
- * @param placeId Area MBID
126
- * @param inc Sub-queries
127
- */
128
- lookupPlace(placeId: string, inc?: PlaceIncludes[]): Promise<mb.IPlace>;
129
- /**
130
- * Lookup release
131
- * @param releaseId Release MBID
132
- * @param inc Include: artist-credits, labels, recordings, release-groups, media, discids, isrcs (with recordings)
133
- * ToDo: ['recordings', 'artists', 'artist-credits', 'isrcs', 'url-rels', 'release-groups']
134
- */
135
- lookupRelease(releaseId: string, inc?: ReleasesIncludes[]): Promise<mb.IRelease>;
136
- /**
137
- * Lookup release-group
138
- * @param releaseGroupId Release-group MBID
139
- * @param inc Include: ToDo
140
- */
141
- lookupReleaseGroup(releaseGroupId: string, inc?: ReleaseGroupIncludes[]): Promise<mb.IReleaseGroup>;
142
- /**
143
- * Lookup recording
144
- * @param recordingId Label MBID
145
- * @param inc Include: artist-credits, isrcs
146
- */
147
- lookupRecording(recordingId: string, inc?: RecordingIncludes[]): Promise<mb.IRecording>;
148
- /**
149
- * Lookup series
150
- * @param seriesId Series MBID
151
- */
152
- lookupSeries(seriesId: string): Promise<mb.ISeries>;
153
- /**
154
- * Lookup work
155
- * @param workId Work MBID
156
- */
157
- lookupWork(workId: string, inc?: WorkIncludes[]): Promise<mb.IWork>;
158
- /**
159
- * Lookup URL
160
- * @param urlId URL MBID
161
- */
162
- lookupUrl(urlId: string, inc?: UrlIncludes[]): Promise<mb.IUrl>;
163
- /**
164
- * Lookup Event
165
- * @param eventId Event MBID
166
- * @param eventIncludes List of sub-queries to enable
167
- */
168
- lookupEvent(eventId: string, eventIncludes?: EventIncludes[]): Promise<mb.IEvent>;
169
- /**
170
- * Generic browse function
87
+ * Lookup entity
88
+ * @param entity 'area', 'artist', collection', 'instrument', 'label', 'place', 'release', 'release-group', 'recording', 'series', 'work', 'url' or 'event'
89
+ * @param mbid Entity MBID
90
+ * @param inc Query, like: {<entity>: <MBID:}
91
+ */
92
+ lookup(entity: 'area', mbid: string, inc?: AreaIncludes[]): Promise<mb.IArea>;
93
+ lookup(entity: 'artist', mbid: string, inc?: ArtistIncludes[]): Promise<mb.IArtist>;
94
+ lookup(entity: 'collection', mbid: string, inc?: CollectionIncludes[]): Promise<mb.ICollection>;
95
+ lookup(entity: 'instrument', mbid: string, inc?: InstrumentIncludes[]): Promise<mb.IInstrument>;
96
+ lookup(entity: 'label', mbid: string, inc?: LabelIncludes[]): Promise<mb.ILabel>;
97
+ lookup(entity: 'place', mbid: string, inc?: PlaceIncludes[]): Promise<mb.IPlace>;
98
+ lookup(entity: 'release', mbid: string, inc?: ReleaseIncludes[]): Promise<mb.IRelease>;
99
+ lookup(entity: 'release-group', mbid: string, inc?: ReleaseGroupIncludes[]): Promise<mb.IReleaseGroup>;
100
+ lookup(entity: 'recording', mbid: string, inc?: RecordingIncludes[]): Promise<mb.IRecording>;
101
+ lookup(entity: 'series', mbid: string, inc?: SeriesIncludes[]): Promise<mb.ISeries>;
102
+ lookup(entity: 'work', mbid: string, inc?: WorkIncludes[]): Promise<mb.IWork>;
103
+ lookup(entity: 'url', mbid: string, inc?: UrlIncludes[]): Promise<mb.IUrl>;
104
+ lookup(entity: 'event', mbid: string, inc?: EventIncludes[]): Promise<mb.IEvent>;
105
+ /**
106
+ * Browse entity
107
+ * https://wiki.musicbrainz.org/MusicBrainz_API#Browse
108
+ * https://wiki.musicbrainz.org/MusicBrainz_API#Linked_entities
171
109
  * https://wiki.musicbrainz.org/Development/JSON_Web_Service#Browse_Requests
110
+ * For example: http://musicbrainz.org/ws/2/release?label=47e718e1-7ee4-460c-b1cc-1192a841c6e5&offset=12&limit=2
172
111
  * @param entity MusicBrainz entity
173
112
  * @param query Query, like: {<entity>: <MBID:}
174
113
  */
175
- browseEntity<T>(entity: mb.EntityType, query?: {
176
- [key: string]: any;
177
- }): Promise<T>;
178
- /**
179
- * Browse areas
180
- * @param query Query, like: {<entity>: <MBID:}
181
- */
182
- browseAreas(query?: mb.IBrowseAreasQuery): Promise<mb.IBrowseAreasResult>;
183
- /**
184
- * Browse artists
185
- * @param query Query, like: {<entity>: <MBID:}
186
- */
187
- browseArtists(query?: mb.IBrowseArtistsQuery): Promise<mb.IBrowseArtistsResult>;
188
- /**
189
- * Browse collections
190
- * @param query Query, like: {<entity>: <MBID:}
191
- */
192
- browseCollections(query?: mb.IBrowseCollectionsQuery): Promise<mb.IBrowseCollectionsResult>;
114
+ browse(entity: 'area', query?: mb.IBrowseAreasQuery): Promise<mb.IBrowseAreasResult>;
115
+ browse(entity: 'artist', query?: mb.IBrowseArtistsQuery): Promise<mb.IBrowseArtistsResult>;
116
+ browse(entity: 'collection', query?: mb.IBrowseCollectionsQuery): Promise<mb.IBrowseCollectionsResult>;
117
+ browse(entity: 'event', query?: mb.IBrowseEventsQuery): Promise<mb.IBrowseEventsResult>;
118
+ browse(entity: 'label', query?: mb.IBrowseLabelsQuery): Promise<mb.IBrowseLabelsResult>;
119
+ browse(entity: 'instrument', query?: mb.IBrowseInstrumentsQuery): Promise<mb.IBrowseInstrumentsResult>;
120
+ browse(entity: 'place', query?: mb.IBrowsePlacesQuery): Promise<mb.IBrowsePlacesResult>;
121
+ browse(entity: 'recording', query?: mb.IBrowseRecordingsQuery): Promise<mb.IBrowseRecordingsResult>;
122
+ browse(entity: 'release', query?: mb.IBrowseReleasesQuery): Promise<mb.IBrowseReleasesResult>;
123
+ browse(entity: 'release-group', query?: mb.IBrowseReleaseGroupsQuery): Promise<mb.IBrowseReleaseGroupsResult>;
124
+ browse(entity: 'series', query?: mb.IBrowseSeriesQuery): Promise<mb.IBrowseSeriesResult>;
125
+ browse(entity: 'url', query?: mb.IBrowseUrlsQuery): Promise<mb.IUrl>;
126
+ browse(entity: 'work', query?: mb.IBrowseWorksQuery): Promise<mb.IBrowseWorksResult>;
193
127
  /**
194
- * Browse events
195
- * @param query Query, like: {<entity>: <MBID:}
196
- */
197
- browseEvents(query?: mb.IBrowseEventsQuery): Promise<mb.IBrowseEventsResult>;
198
- /**
199
- * Browse instruments
200
- * @param query Query, like: {<entity>: <MBID:}
201
- */
202
- browseInstruments(query?: mb.IBrowseInstrumentsQuery): Promise<mb.IBrowseInstrumentsResult>;
203
- /**
204
- * Browse labels
205
- * @param query Query, like: {<entity>: <MBID:}
206
- */
207
- browseLabels(query?: mb.IBrowseLabelsQuery): Promise<mb.IBrowseLabelsResult>;
208
- /**
209
- * Browse places
210
- * @param query Query, like: {<entity>: <MBID:}
211
- */
212
- browsePlaces(query?: mb.IBrowsePlacesQuery): Promise<mb.IBrowsePlacesResult>;
213
- /**
214
- * Browse recordings
215
- * @param query Query, like: {<entity>: <MBID:}
216
- */
217
- browseRecordings(query?: mb.IBrowseRecordingsQuery): Promise<mb.IBrowseRecordingsResult>;
218
- /**
219
- * Browse releases
220
- * @param query Query, like: {<entity>: <MBID:}
221
- */
222
- browseReleases(query?: mb.IBrowseReleasesQuery): Promise<mb.IBrowseReleasesResult>;
223
- /**
224
- * Browse release-groups
225
- * @param query Query, like: {<entity>: <MBID:}
226
- */
227
- browseReleaseGroups(query?: mb.IReleaseGroupsQuery): Promise<mb.IBrowseReleaseGroupsResult>;
228
- /**
229
- * Browse series
230
- * @param query Query, like: {<entity>: <MBID:}
231
- */
232
- browseSeries(query?: mb.IBrowseSeriesQuery): Promise<mb.IBrowseSeriesResult>;
233
- /**
234
- * Browse works
235
- * @param query Query, like: {<entity>: <MBID:}
236
- */
237
- browseWorks(query?: mb.IBrowseWorksQuery): Promise<mb.IBrowseWorksResult>;
238
- /**
239
- * Browse URLs
240
- * @param query Query, like: {<entity>: <MBID:}
128
+ * Search an entity using a search query
129
+ * @param query e.g.: '" artist: Madonna, track: Like a virgin"' or object with search terms: {artist: Madonna}
130
+ * @param entity e.g. 'recording'
131
+ * @param query Arguments
241
132
  */
242
- browseUrls(query?: mb.IBrowseUrlsQuery): Promise<mb.IUrl>;
133
+ search(entity: 'area', query: mb.ISearchQuery<AreaIncludes> & mb.ILinkedEntitiesArea): Promise<mb.IAreaList>;
134
+ search(artist: 'artist', query: mb.ISearchQuery<ArtistIncludes> & mb.ILinkedEntitiesArea): Promise<mb.IArtistList>;
135
+ search(artist: 'recording', query: mb.ISearchQuery<AreaIncludes> & mb.ILinkedEntitiesArea): Promise<mb.IRecordingList>;
136
+ search(artist: 'release', query: mb.ISearchQuery<ReleaseIncludes> & mb.ILinkedEntitiesArea): Promise<mb.IReleaseList>;
137
+ search(artist: 'release-group', query: mb.ISearchQuery<ReleaseGroupIncludes> & mb.ILinkedEntitiesArea): Promise<mb.IReleaseGroupList>;
138
+ search(artist: 'url', query: mb.ISearchQuery<UrlIncludes> & mb.ILinkedEntitiesArea): Promise<mb.IUrlList>;
243
139
  postRecording(xmlMetadata: XmlMetadata): Promise<void>;
244
140
  post(entity: mb.EntityType, xmlMetadata: XmlMetadata): Promise<void>;
245
141
  login(): Promise<boolean>;
@@ -271,13 +167,6 @@ export declare class MusicBrainzApi {
271
167
  * @param editNote Edit note
272
168
  */
273
169
  addIsrc(recording: mb.IRecording, isrc: string, editNote?: string): Promise<void>;
274
- /**
275
- * Search an entity using a search query
276
- * @param query e.g.: '" artist: Madonna, track: Like a virgin"' or object with search terms: {artist: Madonna}
277
- * @param entity e.g. 'recording'
278
- * @param query Arguments
279
- */
280
- search<T extends mb.ISearchResult, I extends string = never>(entity: mb.EntityType, query: mb.ISearchQuery<I>): Promise<T>;
281
170
  /**
282
171
  * Add Spotify-ID to MusicBrainz recording.
283
172
  * This function will automatically lookup the recording title, which is required to submit the recording URL
@@ -286,11 +175,6 @@ export declare class MusicBrainzApi {
286
175
  * @param editNote Comment to add.
287
176
  */
288
177
  addSpotifyIdToRecording(recording: mb.IRecording, spotifyId: string, editNote: string): Promise<void>;
289
- searchArea(query: mb.ISearchQuery<AreaIncludes> & mb.ILinkedEntitiesArea): Promise<mb.IAreaList>;
290
- searchArtist(query: mb.ISearchQuery<ArtistIncludes> & mb.ILinkedEntitiesArtist): Promise<mb.IArtistList>;
291
- searchRelease(query: mb.ISearchQuery<ReleasesIncludes> & mb.ILinkedEntitiesRelease): Promise<mb.IReleaseList>;
292
- searchReleaseGroup(query: mb.ISearchQuery<ReleaseGroupIncludes> & mb.ILinkedEntitiesReleaseGroup): Promise<mb.IReleaseGroupList>;
293
- searchUrl(query: mb.ISearchQuery<UrlIncludes> & mb.ILinkedEntitiesUrl): Promise<mb.IUrlList>;
294
178
  private getSession;
295
179
  }
296
180
  export declare function makeAndQueryString(keyValuePairs: IFormData): string;
@@ -6,7 +6,7 @@ export { XmlIsrc } from './xml/xml-isrc.js';
6
6
  export { XmlIsrcList } from './xml/xml-isrc-list.js';
7
7
  export { XmlRecording } from './xml/xml-recording.js';
8
8
  import { DigestAuth } from './digest-auth.js';
9
- import { RateLimiter } from './rate-limiter.js';
9
+ import { RateLimitThreshold } from 'rate-limit-threshold';
10
10
  import * as mb from './musicbrainz.types.js';
11
11
  import got from 'got';
12
12
  import { CookieJar } from 'tough-cookie';
@@ -80,11 +80,12 @@ export class MusicBrainzApi {
80
80
  },
81
81
  cookieJar: cookieJar
82
82
  };
83
- this.rateLimiter = new RateLimiter(15, 18);
83
+ this.rateLimiter = new RateLimitThreshold(15, 18);
84
84
  }
85
85
  async restGet(relUrl, query = {}, attempt = 1) {
86
86
  query.fmt = 'json';
87
- await this.rateLimiter.limit();
87
+ const delay = await this.rateLimiter.limit();
88
+ debug(`Client side rate limiter activated: cool down for ${Math.round(delay / 100) / 10} s...`);
88
89
  const response = await got.get('ws/2' + relUrl, {
89
90
  ...this.options,
90
91
  searchParams: query,
@@ -95,225 +96,21 @@ export class MusicBrainzApi {
95
96
  });
96
97
  return response.body;
97
98
  }
98
- // -----------------------------------------------------------------------------------------------------------------
99
- // Lookup functions
100
- // -----------------------------------------------------------------------------------------------------------------
101
- /**
102
- * Generic lookup function
103
- * @param entity
104
- * @param mbid
105
- * @param inc
106
- */
107
- lookupEntity(entity, mbid, inc = []) {
99
+ lookup(entity, mbid, inc = []) {
108
100
  return this.restGet(`/${entity}/${mbid}`, { inc: inc.join(' ') });
109
101
  }
110
- /**
111
- * Lookup area
112
- * @param areaId Area MBID
113
- * @param inc Sub-queries
114
- */
115
- lookupArea(areaId, inc = []) {
116
- return this.lookupEntity('area', areaId, inc);
117
- }
118
- /**
119
- * Lookup artist
120
- * @param artistId Artist MBID
121
- * @param inc Sub-queries
122
- */
123
- lookupArtist(artistId, inc = []) {
124
- return this.lookupEntity('artist', artistId, inc);
125
- }
126
- /**
127
- * Lookup collection
128
- * @param collectionId Collection MBID
129
- * @param inc List of additional information to be included about the entity. Any of the entities directly linked to the entity can be included.
130
- */
131
- lookupCollection(collectionId, inc = []) {
132
- return this.lookupEntity('collection', collectionId, inc);
133
- }
134
- /**
135
- * Lookup instrument
136
- * @param artistId Instrument MBID
137
- * @param inc Sub-queries
138
- */
139
- lookupInstrument(instrumentId, inc = []) {
140
- return this.lookupEntity('instrument', instrumentId, inc);
141
- }
142
- /**
143
- * Lookup label
144
- * @param labelId Area MBID
145
- * @param inc Sub-queries
146
- */
147
- lookupLabel(labelId, inc = []) {
148
- return this.lookupEntity('label', labelId, inc);
149
- }
150
- /**
151
- * Lookup place
152
- * @param placeId Area MBID
153
- * @param inc Sub-queries
154
- */
155
- lookupPlace(placeId, inc = []) {
156
- return this.lookupEntity('place', placeId, inc);
157
- }
158
- /**
159
- * Lookup release
160
- * @param releaseId Release MBID
161
- * @param inc Include: artist-credits, labels, recordings, release-groups, media, discids, isrcs (with recordings)
162
- * ToDo: ['recordings', 'artists', 'artist-credits', 'isrcs', 'url-rels', 'release-groups']
163
- */
164
- lookupRelease(releaseId, inc = []) {
165
- return this.lookupEntity('release', releaseId, inc);
166
- }
167
- /**
168
- * Lookup release-group
169
- * @param releaseGroupId Release-group MBID
170
- * @param inc Include: ToDo
171
- */
172
- lookupReleaseGroup(releaseGroupId, inc = []) {
173
- return this.lookupEntity('release-group', releaseGroupId, inc);
174
- }
175
- /**
176
- * Lookup recording
177
- * @param recordingId Label MBID
178
- * @param inc Include: artist-credits, isrcs
179
- */
180
- lookupRecording(recordingId, inc = []) {
181
- return this.lookupEntity('recording', recordingId, inc);
182
- }
183
- /**
184
- * Lookup series
185
- * @param seriesId Series MBID
186
- */
187
- lookupSeries(seriesId) {
188
- return this.lookupEntity('series', seriesId);
189
- }
190
- /**
191
- * Lookup work
192
- * @param workId Work MBID
193
- */
194
- lookupWork(workId, inc = []) {
195
- return this.lookupEntity('work', workId, inc);
196
- }
197
- /**
198
- * Lookup URL
199
- * @param urlId URL MBID
200
- */
201
- lookupUrl(urlId, inc = []) {
202
- return this.lookupEntity('url', urlId, inc);
203
- }
204
- /**
205
- * Lookup Event
206
- * @param eventId Event MBID
207
- * @param eventIncludes List of sub-queries to enable
208
- */
209
- lookupEvent(eventId, eventIncludes = []) {
210
- return this.lookupEntity('event', eventId, eventIncludes);
211
- }
212
- // -----------------------------------------------------------------------------------------------------------------
213
- // Browse functions
214
- // -----------------------------------------------------------------------------------------------------------------
215
- // https://wiki.musicbrainz.org/MusicBrainz_API#Browse
216
- // https://wiki.musicbrainz.org/MusicBrainz_API#Linked_entities
217
- // For example: http://musicbrainz.org/ws/2/release?label=47e718e1-7ee4-460c-b1cc-1192a841c6e5&offset=12&limit=2
218
- /**
219
- * Generic browse function
220
- * https://wiki.musicbrainz.org/Development/JSON_Web_Service#Browse_Requests
221
- * @param entity MusicBrainz entity
222
- * @param query Query, like: {<entity>: <MBID:}
223
- */
224
- browseEntity(entity, query) {
102
+ browse(entity, query) {
225
103
  return this.restGet(`/${entity}`, query);
226
104
  }
227
- /**
228
- * Browse areas
229
- * @param query Query, like: {<entity>: <MBID:}
230
- */
231
- browseAreas(query) {
232
- return this.browseEntity('area', query);
233
- }
234
- /**
235
- * Browse artists
236
- * @param query Query, like: {<entity>: <MBID:}
237
- */
238
- browseArtists(query) {
239
- return this.browseEntity('artist', query);
240
- }
241
- /**
242
- * Browse collections
243
- * @param query Query, like: {<entity>: <MBID:}
244
- */
245
- browseCollections(query) {
246
- return this.browseEntity('collection', query);
247
- }
248
- /**
249
- * Browse events
250
- * @param query Query, like: {<entity>: <MBID:}
251
- */
252
- browseEvents(query) {
253
- return this.browseEntity('event', query);
254
- }
255
- /**
256
- * Browse instruments
257
- * @param query Query, like: {<entity>: <MBID:}
258
- */
259
- browseInstruments(query) {
260
- return this.browseEntity('instrument', query);
261
- }
262
- /**
263
- * Browse labels
264
- * @param query Query, like: {<entity>: <MBID:}
265
- */
266
- browseLabels(query) {
267
- return this.browseEntity('label', query);
268
- }
269
- /**
270
- * Browse places
271
- * @param query Query, like: {<entity>: <MBID:}
272
- */
273
- browsePlaces(query) {
274
- return this.browseEntity('place', query);
275
- }
276
- /**
277
- * Browse recordings
278
- * @param query Query, like: {<entity>: <MBID:}
279
- */
280
- browseRecordings(query) {
281
- return this.browseEntity('recording', query);
282
- }
283
- /**
284
- * Browse releases
285
- * @param query Query, like: {<entity>: <MBID:}
286
- */
287
- browseReleases(query) {
288
- return this.browseEntity('release', query);
289
- }
290
- /**
291
- * Browse release-groups
292
- * @param query Query, like: {<entity>: <MBID:}
293
- */
294
- browseReleaseGroups(query) {
295
- return this.browseEntity('release-group', query);
296
- }
297
- /**
298
- * Browse series
299
- * @param query Query, like: {<entity>: <MBID:}
300
- */
301
- browseSeries(query) {
302
- return this.browseEntity('series', query);
303
- }
304
- /**
305
- * Browse works
306
- * @param query Query, like: {<entity>: <MBID:}
307
- */
308
- browseWorks(query) {
309
- return this.browseEntity('work', query);
310
- }
311
- /**
312
- * Browse URLs
313
- * @param query Query, like: {<entity>: <MBID:}
314
- */
315
- browseUrls(query) {
316
- return this.browseEntity('url', query);
105
+ search(entity, query) {
106
+ const urlQuery = { ...query };
107
+ if (typeof query.query === 'object') {
108
+ urlQuery.query = makeAndQueryString(query.query);
109
+ }
110
+ if (Array.isArray(query.inc)) {
111
+ urlQuery.inc = urlQuery.inc.join(' ');
112
+ }
113
+ return this.restGet('/' + entity + '/', urlQuery);
317
114
  }
318
115
  // ---------------------------------------------------------------------------
319
116
  async postRecording(xmlMetadata) {
@@ -470,25 +267,6 @@ export class MusicBrainzApi {
470
267
  }
471
268
  }
472
269
  // -----------------------------------------------------------------------------------------------------------------
473
- // Query functions
474
- // -----------------------------------------------------------------------------------------------------------------
475
- /**
476
- * Search an entity using a search query
477
- * @param query e.g.: '" artist: Madonna, track: Like a virgin"' or object with search terms: {artist: Madonna}
478
- * @param entity e.g. 'recording'
479
- * @param query Arguments
480
- */
481
- search(entity, query) {
482
- const urlQuery = { ...query };
483
- if (typeof query.query === 'object') {
484
- urlQuery.query = makeAndQueryString(query.query);
485
- }
486
- if (Array.isArray(query.inc)) {
487
- urlQuery.inc = urlQuery.inc.join(' ');
488
- }
489
- return this.restGet('/' + entity + '/', urlQuery);
490
- }
491
- // -----------------------------------------------------------------------------------------------------------------
492
270
  // Helper functions
493
271
  // -----------------------------------------------------------------------------------------------------------------
494
272
  /**
@@ -505,21 +283,6 @@ export class MusicBrainzApi {
505
283
  text: 'https://open.spotify.com/track/' + spotifyId
506
284
  }, editNote);
507
285
  }
508
- searchArea(query) {
509
- return this.search('area', query);
510
- }
511
- searchArtist(query) {
512
- return this.search('artist', query);
513
- }
514
- searchRelease(query) {
515
- return this.search('release', query);
516
- }
517
- searchReleaseGroup(query) {
518
- return this.search('release-group', query);
519
- }
520
- searchUrl(query) {
521
- return this.search('url', query);
522
- }
523
286
  async getSession() {
524
287
  const response = await got.get('login', {
525
288
  ...this.options,
@@ -104,6 +104,7 @@ export interface IRelease extends IEntity {
104
104
  relations?: IRelation[];
105
105
  'artist-credit'?: IArtistCredit[];
106
106
  'release-group'?: IReleaseGroup;
107
+ collections?: ICollection[];
107
108
  }
108
109
  export interface IReleaseEvent {
109
110
  area?: IArea;
@@ -162,14 +163,16 @@ export interface IReleaseGroup extends IEntity {
162
163
  }[];
163
164
  releases?: IRelease[];
164
165
  }
166
+ export interface IAreaMatch extends IArea, IMatch {
167
+ }
165
168
  export interface IArtistMatch extends IArtist, IMatch {
166
169
  }
170
+ export interface IRecordingMatch extends IRecording, IMatch {
171
+ }
167
172
  export interface IReleaseGroupMatch extends IReleaseGroup, IMatch {
168
173
  }
169
174
  export interface IReleaseMatch extends IRelease, IMatch {
170
175
  }
171
- export interface IAreaMatch extends IArea, IMatch {
172
- }
173
176
  export interface ISearchResult {
174
177
  created: DateTimeFormat;
175
178
  count: number;
@@ -185,6 +188,10 @@ export interface IReleaseList extends ISearchResult {
185
188
  releases: IReleaseMatch[];
186
189
  'release-count': number;
187
190
  }
191
+ export interface IRecordingList extends ISearchResult {
192
+ recordings: IRecordingMatch[];
193
+ 'recordings-count': number;
194
+ }
188
195
  export interface IReleaseGroupList extends ISearchResult {
189
196
  'release-groups': IReleaseGroupMatch[];
190
197
  }
@@ -285,6 +292,7 @@ export interface ISearchQuery<I extends string> extends IPagination {
285
292
  */
286
293
  query?: string | IFormData;
287
294
  inc?: I[];
295
+ artist?: string;
288
296
  }
289
297
  /**
290
298
  * https://musicbrainz.org/doc/MusicBrainz_API#Browse
@@ -508,7 +516,7 @@ export interface IBrowseReleasesQuery extends IPagination {
508
516
  /**
509
517
  * Browse release-groups query <entity>: <MBID>
510
518
  */
511
- export interface IReleaseGroupsQuery extends IPagination {
519
+ export interface IBrowseReleaseGroupsQuery extends IPagination {
512
520
  artist?: string;
513
521
  collection?: string;
514
522
  release?: string;
@@ -586,12 +594,12 @@ export interface IBrowseReleaseGroupsResult {
586
594
  'release-group-offset': number;
587
595
  }
588
596
  export interface IBrowseSeriesResult {
589
- series: IReleaseGroupsQuery[];
597
+ series: IReleaseGroup[];
590
598
  'series-count': number;
591
599
  'series-offset': number;
592
600
  }
593
601
  export interface IBrowseWorksResult {
594
- works: IReleaseGroupsQuery[];
602
+ works: IReleaseGroup[];
595
603
  'work-count': number;
596
604
  'work-offset': number;
597
605
  }
@@ -10,5 +10,5 @@ export var LinkType;
10
10
  LinkType[LinkType["crowdfunding_page"] = 905] = "crowdfunding_page";
11
11
  LinkType[LinkType["other_databases"] = 306] = "other_databases";
12
12
  LinkType[LinkType["Allmusic"] = 285] = "Allmusic";
13
- })(LinkType = LinkType || (LinkType = {}));
13
+ })(LinkType || (LinkType = {}));
14
14
  //# sourceMappingURL=musicbrainz.types.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musicbrainz-api",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "MusicBrainz API client for reading and submitting metadata",
5
5
  "exports": "./lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -55,6 +55,7 @@
55
55
  "http-status-codes": "^2.1.4",
56
56
  "json-stringify-safe": "^5.0.1",
57
57
  "jsontoxml": "^1.0.1",
58
+ "rate-limit-threshold": "^0.1.5",
58
59
  "source-map-support": "^0.5.16",
59
60
  "tough-cookie": "^4.1.3",
60
61
  "uuid": "^9.0.0"
@@ -62,7 +63,7 @@
62
63
  "devDependencies": {
63
64
  "@types/chai": "^4.3.0",
64
65
  "@types/jsontoxml": "^1.0.5",
65
- "@types/mocha": "^9.0.0",
66
+ "@types/mocha": "^10.0.4",
66
67
  "@types/node": "^20.8.10",
67
68
  "@typescript-eslint/eslint-plugin": "^5.13.0",
68
69
  "@typescript-eslint/parser": "^5.13.0",
@@ -70,17 +71,16 @@
70
71
  "chai": "^4.2.0",
71
72
  "del-cli": "^5.0.0",
72
73
  "eslint": "^8.10.0",
73
- "eslint-config-prettier": "^8.4.0",
74
+ "eslint-config-prettier": "^9.0.0",
74
75
  "eslint-import-resolver-typescript": "^3.3.0",
75
76
  "eslint-plugin-import": "^2.25.4",
76
77
  "eslint-plugin-jsdoc": "^46.8.2",
77
78
  "eslint-plugin-node": "^11.1.0",
78
- "eslint-plugin-unicorn": "^46.0.0",
79
+ "eslint-plugin-unicorn": "^49.0.0",
79
80
  "mocha": "^10.1.0",
80
- "remark-cli": "^11.0.0",
81
+ "remark-cli": "^12.0.0",
81
82
  "remark-preset-lint-recommended": "^6.1.2",
82
83
  "ts-node": "^10.0.0",
83
- "tslint": "^6.1.1",
84
84
  "typescript": "^5.0.2"
85
85
  },
86
86
  "scripts": {
@@ -1,8 +0,0 @@
1
- export declare class RateLimiter {
2
- private maxCalls;
3
- static sleep(ms: number): Promise<void>;
4
- queue: number[];
5
- private readonly period;
6
- constructor(maxCalls: number, period: number);
7
- limit(): Promise<void>;
8
- }
@@ -1,30 +0,0 @@
1
- import Debug from 'debug';
2
- const debug = Debug('musicbrainz-api:rate-limiter');
3
- export class RateLimiter {
4
- static sleep(ms) {
5
- return new Promise(resolve => setTimeout(resolve, ms));
6
- }
7
- constructor(maxCalls, period) {
8
- this.maxCalls = maxCalls;
9
- this.queue = [];
10
- debug(`Rate limiter initialized with max ${maxCalls} calls in ${period} seconds.`);
11
- this.period = 1000 * period;
12
- }
13
- async limit() {
14
- let now = new Date().getTime();
15
- const t0 = now - (this.period);
16
- while (this.queue.length > 0 && this.queue[0] < t0) {
17
- this.queue.shift();
18
- }
19
- // debug(`Current rate is ${this.queue.length} per ${this.period / 1000} sec`);
20
- if (this.queue.length >= this.maxCalls) {
21
- const delay = this.queue[0] + this.period - now;
22
- debug(`Client side rate limiter activated: cool down for ${delay / 1000} s...`);
23
- return RateLimiter.sleep(delay);
24
- }
25
- now = new Date().getTime();
26
- this.queue.push(now);
27
- // const ratePerSec = 1000 * this.queue.length / (now - this.queue[0]);
28
- }
29
- }
30
- //# sourceMappingURL=rate-limiter.js.map