musicbrainz-api 0.5.2 → 0.7.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.
Files changed (35) hide show
  1. package/.idea/$CACHE_FILE$ +6 -0
  2. package/.idea/$PRODUCT_WORKSPACE_FILE$ +19 -0
  3. package/.idea/checkstyle-idea.xml +16 -0
  4. package/.idea/codeStyles/Project.xml +38 -0
  5. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  6. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  7. package/.idea/misc.xml +6 -0
  8. package/.idea/modules.xml +8 -0
  9. package/.idea/shelf/Uncommitted_changes_before_Update_at_6-1-2022_11_38_[Default_Changelist]/shelved.patch +58 -0
  10. package/.idea/shelf/Uncommitted_changes_before_Update_at_6-1-2022_11_38__Default_Changelist_.xml +4 -0
  11. package/.idea/shelf/Uncommitted_changes_before_rebase_[Default_Changelist]/shelved.patch +738 -0
  12. package/.idea/shelf/Uncommitted_changes_before_rebase_[Default_Changelist]1/shelved.patch +0 -0
  13. package/.idea/shelf/Uncommitted_changes_before_rebase__Default_Changelist_.xml +4 -0
  14. package/.idea/vcs.xml +6 -0
  15. package/.idea/workspace.xml +722 -0
  16. package/README.md +290 -287
  17. package/etc/config.js +32 -0
  18. package/lib/digest-auth.d.ts +21 -21
  19. package/lib/digest-auth.js +87 -86
  20. package/lib/musicbrainz-api.d.ts +156 -140
  21. package/lib/musicbrainz-api.js +390 -372
  22. package/lib/musicbrainz.types.d.ts +379 -252
  23. package/lib/musicbrainz.types.js +16 -15
  24. package/lib/rate-limiter.d.ts +8 -8
  25. package/lib/rate-limiter.js +31 -30
  26. package/lib/xml/xml-isrc-list.d.ts +17 -17
  27. package/lib/xml/xml-isrc-list.js +22 -21
  28. package/lib/xml/xml-isrc.d.ts +10 -10
  29. package/lib/xml/xml-isrc.js +17 -16
  30. package/lib/xml/xml-metadata.d.ts +6 -6
  31. package/lib/xml/xml-metadata.js +29 -28
  32. package/lib/xml/xml-recording.d.ts +24 -24
  33. package/lib/xml/xml-recording.js +20 -19
  34. package/package.json +98 -99
  35. package/yarn-error.log +3608 -0
@@ -1,21 +1,21 @@
1
- export interface ICredentials {
2
- username: string;
3
- password: string;
4
- }
5
- export declare class DigestAuth {
6
- private credentials;
7
- /**
8
- * RFC 2617: handle both MD5 and MD5-sess algorithms.
9
- *
10
- * If the algorithm directive's value is "MD5" or unspecified, then HA1 is
11
- * HA1=MD5(username:realm:password)
12
- * If the algorithm directive's value is "MD5-sess", then HA1 is
13
- * HA1=MD5(MD5(username:realm:password):nonce:cnonce)
14
- */
15
- static ha1Compute(algorithm: any, user: any, realm: any, pass: any, nonce: any, cnonce: any): string;
16
- hasAuth: boolean;
17
- sentAuth: boolean;
18
- bearerToken: string;
19
- constructor(credentials: ICredentials);
20
- digest(method: string, path: string, authHeader: string): string;
21
- }
1
+ export interface ICredentials {
2
+ username: string;
3
+ password: string;
4
+ }
5
+ export declare class DigestAuth {
6
+ private credentials;
7
+ /**
8
+ * RFC 2617: handle both MD5 and MD5-sess algorithms.
9
+ *
10
+ * If the algorithm directive's value is "MD5" or unspecified, then HA1 is
11
+ * HA1=MD5(username:realm:password)
12
+ * If the algorithm directive's value is "MD5-sess", then HA1 is
13
+ * HA1=MD5(MD5(username:realm:password):nonce:cnonce)
14
+ */
15
+ static ha1Compute(algorithm: any, user: any, realm: any, pass: any, nonce: any, cnonce: any): string;
16
+ hasAuth: boolean;
17
+ sentAuth: boolean;
18
+ bearerToken: string;
19
+ constructor(credentials: ICredentials);
20
+ digest(method: string, path: string, authHeader: string): string;
21
+ }
@@ -1,87 +1,88 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const uuid = require("uuid/v4");
4
- const crypto = require("crypto");
5
- function md5(str) {
6
- return crypto.createHash('md5').update(str).digest('hex');
7
- }
8
- class DigestAuth {
9
- constructor(credentials) {
10
- this.credentials = credentials;
11
- this.hasAuth = false;
12
- this.sentAuth = false;
13
- this.bearerToken = null;
14
- }
15
- /**
16
- * RFC 2617: handle both MD5 and MD5-sess algorithms.
17
- *
18
- * If the algorithm directive's value is "MD5" or unspecified, then HA1 is
19
- * HA1=MD5(username:realm:password)
20
- * If the algorithm directive's value is "MD5-sess", then HA1 is
21
- * HA1=MD5(MD5(username:realm:password):nonce:cnonce)
22
- */
23
- static ha1Compute(algorithm, user, realm, pass, nonce, cnonce) {
24
- const ha1 = md5(user + ':' + realm + ':' + pass);
25
- if (algorithm && algorithm.toLowerCase() === 'md5-sess') {
26
- return md5(ha1 + ':' + nonce + ':' + cnonce);
27
- }
28
- else {
29
- return ha1;
30
- }
31
- }
32
- digest(method, path, authHeader) {
33
- // TODO: More complete implementation of RFC 2617.
34
- // - support qop="auth-int" only
35
- // - handle Authentication-Info (not necessarily?)
36
- // - check challenge.stale (not necessarily?)
37
- // - increase nc (not necessarily?)
38
- // For reference:
39
- // http://tools.ietf.org/html/rfc2617#section-3
40
- // https://github.com/bagder/curl/blob/master/lib/http_digest.c
41
- const challenge = {};
42
- const re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi;
43
- while (true) {
44
- const match = re.exec(authHeader);
45
- if (!match) {
46
- break;
47
- }
48
- challenge[match[1]] = match[2] || match[3];
49
- }
50
- const qop = /(^|,)\s*auth\s*($|,)/.test(challenge.qop) && 'auth';
51
- const nc = qop && '00000001';
52
- const cnonce = qop && uuid().replace(/-/g, '');
53
- const ha1 = DigestAuth.ha1Compute(challenge.algorithm, this.credentials.username, challenge.realm, this.credentials.password, challenge.nonce, cnonce);
54
- const ha2 = md5(method + ':' + path);
55
- const digestResponse = qop
56
- ? md5(ha1 + ':' + challenge.nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2)
57
- : md5(ha1 + ':' + challenge.nonce + ':' + ha2);
58
- const authValues = {
59
- username: this.credentials.username,
60
- realm: challenge.realm,
61
- nonce: challenge.nonce,
62
- uri: path,
63
- qop,
64
- response: digestResponse,
65
- nc,
66
- cnonce,
67
- algorithm: challenge.algorithm,
68
- opaque: challenge.opaque
69
- };
70
- const parts = [];
71
- for (const k in authValues) {
72
- if (authValues[k]) {
73
- if (k === 'qop' || k === 'nc' || k === 'algorithm') {
74
- parts.push(k + '=' + authValues[k]);
75
- }
76
- else {
77
- parts.push(k + '="' + authValues[k] + '"');
78
- }
79
- }
80
- }
81
- authHeader = 'Digest ' + parts.join(', ');
82
- this.sentAuth = true;
83
- return authHeader;
84
- }
85
- }
86
- exports.DigestAuth = DigestAuth;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DigestAuth = void 0;
4
+ const uuid_1 = require("uuid");
5
+ const crypto = require("crypto");
6
+ function md5(str) {
7
+ return crypto.createHash('md5').update(str).digest('hex'); // lgtm [js/insufficient-password-hash]
8
+ }
9
+ class DigestAuth {
10
+ constructor(credentials) {
11
+ this.credentials = credentials;
12
+ this.hasAuth = false;
13
+ this.sentAuth = false;
14
+ this.bearerToken = null;
15
+ }
16
+ /**
17
+ * RFC 2617: handle both MD5 and MD5-sess algorithms.
18
+ *
19
+ * If the algorithm directive's value is "MD5" or unspecified, then HA1 is
20
+ * HA1=MD5(username:realm:password)
21
+ * If the algorithm directive's value is "MD5-sess", then HA1 is
22
+ * HA1=MD5(MD5(username:realm:password):nonce:cnonce)
23
+ */
24
+ static ha1Compute(algorithm, user, realm, pass, nonce, cnonce) {
25
+ const ha1 = md5(user + ':' + realm + ':' + pass); // lgtm [js/insufficient-password-hash]
26
+ if (algorithm && algorithm.toLowerCase() === 'md5-sess') {
27
+ return md5(ha1 + ':' + nonce + ':' + cnonce);
28
+ }
29
+ else {
30
+ return ha1;
31
+ }
32
+ }
33
+ digest(method, path, authHeader) {
34
+ // TODO: More complete implementation of RFC 2617.
35
+ // - support qop="auth-int" only
36
+ // - handle Authentication-Info (not necessarily?)
37
+ // - check challenge.stale (not necessarily?)
38
+ // - increase nc (not necessarily?)
39
+ // For reference:
40
+ // http://tools.ietf.org/html/rfc2617#section-3
41
+ // https://github.com/bagder/curl/blob/master/lib/http_digest.c
42
+ const challenge = {};
43
+ const re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi;
44
+ while (true) {
45
+ const match = re.exec(authHeader);
46
+ if (!match) {
47
+ break;
48
+ }
49
+ challenge[match[1]] = match[2] || match[3];
50
+ }
51
+ const qop = /(^|,)\s*auth\s*($|,)/.test(challenge.qop) && 'auth';
52
+ const nc = qop && '00000001';
53
+ const cnonce = qop && (0, uuid_1.v4)().replace(/-/g, '');
54
+ const ha1 = DigestAuth.ha1Compute(challenge.algorithm, this.credentials.username, challenge.realm, this.credentials.password, challenge.nonce, cnonce);
55
+ const ha2 = md5(method + ':' + path); // lgtm [js/insufficient-password-hash]
56
+ const digestResponse = qop
57
+ ? md5(ha1 + ':' + challenge.nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2) // lgtm [js/insufficient-password-hash]
58
+ : md5(ha1 + ':' + challenge.nonce + ':' + ha2); // lgtm [js/insufficient-password-hash]
59
+ const authValues = {
60
+ username: this.credentials.username,
61
+ realm: challenge.realm,
62
+ nonce: challenge.nonce,
63
+ uri: path,
64
+ qop,
65
+ response: digestResponse,
66
+ nc,
67
+ cnonce,
68
+ algorithm: challenge.algorithm,
69
+ opaque: challenge.opaque
70
+ };
71
+ const parts = [];
72
+ for (const k in authValues) {
73
+ if (authValues[k]) {
74
+ if (k === 'qop' || k === 'nc' || k === 'algorithm') {
75
+ parts.push(k + '=' + authValues[k]);
76
+ }
77
+ else {
78
+ parts.push(k + '="' + authValues[k] + '"');
79
+ }
80
+ }
81
+ }
82
+ authHeader = 'Digest ' + parts.join(', ');
83
+ this.sentAuth = true;
84
+ return authHeader;
85
+ }
86
+ }
87
+ exports.DigestAuth = DigestAuth;
87
88
  //# sourceMappingURL=digest-auth.js.map
@@ -1,140 +1,156 @@
1
- export { XmlMetadata } from './xml/xml-metadata';
2
- export { XmlIsrc } from './xml/xml-isrc';
3
- export { XmlIsrcList } from './xml/xml-isrc-list';
4
- export { XmlRecording } from './xml/xml-recording';
5
- import { XmlMetadata } from './xml/xml-metadata';
6
- import * as mb from './musicbrainz.types';
7
- export * from './musicbrainz.types';
8
- /**
9
- * https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2#Subqueries
10
- */
11
- export declare type Includes = 'artists' | 'releases' | 'recordings' | 'artists' | 'artist-credits' | 'isrcs' | 'url-rels' | 'release-groups' | 'aliases' | 'discids' | 'annotation' | 'media' | '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';
12
- export interface IFormData {
13
- [key: string]: string | number;
14
- }
15
- export interface IMusicBrainzConfig {
16
- botAccount?: {
17
- username: string;
18
- password: string;
19
- };
20
- baseUrl?: string;
21
- appName?: string;
22
- appVersion?: string;
23
- /**
24
- * HTTP Proxy
25
- */
26
- proxy?: string;
27
- /**
28
- * User e-mail address or application URL
29
- */
30
- appContactInfo?: string;
31
- }
32
- export declare class MusicBrainzApi {
33
- private static escapeText;
34
- readonly config: IMusicBrainzConfig;
35
- private request;
36
- private rateLimiter;
37
- private readonly cookieJar;
38
- constructor(_config?: IMusicBrainzConfig);
39
- restGet<T>(relUrl: string, query?: {
40
- [key: string]: any;
41
- }, attempt?: number): Promise<T>;
42
- /**
43
- * Generic lookup function
44
- * @param entity
45
- * @param mbid
46
- * @param inc
47
- */
48
- getEntity<T>(entity: mb.EntityType, mbid: string, inc?: Includes[]): Promise<T>;
49
- /**
50
- * Lookup area
51
- * @param areaId Area MBID
52
- * @param inc Sub-queries
53
- */
54
- getArea(areaId: string, inc?: Includes[]): Promise<mb.IArea>;
55
- /**
56
- * Lookup artist
57
- * @param artistId Artist MBID
58
- * @param inc Sub-queries
59
- */
60
- getArtist(artistId: string, inc?: Includes[]): Promise<mb.IArtist>;
61
- /**
62
- * Lookup release
63
- * @param releaseId Release MBID
64
- * @param inc Include: artist-credits, labels, recordings, release-groups, media, discids, isrcs (with recordings)
65
- * ToDo: ['recordings', 'artists', 'artist-credits', 'isrcs', 'url-rels', 'release-groups']
66
- */
67
- getRelease(releaseId: string, inc?: Includes[]): Promise<mb.IRelease>;
68
- /**
69
- * Lookup release-group
70
- * @param releaseGroupId Release-group MBID
71
- * @param inc Include: ToDo
72
- */
73
- getReleaseGroup(releaseGroupId: string, inc?: Includes[]): Promise<mb.IReleaseGroup>;
74
- /**
75
- * Lookup work
76
- * @param workId Work MBID
77
- */
78
- getWork(workId: string): Promise<mb.IWork>;
79
- /**
80
- * Lookup label
81
- * @param labelId Label MBID
82
- */
83
- getLabel(labelId: string): Promise<mb.ILabel>;
84
- /**
85
- * Lookup recording
86
- * @param recordingId Label MBID
87
- * @param inc Include: artist-credits, isrcs
88
- */
89
- getRecording(recordingId: string, inc?: Array<'artists' | 'artist-credits' | 'releases' | 'isrcs' | 'url-rels'>): Promise<mb.IRecording>;
90
- postRecording(xmlMetadata: XmlMetadata): Promise<void>;
91
- post(entity: mb.EntityType, xmlMetadata: XmlMetadata): Promise<void>;
92
- login(): Promise<boolean>;
93
- /**
94
- * Submit entity
95
- * @param entity Entity type e.g. 'recording'
96
- * @param mbid
97
- * @param formData
98
- */
99
- editEntity(entity: mb.EntityType, mbid: string, formData: IFormData): Promise<void>;
100
- /**
101
- * Set URL to recording
102
- * @param recording Recording to update
103
- * @param url2add URL to add to the recording
104
- * @param editNote Edit note
105
- */
106
- addUrlToRecording(recording: mb.IRecording, url2add: {
107
- linkTypeId: mb.LinkType;
108
- text: string;
109
- }, editNote?: string): Promise<void>;
110
- /**
111
- * Add ISRC to recording
112
- * @param recording Recording to update
113
- * @param isrc ISRC code to add
114
- * @param editNote Edit note
115
- */
116
- addIsrc(recording: mb.IRecording, isrc: string, editNote?: string): Promise<void>;
117
- /**
118
- * Search an entity using a search query
119
- * @param query e.g.: '" artist: Madonna, track: Like a virgin"' or object with search terms: {artist: Madonna}
120
- * @param entity e.g. 'recording'
121
- * @param offset
122
- * @param limit
123
- */
124
- search<T extends mb.ISearchResult>(entity: mb.EntityType, query: string | IFormData, offset?: number, limit?: number): Promise<T>;
125
- /**
126
- * Add Spotify-ID to MusicBrainz recording.
127
- * This function will automatically lookup the recording title, which is required to submit the recording URL
128
- * @param recording MBID of the recording
129
- * @param spotifyId Spotify ID
130
- * @param editNote Comment to add.
131
- */
132
- addSpotifyIdToRecording(recording: mb.IRecording, spotifyId: string, editNote: string): Promise<void>;
133
- searchArtist(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IArtistList>;
134
- searchRelease(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IReleaseList>;
135
- searchReleaseGroup(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IReleaseGroupList>;
136
- searchArea(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IAreaList>;
137
- searchUrl(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IUrlList>;
138
- private getCookies;
139
- }
140
- export declare function makeAndQueryString(keyValuePairs: IFormData): string;
1
+ export { XmlMetadata } from './xml/xml-metadata';
2
+ export { XmlIsrc } from './xml/xml-isrc';
3
+ export { XmlIsrcList } from './xml/xml-isrc-list';
4
+ export { XmlRecording } from './xml/xml-recording';
5
+ import { XmlMetadata } from './xml/xml-metadata';
6
+ import * as mb from './musicbrainz.types';
7
+ export * from './musicbrainz.types';
8
+ /**
9
+ * https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2#Subqueries
10
+ */
11
+ export declare type Includes = 'artists' | 'releases' | 'recordings' | 'artist-credits' | 'isrcs' | 'url-rels' | 'release-groups' | 'aliases' | 'discids' | 'annotation' | 'media' | 'area-rels' | 'artist-rels' | 'event-rels' | 'instrument-rels' | 'label-rels' | 'place-rels' | 'recording-rels' | 'release-rels' | 'release-group-rels' | 'series-rels' | 'work-rels';
12
+ export interface IFormData {
13
+ [key: string]: string | number;
14
+ }
15
+ export interface IMusicBrainzConfig {
16
+ botAccount?: {
17
+ username: string;
18
+ password: string;
19
+ };
20
+ baseUrl?: string;
21
+ appName?: string;
22
+ appVersion?: string;
23
+ /**
24
+ * HTTP Proxy
25
+ */
26
+ proxy?: string;
27
+ /**
28
+ * User e-mail address or application URL
29
+ */
30
+ appContactInfo?: string;
31
+ }
32
+ export interface ISessionInformation {
33
+ csrf: {
34
+ sessionKey: string;
35
+ token: string;
36
+ };
37
+ loggedIn?: boolean;
38
+ }
39
+ export declare class MusicBrainzApi {
40
+ private static escapeText;
41
+ readonly config: IMusicBrainzConfig;
42
+ private rateLimiter;
43
+ private options;
44
+ private session;
45
+ static fetchCsrf(html: string): {
46
+ sessionKey: string;
47
+ token: string;
48
+ };
49
+ private static fetchValue;
50
+ private getCookies;
51
+ constructor(_config?: IMusicBrainzConfig);
52
+ restGet<T>(relUrl: string, query?: {
53
+ [key: string]: any;
54
+ }, attempt?: number): Promise<T>;
55
+ /**
56
+ * Generic lookup function
57
+ * @param entity
58
+ * @param mbid
59
+ * @param inc
60
+ */
61
+ getEntity<T>(entity: mb.EntityType, mbid: string, inc?: Includes[]): Promise<T>;
62
+ /**
63
+ * Lookup area
64
+ * @param areaId Area MBID
65
+ * @param inc Sub-queries
66
+ */
67
+ getArea(areaId: string, inc?: Includes[]): Promise<mb.IArea>;
68
+ /**
69
+ * Lookup artist
70
+ * @param artistId Artist MBID
71
+ * @param inc Sub-queries
72
+ */
73
+ getArtist(artistId: string, inc?: Includes[]): Promise<mb.IArtist>;
74
+ /**
75
+ * Lookup release
76
+ * @param releaseId Release MBID
77
+ * @param inc Include: artist-credits, labels, recordings, release-groups, media, discids, isrcs (with recordings)
78
+ * ToDo: ['recordings', 'artists', 'artist-credits', 'isrcs', 'url-rels', 'release-groups']
79
+ */
80
+ getRelease(releaseId: string, inc?: Includes[]): Promise<mb.IRelease>;
81
+ /**
82
+ * Lookup release-group
83
+ * @param releaseGroupId Release-group MBID
84
+ * @param inc Include: ToDo
85
+ */
86
+ getReleaseGroup(releaseGroupId: string, inc?: Includes[]): Promise<mb.IReleaseGroup>;
87
+ /**
88
+ * Lookup work
89
+ * @param workId Work MBID
90
+ */
91
+ getWork(workId: string): Promise<mb.IWork>;
92
+ /**
93
+ * Lookup label
94
+ * @param labelId Label MBID
95
+ */
96
+ getLabel(labelId: string): Promise<mb.ILabel>;
97
+ /**
98
+ * Lookup recording
99
+ * @param recordingId Label MBID
100
+ * @param inc Include: artist-credits, isrcs
101
+ */
102
+ getRecording(recordingId: string, inc?: Includes[]): Promise<mb.IRecording>;
103
+ postRecording(xmlMetadata: XmlMetadata): Promise<void>;
104
+ post(entity: mb.EntityType, xmlMetadata: XmlMetadata): Promise<void>;
105
+ login(): Promise<boolean>;
106
+ /**
107
+ * Logout
108
+ */
109
+ logout(): Promise<boolean>;
110
+ /**
111
+ * Submit entity
112
+ * @param entity Entity type e.g. 'recording'
113
+ * @param mbid
114
+ * @param formData
115
+ */
116
+ editEntity(entity: mb.EntityType, mbid: string, formData: Record<string, any>): Promise<void>;
117
+ /**
118
+ * Set URL to recording
119
+ * @param recording Recording to update
120
+ * @param url2add URL to add to the recording
121
+ * @param editNote Edit note
122
+ */
123
+ addUrlToRecording(recording: mb.IRecording, url2add: {
124
+ linkTypeId: mb.LinkType;
125
+ text: string;
126
+ }, editNote?: string): Promise<void>;
127
+ /**
128
+ * Add ISRC to recording
129
+ * @param recording Recording to update
130
+ * @param isrc ISRC code to add
131
+ * @param editNote Edit note
132
+ */
133
+ addIsrc(recording: mb.IRecording, isrc: string, editNote?: string): Promise<void>;
134
+ /**
135
+ * Search an entity using a search query
136
+ * @param query e.g.: '" artist: Madonna, track: Like a virgin"' or object with search terms: {artist: Madonna}
137
+ * @param entity e.g. 'recording'
138
+ * @param query Arguments
139
+ */
140
+ search<T extends mb.ISearchResult>(entity: mb.EntityType, query: mb.ISearchQuery): Promise<T>;
141
+ /**
142
+ * Add Spotify-ID to MusicBrainz recording.
143
+ * This function will automatically lookup the recording title, which is required to submit the recording URL
144
+ * @param recording MBID of the recording
145
+ * @param spotifyId Spotify ID
146
+ * @param editNote Comment to add.
147
+ */
148
+ addSpotifyIdToRecording(recording: mb.IRecording, spotifyId: string, editNote: string): Promise<void>;
149
+ searchArea(query: mb.ISearchQuery & mb.ILinkedEntitiesArea): Promise<mb.IAreaList>;
150
+ searchArtist(query: mb.ISearchQuery & mb.ILinkedEntitiesArtist): Promise<mb.IArtistList>;
151
+ searchRelease(query: mb.ISearchQuery & mb.ILinkedEntitiesRelease): Promise<mb.IReleaseList>;
152
+ searchReleaseGroup(query: mb.ISearchQuery & mb.ILinkedEntitiesReleaseGroup): Promise<mb.IReleaseGroupList>;
153
+ searchUrl(query: mb.ISearchQuery & mb.ILinkedEntitiesUrl): Promise<mb.IUrlList>;
154
+ private getSession;
155
+ }
156
+ export declare function makeAndQueryString(keyValuePairs: IFormData): string;