musicbrainz-api 0.10.0 → 0.10.2
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/.idea/jpa-buddy.xml +6 -0
- package/.idea/vcs.xml +5 -0
- package/README.md +12 -18
- package/lib/digest-auth.js +6 -6
- package/lib/musicbrainz-api.d.ts +17 -17
- package/lib/musicbrainz-api.js +17 -17
- package/lib/musicbrainz.types.d.ts +7 -7
- package/lib/rate-limiter.js +3 -3
- package/package.json +4 -4
package/.idea/vcs.xml
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<project version="4">
|
|
3
|
+
<component name="GitSharedSettings">
|
|
4
|
+
<option name="FORCE_PUSH_PROHIBITED_PATTERNS">
|
|
5
|
+
<list />
|
|
6
|
+
</option>
|
|
7
|
+
</component>
|
|
3
8
|
<component name="VcsDirectoryMappings">
|
|
4
9
|
<mapping directory="" vcs="Git" />
|
|
5
10
|
</component>
|
package/README.md
CHANGED
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
[](https://npmcharts.com/compare/musicbrainz-api)
|
|
4
4
|
[](https://coveralls.io/github/Borewit/musicbrainz-api?branch=master)
|
|
5
5
|
[](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
|
-
[](https://github.com/Borewit/musicbrainz-api/actions/workflows/codeql.yml)
|
|
7
7
|
[](https://snyk.io/test/github/Borewit/musicbrainz-api?targetFile=package.json)
|
|
8
|
-
[](https://lgtm.com/projects/g/Borewit/musicbrainz-api/alerts/)
|
|
9
8
|
[](https://deepscan.io/dashboard#view=project&tid=5165&pid=6991&bid=63373)
|
|
10
9
|
[](https://discord.gg/958xT5X)
|
|
11
10
|
|
|
@@ -94,13 +93,13 @@ Arguments:
|
|
|
94
93
|
* MBID [(MusicBrainz identifier)](https://wiki.musicbrainz.org/MusicBrainz_Identifier)
|
|
95
94
|
|
|
96
95
|
```js
|
|
97
|
-
const artist = await mbApi.lookupEntity('artist',
|
|
96
|
+
const artist = await mbApi.lookupEntity('artist', 'ab2528d9-719f-4261-8098-21849222a0f2');
|
|
98
97
|
```
|
|
99
98
|
|
|
100
99
|
### Lookup area
|
|
101
100
|
|
|
102
101
|
```js
|
|
103
|
-
const area = await mbApi.lookupArea(
|
|
102
|
+
const area = await mbApi.lookupArea('ab2528d9-719f-4261-8098-21849222a0f2');
|
|
104
103
|
```
|
|
105
104
|
|
|
106
105
|
### Lookup artist
|
|
@@ -108,7 +107,7 @@ const area = await mbApi.lookupArea({query: 'ab2528d9-719f-4261-8098-21849222a0f
|
|
|
108
107
|
Lookup an `artist` and include their `releases`, `release-groups` and `aliases`
|
|
109
108
|
|
|
110
109
|
```js
|
|
111
|
-
const artist = await mbApi.lookupArtist(
|
|
110
|
+
const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2');
|
|
112
111
|
```
|
|
113
112
|
|
|
114
113
|
### Lookup instrument
|
|
@@ -116,7 +115,7 @@ const artist = await mbApi.lookupArtist({query: 'ab2528d9-719f-4261-8098-2184922
|
|
|
116
115
|
Lookup an instrument
|
|
117
116
|
|
|
118
117
|
```js
|
|
119
|
-
const
|
|
118
|
+
const instrument = await mbApi.lookupInstrument('b3eac5f9-7859-4416-ac39-7154e2e8d348');
|
|
120
119
|
```
|
|
121
120
|
|
|
122
121
|
### Lookup label
|
|
@@ -124,13 +123,13 @@ const artist = await mbApi.lookupInstrument({query: 'b3eac5f9-7859-4416-ac39-715
|
|
|
124
123
|
Lookup a label
|
|
125
124
|
|
|
126
125
|
```js
|
|
127
|
-
const
|
|
126
|
+
const label = await mbApi.lookupLabel('25dda9f9-f069-4898-82f0-59330a106c7f');
|
|
128
127
|
```
|
|
129
128
|
|
|
130
129
|
### Lookup place
|
|
131
130
|
|
|
132
131
|
```js
|
|
133
|
-
const
|
|
132
|
+
const place = await mbApi.lookupPlace('e6cfb74d-d69b-44c3-b890-1b3f509816e4');
|
|
134
133
|
```
|
|
135
134
|
|
|
136
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:
|
|
@@ -142,32 +141,27 @@ const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2',
|
|
|
142
141
|
|
|
143
142
|
The second argument can be used to pass [subqueries](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Subqueries):
|
|
144
143
|
```js
|
|
145
|
-
const
|
|
144
|
+
const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c', ['artists', 'url-rels']);
|
|
146
145
|
```
|
|
147
146
|
|
|
148
147
|
### Lookup release
|
|
149
148
|
```js
|
|
150
|
-
const release = await mbApi.lookupRelease(
|
|
149
|
+
const release = await mbApi.lookupRelease('976e0677-a480-4a5e-a177-6a86c1900bbf', ['artists', 'url-rels']);
|
|
151
150
|
```
|
|
152
151
|
|
|
153
152
|
### Lookup release-group
|
|
154
153
|
```js
|
|
155
|
-
const releaseGroup = await mbApi.lookupReleaseGroup(
|
|
154
|
+
const releaseGroup = await mbApi.lookupReleaseGroup('19099ea5-3600-4154-b482-2ec68815883e');
|
|
156
155
|
```
|
|
157
156
|
|
|
158
157
|
### Lookup work
|
|
159
158
|
```js
|
|
160
|
-
const work = await mbApi.lookupWork(
|
|
159
|
+
const work = await mbApi.lookupWork('b2aa02f4-6c95-43be-a426-aedb9f9a3805');
|
|
161
160
|
```
|
|
162
161
|
|
|
163
162
|
### Lookup URL
|
|
164
163
|
```js
|
|
165
|
-
const url = await mbApi.lookupUrl(
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### Lookup URL
|
|
169
|
-
```js
|
|
170
|
-
const url = await mbApi.lookupUrl({query: 'c69556a6-7ded-4c54-809c-afb45a1abe7d'});
|
|
164
|
+
const url = await mbApi.lookupUrl('c69556a6-7ded-4c54-809c-afb45a1abe7d');
|
|
171
165
|
```
|
|
172
166
|
|
|
173
167
|
## Browse entities
|
package/lib/digest-auth.js
CHANGED
|
@@ -7,12 +7,6 @@ function md5(str) {
|
|
|
7
7
|
return crypto.createHash('md5').update(str).digest('hex'); // lgtm [js/insufficient-password-hash]
|
|
8
8
|
}
|
|
9
9
|
class DigestAuth {
|
|
10
|
-
constructor(credentials) {
|
|
11
|
-
this.credentials = credentials;
|
|
12
|
-
this.hasAuth = false;
|
|
13
|
-
this.sentAuth = false;
|
|
14
|
-
this.bearerToken = null;
|
|
15
|
-
}
|
|
16
10
|
/**
|
|
17
11
|
* RFC 2617: handle both MD5 and MD5-sess algorithms.
|
|
18
12
|
*
|
|
@@ -25,6 +19,12 @@ class DigestAuth {
|
|
|
25
19
|
const ha1 = md5(user + ':' + realm + ':' + pass); // lgtm [js/insufficient-password-hash]
|
|
26
20
|
return algorithm && algorithm.toLowerCase() === 'md5-sess' ? md5(ha1 + ':' + nonce + ':' + cnonce) : ha1;
|
|
27
21
|
}
|
|
22
|
+
constructor(credentials) {
|
|
23
|
+
this.credentials = credentials;
|
|
24
|
+
this.hasAuth = false;
|
|
25
|
+
this.sentAuth = false;
|
|
26
|
+
this.bearerToken = null;
|
|
27
|
+
}
|
|
28
28
|
digest(method, path, authHeader) {
|
|
29
29
|
// TODO: More complete implementation of RFC 2617.
|
|
30
30
|
// - support qop="auth-int" only
|
package/lib/musicbrainz-api.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ export { XmlRecording } from './xml/xml-recording';
|
|
|
5
5
|
import { XmlMetadata } from './xml/xml-metadata';
|
|
6
6
|
import * as mb from './musicbrainz.types';
|
|
7
7
|
export * from './musicbrainz.types';
|
|
8
|
-
export
|
|
9
|
-
export
|
|
8
|
+
export type RelationsIncludes = 'area-rels' | 'artist-rels' | 'event-rels' | 'instrument-rels' | 'label-rels' | 'place-rels' | 'recording-rels' | 'release-rels' | 'release-group-rels' | 'series-rels' | 'url-rels' | 'work-rels';
|
|
9
|
+
export type SubQueryIncludes =
|
|
10
10
|
/**
|
|
11
11
|
* include discids for all media in the releases
|
|
12
12
|
*/
|
|
@@ -27,21 +27,21 @@ export declare type SubQueryIncludes =
|
|
|
27
27
|
* include only those releases where the artist appears on one of the tracks, only valid on artists in combination with `releases`
|
|
28
28
|
*/
|
|
29
29
|
| 'various-artists';
|
|
30
|
-
export
|
|
31
|
-
export
|
|
32
|
-
export
|
|
33
|
-
export
|
|
34
|
-
export
|
|
35
|
-
export
|
|
36
|
-
export
|
|
37
|
-
export
|
|
38
|
-
export
|
|
39
|
-
export
|
|
40
|
-
export
|
|
41
|
-
export
|
|
42
|
-
export
|
|
43
|
-
export
|
|
44
|
-
export
|
|
30
|
+
export type MiscIncludes = 'aliases' | 'annotation' | 'tags' | 'genres' | 'ratings' | 'media';
|
|
31
|
+
export type AreaIncludes = MiscIncludes | RelationsIncludes;
|
|
32
|
+
export type ArtistIncludes = MiscIncludes | RelationsIncludes | 'recordings' | 'releases' | 'release-groups' | 'works';
|
|
33
|
+
export type CollectionIncludes = MiscIncludes | RelationsIncludes | 'user-collections';
|
|
34
|
+
export type EventIncludes = MiscIncludes | RelationsIncludes;
|
|
35
|
+
export type GenreIncludes = MiscIncludes;
|
|
36
|
+
export type InstrumentIncludes = MiscIncludes | RelationsIncludes;
|
|
37
|
+
export type LabelIncludes = MiscIncludes | RelationsIncludes | 'releases';
|
|
38
|
+
export type PlaceIncludes = MiscIncludes | RelationsIncludes;
|
|
39
|
+
export type RecordingIncludes = MiscIncludes | RelationsIncludes | SubQueryIncludes | 'artists' | 'releases' | 'isrcs';
|
|
40
|
+
export type ReleasesIncludes = MiscIncludes | SubQueryIncludes | RelationsIncludes | 'artists' | 'collections' | 'labels' | 'recordings' | 'release-groups';
|
|
41
|
+
export type ReleaseGroupIncludes = MiscIncludes | SubQueryIncludes | RelationsIncludes | 'artists' | 'releases';
|
|
42
|
+
export type SeriesIncludes = MiscIncludes | RelationsIncludes;
|
|
43
|
+
export type WorkIncludes = MiscIncludes | RelationsIncludes;
|
|
44
|
+
export type UrlIncludes = RelationsIncludes;
|
|
45
45
|
export interface IFormData {
|
|
46
46
|
[key: string]: string | number;
|
|
47
47
|
}
|
package/lib/musicbrainz-api.js
CHANGED
|
@@ -37,23 +37,6 @@ const util_1 = require("util");
|
|
|
37
37
|
const retries = 3;
|
|
38
38
|
const debug = Debug('musicbrainz-api');
|
|
39
39
|
class MusicBrainzApi {
|
|
40
|
-
constructor(_config) {
|
|
41
|
-
this.config = {
|
|
42
|
-
baseUrl: 'https://musicbrainz.org'
|
|
43
|
-
};
|
|
44
|
-
Object.assign(this.config, _config);
|
|
45
|
-
const cookieJar = new tough.CookieJar();
|
|
46
|
-
this.getCookies = (0, util_1.promisify)(cookieJar.getCookies.bind(cookieJar));
|
|
47
|
-
this.options = {
|
|
48
|
-
prefixUrl: this.config.baseUrl,
|
|
49
|
-
timeout: 20 * 1000,
|
|
50
|
-
headers: {
|
|
51
|
-
'User-Agent': `${this.config.appName}/${this.config.appVersion} ( ${this.config.appContactInfo} )`
|
|
52
|
-
},
|
|
53
|
-
cookieJar
|
|
54
|
-
};
|
|
55
|
-
this.rateLimiter = new rate_limiter_1.RateLimiter(60, 50);
|
|
56
|
-
}
|
|
57
40
|
static escapeText(text) {
|
|
58
41
|
let str = '';
|
|
59
42
|
for (const chr of text) {
|
|
@@ -101,6 +84,23 @@ class MusicBrainzApi {
|
|
|
101
84
|
}
|
|
102
85
|
}
|
|
103
86
|
}
|
|
87
|
+
constructor(_config) {
|
|
88
|
+
this.config = {
|
|
89
|
+
baseUrl: 'https://musicbrainz.org'
|
|
90
|
+
};
|
|
91
|
+
Object.assign(this.config, _config);
|
|
92
|
+
const cookieJar = new tough.CookieJar();
|
|
93
|
+
this.getCookies = (0, util_1.promisify)(cookieJar.getCookies.bind(cookieJar));
|
|
94
|
+
this.options = {
|
|
95
|
+
prefixUrl: this.config.baseUrl,
|
|
96
|
+
timeout: 20 * 1000,
|
|
97
|
+
headers: {
|
|
98
|
+
'User-Agent': `${this.config.appName}/${this.config.appVersion} ( ${this.config.appContactInfo} )`
|
|
99
|
+
},
|
|
100
|
+
cookieJar
|
|
101
|
+
};
|
|
102
|
+
this.rateLimiter = new rate_limiter_1.RateLimiter(60, 50);
|
|
103
|
+
}
|
|
104
104
|
async restGet(relUrl, query = {}, attempt = 1) {
|
|
105
105
|
query.fmt = 'json';
|
|
106
106
|
let response;
|
|
@@ -39,7 +39,7 @@ export interface IArtist extends IEntity {
|
|
|
39
39
|
ipis?: any[];
|
|
40
40
|
isnis?: string[];
|
|
41
41
|
aliases?: IAlias[];
|
|
42
|
-
gender?:
|
|
42
|
+
gender?: string;
|
|
43
43
|
type?: string;
|
|
44
44
|
area?: IArea;
|
|
45
45
|
begin_area?: IArea;
|
|
@@ -81,7 +81,7 @@ export interface IInstrument extends IEntity {
|
|
|
81
81
|
type: string;
|
|
82
82
|
description: string;
|
|
83
83
|
}
|
|
84
|
-
export
|
|
84
|
+
export type ReleaseQuality = 'normal';
|
|
85
85
|
export interface IRelease extends IEntity {
|
|
86
86
|
title: string;
|
|
87
87
|
'text-representation': {
|
|
@@ -109,7 +109,7 @@ export interface IReleaseEvent {
|
|
|
109
109
|
area?: IArea;
|
|
110
110
|
date?: string;
|
|
111
111
|
}
|
|
112
|
-
export
|
|
112
|
+
export type MediaFormatType = 'Digital Media';
|
|
113
113
|
export interface IRecording extends IEntity {
|
|
114
114
|
video: boolean;
|
|
115
115
|
length: number;
|
|
@@ -185,7 +185,7 @@ export interface IReleaseGroupList extends ISearchResult {
|
|
|
185
185
|
export interface IUrlList extends ISearchResult {
|
|
186
186
|
urls: IUrlMatch[];
|
|
187
187
|
}
|
|
188
|
-
export
|
|
188
|
+
export type RelationDirection = 'backward' | 'forward';
|
|
189
189
|
export interface IRelation {
|
|
190
190
|
'attribute-ids': any;
|
|
191
191
|
direction: RelationDirection;
|
|
@@ -237,8 +237,8 @@ export interface IReleaseSearchResult extends ISearchResult {
|
|
|
237
237
|
/**
|
|
238
238
|
* https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2#Subqueries
|
|
239
239
|
*/
|
|
240
|
-
export
|
|
241
|
-
export
|
|
240
|
+
export type EntityType = 'area' | 'artist' | 'collection' | 'event' | 'instrument' | 'label' | 'place' | 'recording' | 'release' | 'release-group' | 'series' | 'work' | 'url';
|
|
241
|
+
export type Relationships = 'area-rels' | 'artist-rels' | 'event-rels' | 'instrument-rels' | 'label-rels' | 'place-rels' | 'recording-rels' | 'release-rels' | 'release-group-rels' | 'series-rels' | 'url-rels' | 'work-rels';
|
|
242
242
|
export declare enum LinkType {
|
|
243
243
|
license = 302,
|
|
244
244
|
production = 256,
|
|
@@ -569,7 +569,7 @@ export interface IBrowseReleasesResult {
|
|
|
569
569
|
'release-offset': number;
|
|
570
570
|
}
|
|
571
571
|
export interface IBrowseReleaseGroupsResult {
|
|
572
|
-
'release-groups':
|
|
572
|
+
'release-groups': IReleaseGroup[];
|
|
573
573
|
'release-group-count': number;
|
|
574
574
|
'release-group-offset': number;
|
|
575
575
|
}
|
package/lib/rate-limiter.js
CHANGED
|
@@ -4,14 +4,14 @@ exports.RateLimiter = void 0;
|
|
|
4
4
|
const Debug = require("debug");
|
|
5
5
|
const debug = Debug('musicbrainz-api:rate-limiter');
|
|
6
6
|
class RateLimiter {
|
|
7
|
+
static sleep(ms) {
|
|
8
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
9
|
+
}
|
|
7
10
|
constructor(period, maxCalls) {
|
|
8
11
|
this.maxCalls = maxCalls;
|
|
9
12
|
this.queue = [];
|
|
10
13
|
this.period = 1000 * period;
|
|
11
14
|
}
|
|
12
|
-
static sleep(ms) {
|
|
13
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
14
|
-
}
|
|
15
15
|
async limit() {
|
|
16
16
|
let now = new Date().getTime();
|
|
17
17
|
const t0 = now - (this.period);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "musicbrainz-api",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "MusicBrainz API client for reading and submitting metadata",
|
|
5
5
|
"main": "lib/musicbrainz-api",
|
|
6
6
|
"types": "lib/musicbrainz-api",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@types/caseless": "^0.12.1",
|
|
39
39
|
"@types/request-promise-native": "^1.0.17",
|
|
40
|
-
"@types/uuid": "^
|
|
40
|
+
"@types/uuid": "^9.0.0",
|
|
41
41
|
"caseless": "^0.12.0",
|
|
42
42
|
"debug": "^4.1.1",
|
|
43
43
|
"got": "^11.8.5",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"jsontoxml": "^1.0.1",
|
|
47
47
|
"source-map-support": "^0.5.16",
|
|
48
48
|
"tough-cookie": "^4.0.0",
|
|
49
|
-
"uuid": "^
|
|
49
|
+
"uuid": "^9.0.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/chai": "^4.3.0",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"eslint-plugin-import": "^2.25.4",
|
|
63
63
|
"eslint-plugin-jsdoc": "^39.3.3",
|
|
64
64
|
"eslint-plugin-node": "^11.1.0",
|
|
65
|
-
"eslint-plugin-unicorn": "^
|
|
65
|
+
"eslint-plugin-unicorn": "^45.0.0",
|
|
66
66
|
"mocha": "^9.0.1",
|
|
67
67
|
"nyc": "^15.0.0",
|
|
68
68
|
"remark-cli": "^11.0.0",
|