musicbrainz-api 0.21.0 → 0.23.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/LICENSE.txt ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright © 2025 Borewit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -116,18 +116,34 @@ MusicBrainz API documentation: [XML Web Service/Version 2 Lookups](https://wiki.
116
116
  ### Lookup Function
117
117
 
118
118
  ```js
119
- const artist = await mbApi.lookup('artist', 'ab2528d9-719f-4261-8098-21849222a0f2');
119
+ const artist = await mbApi.lookup('artist', 'ab2528d9-719f-4261-8098-21849222a0f2', ['recordings']);
120
120
  ```
121
121
 
122
122
  Arguments:
123
- - entity: `'area'` | `'artist'` | `'collection'` | `'instrument'` | `'label'` | `'place'` | `'release'` | `'release-group'` | `'recording'` | `'series'` | `'work'` | `'url'` | `'event'`
124
- - MBID [(MusicBrainz identifier)](https://wiki.musicbrainz.org/MusicBrainz_Identifier)
125
- - query
123
+ - entity (`string`): `'area'` | `'artist'` | `'collection'` | `'instrument'` | `'label'` | `'place'` | `'release'` | `'release-group'` | `'recording'` | `'series'` | `'work'` | `'url'` | `'event'`
124
+ - MBID (`string`): [(MusicBrainz identifier)](https://wiki.musicbrainz.org/MusicBrainz_Identifier)
125
+ - include arguments (`string[]`), see [Include arguments](#include-arguments)
126
126
 
127
+ #### Lookup URLs
127
128
 
128
- | Query argument | Query value |
129
- |-----------------------|-----------------|
130
- | `query.collection` | Collection MBID |
129
+ There is special method to lookup URL entity / entities by one, or an array of URLs
130
+ ([MusicBrainz documentation](https://musicbrainz.org/doc/MusicBrainz_API#url_(by_text))):
131
+
132
+ ```js
133
+ const urls = await mbApi.lookupUrl(['https://open.spotify.com/track/2AMysGXOe0zzZJMtH3Nizb', 'https://open.spotify.com/track/78Teboqh9lPIxWlIW5RMQL']);
134
+ ```
135
+
136
+ or
137
+
138
+ ```js
139
+ const url = await mbApi.lookupUrl('https://open.spotify.com/track/2AMysGXOe0zzZJMtH3Nizb']);
140
+ ```
141
+
142
+ Arguments:
143
+ - url (`string` | `string[]`): URL or array of URLs
144
+ - include arguments (`string[]`), see [Include arguments](#include-arguments)
145
+
146
+ Note that the return type is different, depending on if a single URL or an array of URLs is provided.
131
147
 
132
148
  ### Browse artist
133
149
 
@@ -355,6 +371,82 @@ Search a combination of a release-group and an artist.
355
371
  const result = await mbApi.search('release-group', {artist: 'Racine carrée', releasegroup: 'Stromae'});
356
372
  ```
357
373
 
374
+ ## Include arguments
375
+
376
+
377
+ ### Subqueries
378
+
379
+ _Include Arguments_ which allow you to request more information to be included about the entity.
380
+
381
+ | entity | supported _include arguments_ |
382
+ |------------------|----------------------------------------------------------------------------|
383
+ | `area` | |
384
+ | `artist` | `recordings`, `releases`, `release-groups`, `works` |
385
+ | `collection` | `user-collections` (includes private collections, requires authentication) |
386
+ | `event` | |
387
+ | `genre` | |
388
+ | `instrument` | |
389
+ | `label` | `releases` |
390
+ | `place` | |
391
+ | `recording` | `artists`, `releases`, `release-groups`, `isrcs`, `url-rels` |
392
+ | `release` | `artists`, `collections`, `labels`, `recordings`, `release-groups` |
393
+ | `release-group` | `artists`, `releases` |
394
+ | `series` | |
395
+ | `work` | |
396
+ | `url` | |
397
+
398
+ ### Arguments which affect subqueries
399
+
400
+ Some additional _include parameters_ are supported to specify how much of the data about the linked entities should be included:
401
+
402
+ | _include argument_ | Description |
403
+ |--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
404
+ | `discids` | include discids for all media in the releases |
405
+ | `media` | include media for all releases, this includes the # of tracks on each medium and its format. |
406
+ | `isrcs` | user-collections (includes private collections, requires authentication)include isrcs for all recordings |
407
+ | `artist-credits` | include artists credits for all releases and recordings |
408
+ | `various-artists` | include only those releases where the artist appears on one of the tracks, but not in the artist credit for the release itself (this is only valid on entity `"artist"` and _include argument_ `"releases request"`). |
409
+
410
+ ### Miscellaneous arguments
411
+
412
+ | _include argument_ | Description |
413
+ |-----------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
414
+ | `aliases` | include artist, label, area or work aliases; treat these as a set, as they are not deliberately ordered |
415
+ | `annotation` | include annotation |
416
+ | `tags`, `ratings` | include tags and/or ratings for the entity |
417
+ | `user-tags`, `user-ratings` | same as above, but only return the tags and/or ratings submitted by the specified user |
418
+ | `genres`, `user-genres` | include genres (tags in the [genres list](https://musicbrainz.org/genres)): either all or the ones submitted by the user, respectively |
419
+
420
+ ### Relationships
421
+
422
+ You can request relationships with the appropriate includes:
423
+ - `area-rels`
424
+ - `artist-rels`
425
+ - `event-rels`
426
+ - `genre-rels`
427
+ - `instrument-rels`
428
+ - `label-rels`
429
+ - `place-rels`
430
+ - `recording-rels`
431
+ - `release-rels`
432
+ - `release-group-rels`
433
+ - `series-rels`
434
+ - `url-rels`
435
+ - `work-rels`
436
+
437
+ These will load relationships between the requested entity and the specific entity type.
438
+ For example, if you request "work-rels" when looking up an artist,
439
+ you'll get all the relationships between this artist and any works,
440
+ and if you request "artist-rels" you'll get the relationships between this artist and any other artists.
441
+ As such, keep in mind requesting "artist-rels" for an artist, "release-rels" for a release, etc. will not load all the relationships for the entity, just the ones to other entities of the same type.
442
+
443
+ In a release request, you might also be interested on relationships for the recordings linked to the release, or the release group linked to the release, or even for the works linked to those recordings that are linked to the release (for example, to find out who played guitar on a specific track, who wrote the lyrics for the song being performed, or whether the release group is part of a series). Similarly, for a recording request, you might want to get the relationships for any linked works.
444
+ There are three additional includes for this:
445
+
446
+ - recording-level-rels
447
+ - release-group-level-rels (for releases only)
448
+ - work-level-rels
449
+
358
450
  # Submitting data via XML POST
359
451
 
360
452
  [Submitting data via XML POST](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Submitting_data) may be done using personal MusicBrainz credentials.
@@ -425,26 +517,40 @@ await mbApi.addSpotifyIdToRecording(recording, '2AMysGXOe0zzZJMtH3Nizb');
425
517
  This library also supports the [Cover Art Archive API](https://musicbrainz.org/doc/Cover_Art_Archive/API).
426
518
 
427
519
  ### Fetch Release Cover Art
520
+
521
+ #### Fetch available cover art information
522
+
428
523
  ```js
429
524
  import { CoverArtArchiveApi } from 'musicbrainz-api';
430
525
 
431
526
  const coverArtArchiveApiClient = new CoverArtArchiveApi();
432
527
 
433
- async function getReleaseCoverArt(releaseMbid, coverType = '') {
434
- try {
435
- const coverInfo = await coverArtArchiveApiClient.getReleaseCovers(releaseMbid, coverType);
436
- console.log(`Cover info for ${coverType || 'all covers'}`, coverInfo);
437
- } catch (error) {
438
- console.error(`Failed to fetch ${coverType || 'all covers'}:`, error);
528
+ async function fetchCoverArt(releaseMbid, coverType = '') {
529
+ const coverInfo = await coverArtArchiveApiClient.getReleaseCovers(releaseMbid);
530
+ for(const image of coverInfo.images) {
531
+ console.log(`Cover art front=${image.front} back=${image.back} url=${image.image}`);
439
532
  }
440
533
  }
441
534
 
442
- (async () => {
443
- const releaseMbid = 'your-release-mbid-here'; // Replace with actual MBID
444
- await getReleaseCoverArt(releaseMbid); // Get all covers
445
- await getReleaseCoverArt(releaseMbid, 'front'); // Get best front cover
446
- await getReleaseCoverArt(releaseMbid, 'back'); // Get best back cover
447
- })();
535
+ fetchCoverArt('976e0677-a480-4a5e-a177-6a86c1900bbf').catch(error => {
536
+ console.error(`Failed to fetch cover art: ${error.message}`);
537
+ })
538
+ ```
539
+
540
+ #### Fetch front or back cover for a release
541
+ ```js
542
+ import { CoverArtArchiveApi } from 'musicbrainz-api';
543
+
544
+ const coverArtArchiveApiClient = new CoverArtArchiveApi();
545
+
546
+ async function fetchCoverArt(releaseMbid, coverType = '') {
547
+ const coverInfo = await coverArtArchiveApiClient.getReleaseCover(releaseMbid, 'front');
548
+ console.log(`Cover art url=${coverInfo.url}`);
549
+ }
550
+
551
+ fetchCoverArt('976e0677-a480-4a5e-a177-6a86c1900bbf').catch(error => {
552
+ console.error(`Failed to fetch cover art: ${error.message}`);
553
+ })
448
554
  ```
449
555
 
450
556
  ### Release Group Cover Art
@@ -453,22 +559,32 @@ import { CoverArtArchiveApi } from 'musicbrainz-api';
453
559
 
454
560
  const coverArtArchiveApiClient = new CoverArtArchiveApi();
455
561
 
456
- async function getCoverArt(releaseGroupMbid, coverType = '') {
457
- try {
458
- const coverInfo = await coverArtArchiveApiClient.getReleaseGroupCovers(releaseGroupMbid, coverType);
459
- console.log(`Cover info for ${coverType || 'all covers'}`, coverInfo);
460
- } catch (error) {
461
- console.error(`Failed to fetch ${coverType || 'all covers'}:`, error);
562
+ async function fetchCoverArt(releaseMbid, coverType = '') {
563
+ const coverInfo = await coverArtArchiveApiClient.getReleaseGroupCovers(releaseMbid);
564
+ for(const image of coverInfo.images) {
565
+ console.log(`Cover art front=${image.front} back=${image.back} url=${image.image}`);
462
566
  }
463
567
  }
464
568
 
465
- (async () => {
466
- const releaseGroupMbid = 'your-release-group-mbid-here'; // Replace with actual MBID
467
- await getCoverArt(releaseGroupMbid); // Get all covers
468
- await getCoverArt(releaseGroupMbid, 'front'); // Get best front cover
469
- await getCoverArt(releaseGroupMbid, 'back'); // Get best back cover
470
- })();
569
+ fetchCoverArt('976e0677-a480-4a5e-a177-6a86c1900bbf').catch(error => {
570
+ console.error(`Failed to fetch cover art: ${error.message}`);
571
+ })
572
+ ```
471
573
 
574
+ #### Fetch front or back cover for a release-group
575
+ ```js
576
+ import { CoverArtArchiveApi } from 'musicbrainz-api';
577
+
578
+ const coverArtArchiveApiClient = new CoverArtArchiveApi();
579
+
580
+ async function fetchCoverArt(releaseMbid, coverType = '') {
581
+ const coverInfo = await coverArtArchiveApiClient.getReleaseGroupCover(releaseMbid, 'front');
582
+ console.log(`Cover art url=${coverInfo.url}`);
583
+ }
584
+
585
+ fetchCoverArt('976e0677-a480-4a5e-a177-6a86c1900bbf').catch(error => {
586
+ console.error(`Failed to fetch cover art: ${error.message}`);
587
+ })
472
588
  ```
473
589
 
474
590
  ## CommonJS backward compatibility
@@ -505,3 +621,7 @@ async function run() {
505
621
 
506
622
  run();
507
623
  ```
624
+
625
+ ## Licence
626
+
627
+ This project is licensed under the [MIT License](LICENSE.txt). Feel free to use, modify, and distribute as needed.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musicbrainz-api",
3
- "version": "0.21.0",
3
+ "version": "0.23.0",
4
4
  "description": "MusicBrainz API client for reading and submitting metadata",
5
5
  "exports": {
6
6
  "node": {
@@ -90,9 +90,10 @@
90
90
  "compile-lib": "tsc -p lib",
91
91
  "compile-test": "tsc -p test",
92
92
  "compile": "yarn run compile-lib && yarn run compile-test",
93
- "lint-md": "remark -u preset-lint-recommended .",
94
- "lint-ts": "biome check",
95
- "lint": "yarn run lint-md && yarn run lint-ts",
93
+ "lint:md": "remark -u preset-lint-recommended .",
94
+ "lint:ts": "biome check",
95
+ "lint:fix": "biome check --fix",
96
+ "lint": "yarn run lint:md && yarn run lint:ts",
96
97
  "test": "mocha",
97
98
  "build": "yarn run clean && yarn run compile",
98
99
  "start": "yarn run compile && yarn run lint && yarn run cover-test",
@@ -114,5 +115,5 @@
114
115
  ],
115
116
  "report-dir": "coverage"
116
117
  },
117
- "packageManager": "yarn@4.6.0"
118
+ "packageManager": "yarn@4.9.1"
118
119
  }
@@ -1,48 +0,0 @@
1
- export type CovertType = 'Front' | 'Back' | 'Booklet' | 'Medium' | 'Obi' | 'Spine' | 'Track' | 'Tray' | 'Sticker' | 'Poster' | 'Liner' | 'Watermark' | 'Raw/Unedited' | 'Matrix/Runout' | 'Top' | 'Bottom' | 'Other';
2
- export interface IImage {
3
- types: CovertType[];
4
- front: boolean;
5
- back: boolean;
6
- edit: number;
7
- image: string;
8
- comment: string;
9
- approved: boolean;
10
- id: string;
11
- thumbnails: {
12
- large: string;
13
- small: string;
14
- '250': string;
15
- '500'?: string;
16
- '1200'?: string;
17
- };
18
- }
19
- export interface ICoverInfo {
20
- images: IImage[];
21
- release: string;
22
- }
23
- export declare class CoverArtArchiveApi {
24
- private httpClient;
25
- private getJson;
26
- /**
27
- * Fetch release
28
- * @releaseId Release MBID
29
- * @param releaseId MusicBrainz Release MBID
30
- * @param coverType Cover type
31
- */
32
- getReleaseCovers(releaseId: string, coverType?: 'front' | 'back'): Promise<ICoverInfo>;
33
- /**
34
- * Fetch release-group
35
- * @releaseGroupId Release-group MBID
36
- * @param releaseGroupId MusicBrainz Release Group MBID
37
- * @param coverType Cover type
38
- */
39
- getReleaseGroupCovers(releaseGroupId: string, coverType?: 'front' | 'back'): Promise<ICoverInfo>;
40
- /**
41
- * Fetch covers
42
- * @releaseId MBID
43
- * @param releaseId MusicBrainz Release Group MBID
44
- * @param releaseType Fetch covers for specific release or release-group
45
- * @param coverType Cover type
46
- */
47
- private getCovers;
48
- }
@@ -1,60 +0,0 @@
1
- /* eslint-disable-next-line */
2
- import { HttpClient } from "./http-client.js";
3
- export class CoverArtArchiveApi {
4
- constructor() {
5
- this.httpClient = new HttpClient({ baseUrl: 'https://coverartarchive.org', userAgent: 'Node.js musicbrains-api', timeout: 20000 });
6
- }
7
- async getJson(path) {
8
- const response = await this.httpClient.get(path, {
9
- headers: {
10
- Accept: "application/json"
11
- }
12
- });
13
- const contentType = response.headers.get("Content-Type");
14
- if (response.status === 404 && contentType?.toLowerCase() !== "application/json") {
15
- return {
16
- "error": "Not Found",
17
- "help": "For usage, please see: https://musicbrainz.org/development/mmd"
18
- };
19
- }
20
- return response.json();
21
- }
22
- /**
23
- * Fetch release
24
- * @releaseId Release MBID
25
- * @param releaseId MusicBrainz Release MBID
26
- * @param coverType Cover type
27
- */
28
- getReleaseCovers(releaseId, coverType) {
29
- return this.getCovers(releaseId, 'release', coverType);
30
- }
31
- /**
32
- * Fetch release-group
33
- * @releaseGroupId Release-group MBID
34
- * @param releaseGroupId MusicBrainz Release Group MBID
35
- * @param coverType Cover type
36
- */
37
- getReleaseGroupCovers(releaseGroupId, coverType) {
38
- return this.getCovers(releaseGroupId, 'release-group', coverType);
39
- }
40
- /**
41
- * Fetch covers
42
- * @releaseId MBID
43
- * @param releaseId MusicBrainz Release Group MBID
44
- * @param releaseType Fetch covers for specific release or release-group
45
- * @param coverType Cover type
46
- */
47
- async getCovers(releaseId, releaseType = 'release', coverType) {
48
- const path = [releaseType, releaseId];
49
- if (coverType) {
50
- path.push(coverType);
51
- }
52
- const info = await this.getJson(`/${path.join('/')}`);
53
- // Hack to correct http addresses into https
54
- if (info.release?.startsWith('http:')) {
55
- info.release = `https${info.release.substring(4)}`;
56
- }
57
- return info;
58
- }
59
- }
60
- //# sourceMappingURL=coverartarchive-api.js.map
@@ -1,21 +0,0 @@
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: string, user: string, realm: string, pass: string, nonce: string, cnonce: string): string;
16
- hasAuth: boolean;
17
- sentAuth: boolean;
18
- bearerToken: string | null;
19
- constructor(credentials: ICredentials);
20
- digest(method: string, path: string, authHeader: string): string;
21
- }
@@ -1,77 +0,0 @@
1
- import { v4 as uuidv4 } from 'uuid';
2
- import sparkMd5 from 'spark-md5';
3
- const md5 = sparkMd5.hash;
4
- export class DigestAuth {
5
- /**
6
- * RFC 2617: handle both MD5 and MD5-sess algorithms.
7
- *
8
- * If the algorithm directive's value is "MD5" or unspecified, then HA1 is
9
- * HA1=MD5(username:realm:password)
10
- * If the algorithm directive's value is "MD5-sess", then HA1 is
11
- * HA1=MD5(MD5(username:realm:password):nonce:cnonce)
12
- */
13
- static ha1Compute(algorithm, user, realm, pass, nonce, cnonce) {
14
- const ha1 = md5(`${user}:${realm}:${pass}`); // lgtm [js/insufficient-password-hash]
15
- return algorithm && algorithm.toLowerCase() === 'md5-sess' ? md5(`${ha1}:${nonce}:${cnonce}`) : ha1;
16
- }
17
- constructor(credentials) {
18
- this.credentials = credentials;
19
- this.hasAuth = false;
20
- this.sentAuth = false;
21
- this.bearerToken = null;
22
- }
23
- digest(method, path, authHeader) {
24
- // TODO: More complete implementation of RFC 2617.
25
- // - support qop="auth-int" only
26
- // - handle Authentication-Info (not necessarily?)
27
- // - check challenge.stale (not necessarily?)
28
- // - increase nc (not necessarily?)
29
- // For reference:
30
- // http://tools.ietf.org/html/rfc2617#section-3
31
- // https://github.com/bagder/curl/blob/master/lib/http_digest.c
32
- const challenge = {};
33
- const re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi;
34
- while (true) {
35
- const match = re.exec(authHeader);
36
- if (!match) {
37
- break;
38
- }
39
- challenge[match[1]] = match[2] || match[3];
40
- }
41
- const qop = /(^|,)\s*auth\s*($|,)/.test(challenge.qop) && 'auth';
42
- const nc = qop && '00000001';
43
- const cnonce = qop && uuidv4().replace(/-/g, '');
44
- const ha1 = DigestAuth.ha1Compute(challenge.algorithm, this.credentials.username, challenge.realm, this.credentials.password, challenge.nonce, cnonce);
45
- const ha2 = md5(`${method}:${path}`); // lgtm [js/insufficient-password-hash]
46
- const digestResponse = qop
47
- ? md5(`${ha1}:${challenge.nonce}:${nc}:${cnonce}:${qop}:${ha2}`) // lgtm [js/insufficient-password-hash]
48
- : md5(`${ha1}:${challenge.nonce}:${ha2}`); // lgtm [js/insufficient-password-hash]
49
- const authValues = {
50
- username: this.credentials.username,
51
- realm: challenge.realm,
52
- nonce: challenge.nonce,
53
- uri: path,
54
- qop,
55
- response: digestResponse,
56
- nc,
57
- cnonce,
58
- algorithm: challenge.algorithm,
59
- opaque: challenge.opaque
60
- };
61
- const parts = [];
62
- Object.entries(authValues).forEach(([key, value]) => {
63
- if (value) {
64
- if (key === 'qop' || key === 'nc' || key === 'algorithm') {
65
- parts.push(`${key}=${value}`);
66
- }
67
- else {
68
- parts.push(`${key}="${value}"`);
69
- }
70
- }
71
- });
72
- const digest = `Digest ${parts.join(', ')}`;
73
- this.sentAuth = true;
74
- return digest;
75
- }
76
- }
77
- //# sourceMappingURL=digest-auth.js.map
@@ -1,2 +0,0 @@
1
- export * from './coverartarchive-api.js';
2
- export * from './musicbrainz-api.js';
@@ -1,3 +0,0 @@
1
- export * from './coverartarchive-api.js';
2
- export * from './musicbrainz-api.js';
3
- //# sourceMappingURL=entry-default.js.map
@@ -1,2 +0,0 @@
1
- export * from './coverartarchive-api.js';
2
- export * from './musicbrainz-api-node.js';
package/lib/entry-node.js DELETED
@@ -1,3 +0,0 @@
1
- export * from './coverartarchive-api.js';
2
- export * from './musicbrainz-api-node.js';
3
- //# sourceMappingURL=entry-node.js.map
@@ -1,11 +0,0 @@
1
- import { type Cookie } from "tough-cookie";
2
- import { HttpClient, type IHttpClientOptions } from "./http-client.js";
3
- export type HttpFormData = {
4
- [key: string]: string;
5
- };
6
- export declare class HttpClientNode extends HttpClient {
7
- private cookieJar;
8
- constructor(options: IHttpClientOptions);
9
- protected registerCookies(response: Response): Promise<Cookie | undefined>;
10
- getCookies(): Promise<string | null>;
11
- }
@@ -1,19 +0,0 @@
1
- import { CookieJar } from "tough-cookie";
2
- import { HttpClient } from "./http-client.js";
3
- export class HttpClientNode extends HttpClient {
4
- constructor(options) {
5
- super(options);
6
- this.cookieJar = new CookieJar();
7
- }
8
- registerCookies(response) {
9
- const cookie = response.headers.get('set-cookie');
10
- if (cookie) {
11
- return this.cookieJar.setCookie(cookie, response.url);
12
- }
13
- return Promise.resolve(undefined);
14
- }
15
- getCookies() {
16
- return this.cookieJar.getCookieString(this.options.baseUrl); // Get cookies for the request
17
- }
18
- }
19
- //# sourceMappingURL=http-client-node.js.map
@@ -1,27 +0,0 @@
1
- import type { Cookie } from "tough-cookie";
2
- export type HttpFormData = {
3
- [key: string]: string;
4
- };
5
- export interface IHttpClientOptions {
6
- baseUrl: string;
7
- timeout: number;
8
- userAgent: string;
9
- }
10
- export interface IFetchOptions {
11
- query?: HttpFormData;
12
- retryLimit?: number;
13
- body?: string;
14
- headers?: HeadersInit;
15
- followRedirects?: boolean;
16
- }
17
- export declare class HttpClient {
18
- protected options: IHttpClientOptions;
19
- constructor(options: IHttpClientOptions);
20
- get(path: string, options?: IFetchOptions): Promise<Response>;
21
- post(path: string, options?: IFetchOptions): Promise<Response>;
22
- postForm(path: string, formData: HttpFormData, options?: IFetchOptions): Promise<Response>;
23
- postJson(path: string, json: Object, options?: IFetchOptions): Promise<Response>;
24
- private _fetch;
25
- protected registerCookies(response: Response): Promise<Cookie | undefined>;
26
- getCookies(): Promise<string | null>;
27
- }
@@ -1,50 +0,0 @@
1
- export class HttpClient {
2
- constructor(options) {
3
- this.options = options;
4
- }
5
- get(path, options) {
6
- return this._fetch('get', path, options);
7
- }
8
- post(path, options) {
9
- return this._fetch('post', path, options);
10
- }
11
- postForm(path, formData, options) {
12
- const encodedFormData = new URLSearchParams(formData).toString();
13
- return this._fetch('post', path, { ...options, body: encodedFormData, headers: { 'Content-Type': 'application/x-www-form-urlencoded' } });
14
- }
15
- // biome-ignore lint/complexity/noBannedTypes:
16
- postJson(path, json, options) {
17
- const encodedJson = JSON.stringify(json);
18
- return this._fetch('post', path, { ...options, body: encodedJson, headers: { 'Content-Type': 'application/json.' } });
19
- }
20
- async _fetch(method, path, options) {
21
- if (!options)
22
- options = {};
23
- let url = `${this.options.baseUrl}/${path}`;
24
- if (options.query) {
25
- url += `?${new URLSearchParams(options.query)}`;
26
- }
27
- const cookies = await this.getCookies();
28
- const headers = new Headers(options.headers);
29
- headers.set('User-Agent', this.options.userAgent);
30
- if (cookies !== null) {
31
- headers.set('Cookie', cookies);
32
- }
33
- const response = await fetch(url, {
34
- method,
35
- ...options,
36
- headers,
37
- body: options.body,
38
- redirect: options.followRedirects === false ? 'manual' : 'follow'
39
- });
40
- await this.registerCookies(response);
41
- return response;
42
- }
43
- registerCookies(response) {
44
- return Promise.resolve(undefined);
45
- }
46
- async getCookies() {
47
- return Promise.resolve(null);
48
- }
49
- }
50
- //# sourceMappingURL=http-client.js.map
@@ -1,16 +0,0 @@
1
- export { XmlMetadata } from './xml/xml-metadata.js';
2
- export { XmlIsrc } from './xml/xml-isrc.js';
3
- export { XmlIsrcList } from './xml/xml-isrc-list.js';
4
- export { XmlRecording } from './xml/xml-recording.js';
5
- import { HttpClientNode } from "./http-client-node.js";
6
- import { MusicBrainzApi as MusicBrainzApiDefault } from "./musicbrainz-api.js";
7
- export * from './musicbrainz.types.js';
8
- export * from './http-client.js';
9
- export declare class MusicBrainzApi extends MusicBrainzApiDefault {
10
- protected initHttpClient(): HttpClientNode;
11
- login(): Promise<boolean>;
12
- /**
13
- * Logout
14
- */
15
- logout(): Promise<boolean>;
16
- }