musicbrainz-api 0.14.0 → 0.16.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
@@ -98,7 +98,7 @@ const artist = await mbApi.lookup('artist', 'ab2528d9-719f-4261-8098-21849222a0f
98
98
  ### Browse artist
99
99
 
100
100
  ```js
101
- const artists = await browse('artist', query);
101
+ const artists = await mbApi.browse('artist', query);
102
102
  ````
103
103
 
104
104
  | Query argument | Query value |
@@ -112,7 +112,7 @@ const artists = await browse('artist', query);
112
112
 
113
113
  ### Browse collection
114
114
  ```js
115
- const collections = await browse('collection', query);
115
+ const collections = await mbApi.browse('collection', query);
116
116
  ````
117
117
 
118
118
  | Query argument | Query value |
@@ -130,7 +130,7 @@ const collections = await browse('collection', query);
130
130
 
131
131
  ### Browse events
132
132
  ```js
133
- const events = await browse('event', query);
133
+ const events = await mbApi.browse('event', query);
134
134
  ````
135
135
 
136
136
  | Query argument | Query value |
@@ -142,7 +142,7 @@ const events = await browse('event', query);
142
142
 
143
143
  ### Browse instruments
144
144
  ```js
145
- const instruments = await browse('event', query);
145
+ const instruments = await mbApi.browse('event', query);
146
146
  ````
147
147
 
148
148
  | Query argument | Query value |
@@ -151,7 +151,7 @@ const instruments = await browse('event', query);
151
151
 
152
152
  ### Browse labels
153
153
  ```js
154
- const labels = await browse('label', query);
154
+ const labels = await mbApi.browse('label', query);
155
155
  ````
156
156
 
157
157
  | Query argument | Query value |
@@ -162,7 +162,7 @@ const labels = await browse('label', query);
162
162
 
163
163
  ### Browse places
164
164
  ```js
165
- const places = await browse('place', query);
165
+ const places = await mbApi.browse('place', query);
166
166
  ````
167
167
 
168
168
  | Query argument | Query value |
@@ -172,7 +172,7 @@ const places = await browse('place', query);
172
172
 
173
173
  ### Browse recordings
174
174
  ```js
175
- const recordings = await browse('recording', query);
175
+ const recordings = await mbApi.browse('recording', query);
176
176
  ````
177
177
 
178
178
  | Query argument | Query value |
@@ -184,7 +184,7 @@ const recordings = await browse('recording', query);
184
184
 
185
185
  ### Browse releases
186
186
  ```js
187
- const releases = await browse('release', query);
187
+ const releases = await mbApi.browse('release', query);
188
188
  ````
189
189
 
190
190
  | Query argument | Query value |
@@ -202,7 +202,7 @@ const releases = await browse('release', query);
202
202
 
203
203
  ### Browse release-groups
204
204
  ```js
205
- const releaseGroups = await browse('release-group',query);
205
+ const releaseGroups = await mbApi.browse('release-group',query);
206
206
  ```
207
207
 
208
208
  | Query argument | Query value |
@@ -213,7 +213,7 @@ const releaseGroups = await browse('release-group',query);
213
213
 
214
214
  ### Browse series
215
215
  ```js
216
- const series = await browse('series');
216
+ const series = await mbApi.browse('series');
217
217
  ````
218
218
 
219
219
  | Query argument | Query value |
@@ -231,7 +231,7 @@ const series = await browse('series');
231
231
 
232
232
  ### Browse works
233
233
  ```js
234
- const works = await browse('work');
234
+ const works = await mbApi.browse('work');
235
235
  ````
236
236
 
237
237
  | Query argument | Query value |
@@ -241,7 +241,7 @@ const works = await browse('work');
241
241
 
242
242
  ### Browse urls
243
243
  ```js
244
- const urls = await browse('url');
244
+ const urls = await mbApi.browse('url');
245
245
  ````
246
246
 
247
247
  | Query argument | Query value |
@@ -277,7 +277,7 @@ Arguments:
277
277
  For example, to find any recordings of _'We Will Rock You'_ by Queen:
278
278
  ```js
279
279
  const query = 'query="We Will Rock You" AND arid:0383dadf-2a4e-4d10-a46a-e9e041da8eb3';
280
- const result = await mbApi.query<mb.IReleaseGroupList>('release-group', {query});
280
+ const result = await mbApi.search('release-group', {query});
281
281
  ```
282
282
 
283
283
  ##### Example: search Île-de-France
@@ -391,6 +391,7 @@ await mbApi.addSpotifyIdToRecording(recording, '2AMysGXOe0zzZJMtH3Nizb');
391
391
 
392
392
  Implementation of the [Cover Art Archive API](https://musicbrainz.org/doc/Cover_Art_Archive/API).
393
393
 
394
+ ### Release Cover Art
394
395
  ```js
395
396
  import {CoverArtArchiveApi} from 'musicbrainz-api';
396
397
 
@@ -408,6 +409,25 @@ coverArtArchiveApiClient.getReleaseCovers(releaseMbid, 'back').then(releaseCover
408
409
 
409
410
  ```
410
411
 
412
+ ### Release Group Cover Art
413
+ ```js
414
+ import {CoverArtArchiveApi} from 'musicbrainz-api';
415
+
416
+ coverArtArchiveApiClient.getReleaseGroupCovers(releaseGroupMbid).then(releaseGroupCoverInfo => {
417
+ console.log('Release cover info', releaseGroupCoverInfo);
418
+ });
419
+
420
+ coverArtArchiveApiClient.getReleaseGroupCovers(releaseGroupMbid, 'front').then(releaseGroupCoverInfo => {
421
+ console.log('Get best front cover', releaseGroupCoverInfo);
422
+ });
423
+
424
+ coverArtArchiveApiClient.getReleaseGroupCovers(releaseGroupMbid, 'back').then(releaseGroupCoverInfo => {
425
+ console.log('Get best back cover', releaseGroupCoverInfo);
426
+ });
427
+
428
+ ```
429
+
430
+
411
431
  ## Compatibility
412
432
 
413
433
  The JavaScript in runtime is compliant with [ECMAScript 2017 (ES8)](https://en.wikipedia.org/wiki/ECMAScript#8th_Edition_-_ECMAScript_2017).
@@ -24,8 +24,25 @@ export declare class CoverArtArchiveApi {
24
24
  private host;
25
25
  private getJson;
26
26
  /**
27
- *
27
+ * Fetch release
28
+ * @releaseId Release MBID
28
29
  * @param releaseId MusicBrainz Release MBID
30
+ * @param coverType Cover type
29
31
  */
30
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;
31
48
  }
@@ -5,27 +5,49 @@ export class CoverArtArchiveApi {
5
5
  this.host = 'coverartarchive.org';
6
6
  }
7
7
  async getJson(path) {
8
- const response = await got.get('https://' + this.host + path, {
8
+ const response = await got.get(`https://${this.host}${path}`, {
9
9
  headers: {
10
- Accept: `application/json`
10
+ Accept: "application/json"
11
11
  },
12
12
  responseType: 'json'
13
13
  });
14
14
  return response.body;
15
15
  }
16
16
  /**
17
- *
17
+ * Fetch release
18
+ * @releaseId Release MBID
18
19
  * @param releaseId MusicBrainz Release MBID
20
+ * @param coverType Cover type
19
21
  */
20
- async getReleaseCovers(releaseId, coverType) {
21
- const path = ['release', releaseId];
22
+ getReleaseCovers(releaseId, coverType) {
23
+ return this.getCovers(releaseId, 'release', coverType);
24
+ }
25
+ /**
26
+ * Fetch release-group
27
+ * @releaseGroupId Release-group MBID
28
+ * @param releaseGroupId MusicBrainz Release Group MBID
29
+ * @param coverType Cover type
30
+ */
31
+ getReleaseGroupCovers(releaseGroupId, coverType) {
32
+ return this.getCovers(releaseGroupId, 'release-group', coverType);
33
+ }
34
+ /**
35
+ * Fetch covers
36
+ * @releaseId MBID
37
+ * @param releaseId MusicBrainz Release Group MBID
38
+ * @param releaseType Fetch covers for specific release or release-group
39
+ * @param coverType Cover type
40
+ */
41
+ async getCovers(releaseId, releaseType = 'release', coverType) {
42
+ var _a;
43
+ const path = [releaseType, releaseId];
22
44
  if (coverType) {
23
45
  path.push(coverType);
24
46
  }
25
- const info = await this.getJson('/' + path.join('/'));
47
+ const info = await this.getJson(`/${path.join('/')}`);
26
48
  // Hack to correct http addresses into https
27
- if (info.release && info.release.startsWith('http:')) {
28
- info.release = 'https' + info.release.substring(4);
49
+ if ((_a = info.release) === null || _a === void 0 ? void 0 : _a.startsWith('http:')) {
50
+ info.release = `https${info.release.substring(4)}`;
29
51
  }
30
52
  return info;
31
53
  }
@@ -1,5 +1,5 @@
1
1
  import { v4 as uuidv4 } from 'uuid';
2
- import * as crypto from 'crypto';
2
+ import * as crypto from 'node:crypto';
3
3
  function md5(str) {
4
4
  return crypto.createHash('md5').update(str).digest('hex'); // lgtm [js/insufficient-password-hash]
5
5
  }
@@ -13,8 +13,8 @@ export class DigestAuth {
13
13
  * HA1=MD5(MD5(username:realm:password):nonce:cnonce)
14
14
  */
15
15
  static ha1Compute(algorithm, user, realm, pass, nonce, cnonce) {
16
- const ha1 = md5(user + ':' + realm + ':' + pass); // lgtm [js/insufficient-password-hash]
17
- return algorithm && algorithm.toLowerCase() === 'md5-sess' ? md5(ha1 + ':' + nonce + ':' + cnonce) : ha1;
16
+ const ha1 = md5(`${user}:${realm}:${pass}`); // lgtm [js/insufficient-password-hash]
17
+ return algorithm && algorithm.toLowerCase() === 'md5-sess' ? md5(`${ha1}:${nonce}:${cnonce}`) : ha1;
18
18
  }
19
19
  constructor(credentials) {
20
20
  this.credentials = credentials;
@@ -44,10 +44,10 @@ export class DigestAuth {
44
44
  const nc = qop && '00000001';
45
45
  const cnonce = qop && uuidv4().replace(/-/g, '');
46
46
  const ha1 = DigestAuth.ha1Compute(challenge.algorithm, this.credentials.username, challenge.realm, this.credentials.password, challenge.nonce, cnonce);
47
- const ha2 = md5(method + ':' + path); // lgtm [js/insufficient-password-hash]
47
+ const ha2 = md5(`${method}:${path}`); // lgtm [js/insufficient-password-hash]
48
48
  const digestResponse = qop
49
- ? md5(ha1 + ':' + challenge.nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2) // lgtm [js/insufficient-password-hash]
50
- : md5(ha1 + ':' + challenge.nonce + ':' + ha2); // lgtm [js/insufficient-password-hash]
49
+ ? md5(`${ha1}:${challenge.nonce}:${nc}:${cnonce}:${qop}:${ha2}`) // lgtm [js/insufficient-password-hash]
50
+ : md5(`${ha1}:${challenge.nonce}:${ha2}`); // lgtm [js/insufficient-password-hash]
51
51
  const authValues = {
52
52
  username: this.credentials.username,
53
53
  realm: challenge.realm,
@@ -64,16 +64,16 @@ export class DigestAuth {
64
64
  Object.entries(authValues).forEach(([key, value]) => {
65
65
  if (value) {
66
66
  if (key === 'qop' || key === 'nc' || key === 'algorithm') {
67
- parts.push(key + '=' + value);
67
+ parts.push(`${key}=${value}`);
68
68
  }
69
69
  else {
70
- parts.push(key + '="' + value + '"');
70
+ parts.push(`${key}="${value}"`);
71
71
  }
72
72
  }
73
73
  });
74
- authHeader = 'Digest ' + parts.join(', ');
74
+ const digest = `Digest ${parts.join(', ')}`;
75
75
  this.sentAuth = true;
76
- return authHeader;
76
+ return digest;
77
77
  }
78
78
  }
79
79
  //# sourceMappingURL=digest-auth.js.map
@@ -2,7 +2,7 @@ export { XmlMetadata } from './xml/xml-metadata.js';
2
2
  export { XmlIsrc } from './xml/xml-isrc.js';
3
3
  export { XmlIsrcList } from './xml/xml-isrc-list.js';
4
4
  export { XmlRecording } from './xml/xml-recording.js';
5
- import { XmlMetadata } from './xml/xml-metadata.js';
5
+ import type { XmlMetadata } from './xml/xml-metadata.js';
6
6
  import * as mb from './musicbrainz.types.js';
7
7
  export * from './musicbrainz.types.js';
8
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';
@@ -46,7 +46,7 @@ export type IFormData = {
46
46
  [key: string]: string | number;
47
47
  };
48
48
  export interface IMusicBrainzConfig {
49
- botAccount: {
49
+ botAccount?: {
50
50
  username?: string;
51
51
  password?: string;
52
52
  };
@@ -71,7 +71,6 @@ export interface ISessionInformation {
71
71
  loggedIn?: boolean;
72
72
  }
73
73
  export declare class MusicBrainzApi {
74
- private static escapeText;
75
74
  readonly config: IMusicBrainzConfig;
76
75
  private rateLimiter;
77
76
  private options;
@@ -82,7 +81,7 @@ export declare class MusicBrainzApi {
82
81
  constructor(_config?: IMusicBrainzConfig);
83
82
  restGet<T>(relUrl: string, query?: {
84
83
  [key: string]: any;
85
- }, attempt?: number): Promise<T>;
84
+ }): Promise<T>;
86
85
  /**
87
86
  * Lookup entity
88
87
  * @param entity 'area', 'artist', collection', 'instrument', 'label', 'place', 'release', 'release-group', 'recording', 'series', 'work', 'url' or 'event'
@@ -164,9 +163,8 @@ export declare class MusicBrainzApi {
164
163
  * Add ISRC to recording
165
164
  * @param recording Recording to update
166
165
  * @param isrc ISRC code to add
167
- * @param editNote Edit note
168
166
  */
169
- addIsrc(recording: mb.IRecording, isrc: string, editNote?: string): Promise<void>;
167
+ addIsrc(recording: mb.IRecording, isrc: string): Promise<void>;
170
168
  /**
171
169
  * Add Spotify-ID to MusicBrainz recording.
172
170
  * This function will automatically lookup the recording title, which is required to submit the recording URL
@@ -1,4 +1,4 @@
1
- import * as assert from 'assert';
1
+ import * as assert from 'node:assert';
2
2
  import { StatusCodes as HttpStatus } from 'http-status-codes';
3
3
  import Debug from 'debug';
4
4
  export { XmlMetadata } from './xml/xml-metadata.js';
@@ -11,38 +11,9 @@ import * as mb from './musicbrainz.types.js';
11
11
  import got from 'got';
12
12
  import { CookieJar } from 'tough-cookie';
13
13
  export * from './musicbrainz.types.js';
14
- import { promisify } from 'util';
14
+ import { promisify } from 'node:util';
15
15
  const debug = Debug('musicbrainz-api');
16
16
  export class MusicBrainzApi {
17
- static escapeText(text) {
18
- let str = '';
19
- for (const chr of text) {
20
- // Escaping Special Characters: + - && || ! ( ) { } [ ] ^ " ~ * ? : \ /
21
- // ToDo: && ||
22
- switch (chr) {
23
- case '+':
24
- case '-':
25
- case '!':
26
- case '(':
27
- case ')':
28
- case '{':
29
- case '}':
30
- case '[':
31
- case ']':
32
- case '^':
33
- case '"':
34
- case '~':
35
- case '*':
36
- case '?':
37
- case ':':
38
- case '\\':
39
- case '/':
40
- str += '\\';
41
- }
42
- str += chr;
43
- }
44
- return str;
45
- }
46
17
  static fetchCsrf(html) {
47
18
  return {
48
19
  sessionKey: MusicBrainzApi.fetchValue(html, 'csrf_session_key'),
@@ -56,15 +27,13 @@ export class MusicBrainzApi {
56
27
  if (pos >= 0) {
57
28
  pos += 7;
58
29
  const endValuePos = html.indexOf('"', pos);
59
- const value = html.substring(pos, endValuePos);
60
- return value;
30
+ return html.substring(pos, endValuePos);
61
31
  }
62
32
  }
63
33
  }
64
34
  constructor(_config) {
65
35
  this.config = {
66
- baseUrl: 'https://musicbrainz.org',
67
- botAccount: {}
36
+ baseUrl: 'https://musicbrainz.org'
68
37
  };
69
38
  Object.assign(this.config, _config);
70
39
  const cookieJar = new CookieJar();
@@ -82,11 +51,11 @@ export class MusicBrainzApi {
82
51
  };
83
52
  this.rateLimiter = new RateLimitThreshold(15, 18);
84
53
  }
85
- async restGet(relUrl, query = {}, attempt = 1) {
54
+ async restGet(relUrl, query = {}) {
86
55
  query.fmt = 'json';
87
56
  const delay = await this.rateLimiter.limit();
88
57
  debug(`Client side rate limiter activated: cool down for ${Math.round(delay / 100) / 10} s...`);
89
- const response = await got.get('ws/2' + relUrl, {
58
+ const response = await got.get(`ws/2${relUrl}`, {
90
59
  ...this.options,
91
60
  searchParams: query,
92
61
  responseType: 'json',
@@ -110,7 +79,7 @@ export class MusicBrainzApi {
110
79
  if (Array.isArray(query.inc)) {
111
80
  urlQuery.inc = urlQuery.inc.join(' ');
112
81
  }
113
- return this.restGet('/' + entity + '/', urlQuery);
82
+ return this.restGet(`/${entity}/`, urlQuery);
114
83
  }
115
84
  // ---------------------------------------------------------------------------
116
85
  async postRecording(xmlMetadata) {
@@ -118,7 +87,7 @@ export class MusicBrainzApi {
118
87
  }
119
88
  async post(entity, xmlMetadata) {
120
89
  if (!this.config.appName || !this.config.appVersion) {
121
- throw new Error(`XML-Post requires the appName & appVersion to be defined`);
90
+ throw new Error("XML-Post requires the appName & appVersion to be defined");
122
91
  }
123
92
  const clientId = `${this.config.appName.replace(/-/g, '.')}-${this.config.appVersion}`;
124
93
  const path = `ws/2/${entity}/`;
@@ -151,9 +120,10 @@ export class MusicBrainzApi {
151
120
  } while (n++ < 5);
152
121
  }
153
122
  async login() {
154
- assert.ok(this.config.botAccount.username, 'bot username should be set');
155
- assert.ok(this.config.botAccount.password, 'bot password should be set');
156
- if (this.session && this.session.loggedIn) {
123
+ var _a, _b, _c;
124
+ assert.ok((_a = this.config.botAccount) === null || _a === void 0 ? void 0 : _a.username, 'bot username should be set');
125
+ assert.ok((_b = this.config.botAccount) === null || _b === void 0 ? void 0 : _b.password, 'bot password should be set');
126
+ if ((_c = this.session) === null || _c === void 0 ? void 0 : _c.loggedIn) {
157
127
  for (const cookie of await this.getCookies(this.options.prefixUrl)) {
158
128
  if (cookie.key === 'remember_login') {
159
129
  return true;
@@ -208,12 +178,13 @@ export class MusicBrainzApi {
208
178
  * @param formData
209
179
  */
210
180
  async editEntity(entity, mbid, formData) {
181
+ var _a, _b;
211
182
  await this.rateLimiter.limit();
212
183
  this.session = await this.getSession();
213
184
  formData.csrf_session_key = this.session.csrf.sessionKey;
214
185
  formData.csrf_token = this.session.csrf.token;
215
- formData.username = this.config.botAccount.username;
216
- formData.password = this.config.botAccount.password;
186
+ formData.username = (_a = this.config.botAccount) === null || _a === void 0 ? void 0 : _a.username;
187
+ formData.password = (_b = this.config.botAccount) === null || _b === void 0 ? void 0 : _b.password;
217
188
  formData.remember_me = 1;
218
189
  const response = await got.post(`${entity}/${mbid}/edit`, {
219
190
  ...this.options,
@@ -221,7 +192,7 @@ export class MusicBrainzApi {
221
192
  followRedirect: false
222
193
  });
223
194
  if (response.statusCode === HttpStatus.OK)
224
- throw new Error(`Failed to submit form data`);
195
+ throw new Error("Failed to submit form data");
225
196
  if (response.statusCode === HttpStatus.MOVED_TEMPORARILY)
226
197
  return;
227
198
  throw new Error(`Unexpected status code: ${response.statusCode}`);
@@ -250,11 +221,10 @@ export class MusicBrainzApi {
250
221
  * Add ISRC to recording
251
222
  * @param recording Recording to update
252
223
  * @param isrc ISRC code to add
253
- * @param editNote Edit note
254
224
  */
255
- async addIsrc(recording, isrc, editNote = '') {
225
+ async addIsrc(recording, isrc) {
256
226
  const formData = {};
257
- formData[`edit-recording.name`] = recording.title; // Required
227
+ formData["edit-recording.name"] = recording.title; // Required
258
228
  if (!recording.isrcs) {
259
229
  throw new Error('You must retrieve recording with existing ISRC values');
260
230
  }
@@ -280,13 +250,13 @@ export class MusicBrainzApi {
280
250
  assert.strictEqual(spotifyId.length, 22);
281
251
  return this.addUrlToRecording(recording, {
282
252
  linkTypeId: mb.LinkType.stream_for_free,
283
- text: 'https://open.spotify.com/track/' + spotifyId
253
+ text: `https://open.spotify.com/track/${spotifyId}`
284
254
  }, editNote);
285
255
  }
286
256
  async getSession() {
287
257
  const response = await got.get('login', {
288
258
  ...this.options,
289
- followRedirect: false,
259
+ followRedirect: false, // Disable redirects
290
260
  responseType: 'text'
291
261
  });
292
262
  return {
@@ -36,7 +36,7 @@ export interface IArtist extends IEntity {
36
36
  'gender-id'?: string;
37
37
  'life-span'?: IPeriod;
38
38
  country?: string;
39
- ipis?: any[];
39
+ ipis?: string[];
40
40
  isnis?: string[];
41
41
  aliases?: IAlias[];
42
42
  gender?: string;
@@ -200,13 +200,13 @@ export interface IUrlList extends ISearchResult {
200
200
  }
201
201
  export type RelationDirection = 'backward' | 'forward';
202
202
  export interface IRelation {
203
- 'attribute-ids': any;
203
+ 'attribute-ids': unknown[];
204
204
  direction: RelationDirection;
205
205
  'target-credit': string;
206
206
  end: null | unknown;
207
207
  'source-credit': string;
208
208
  ended: boolean;
209
- 'attribute-values': unknown;
209
+ 'attribute-values': unknown[];
210
210
  attributes?: any[];
211
211
  type: string;
212
212
  begin?: null | unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musicbrainz-api",
3
- "version": "0.14.0",
3
+ "version": "0.16.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",
@@ -34,7 +34,6 @@
34
34
  "download covers"
35
35
  ],
36
36
  "license": "MIT",
37
- "private": false,
38
37
  "engines": {
39
38
  "node": "^14.13.1 || >=16.0.0"
40
39
  },
@@ -46,55 +45,47 @@
46
45
  "url": "https://github.com/Borewit/musicbrainz-api/issues"
47
46
  },
48
47
  "dependencies": {
48
+ "@biomejs/biome": "1.8.3",
49
49
  "@types/caseless": "^0.12.1",
50
50
  "@types/request-promise-native": "^1.0.17",
51
- "@types/uuid": "^9.0.0",
51
+ "@types/uuid": "^10.0.0",
52
52
  "caseless": "^0.12.0",
53
53
  "debug": "^4.3.4",
54
- "got": "^13.0.0",
54
+ "got": "^14.2.1",
55
55
  "http-status-codes": "^2.1.4",
56
56
  "json-stringify-safe": "^5.0.1",
57
57
  "jsontoxml": "^1.0.1",
58
58
  "rate-limit-threshold": "^0.1.5",
59
59
  "source-map-support": "^0.5.16",
60
60
  "tough-cookie": "^4.1.3",
61
- "uuid": "^9.0.0"
61
+ "uuid": "^10.0.0"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@types/chai": "^4.3.0",
65
65
  "@types/jsontoxml": "^1.0.5",
66
66
  "@types/mocha": "^10.0.4",
67
- "@types/node": "^20.8.10",
68
- "@typescript-eslint/eslint-plugin": "^5.13.0",
69
- "@typescript-eslint/parser": "^5.13.0",
70
- "c8": "^8.0.1",
71
- "chai": "^4.2.0",
67
+ "@types/node": "^22.1.0",
68
+ "c8": "^10.1.2",
69
+ "chai": "^5.1.0",
72
70
  "del-cli": "^5.0.0",
73
- "eslint": "^8.10.0",
74
- "eslint-config-prettier": "^9.0.0",
75
- "eslint-import-resolver-typescript": "^3.3.0",
76
- "eslint-plugin-import": "^2.25.4",
77
- "eslint-plugin-jsdoc": "^46.8.2",
78
- "eslint-plugin-node": "^11.1.0",
79
- "eslint-plugin-unicorn": "^49.0.0",
80
71
  "mocha": "^10.1.0",
81
72
  "remark-cli": "^12.0.0",
82
- "remark-preset-lint-recommended": "^6.1.2",
73
+ "remark-preset-lint-recommended": "^7.0.0",
83
74
  "ts-node": "^10.0.0",
84
75
  "typescript": "^5.0.2"
85
76
  },
86
77
  "scripts": {
87
- "clean": "del-cli lib/**/*.js lib/**/*.js.map lib/**/*.d.ts test/**/*.js test/**/*.js.map",
78
+ "clean": "del-cli 'lib/**/*.js' 'lib/**/*.js.map' 'lib/**/*.d.ts' 'test/**/*.js' 'test/**/*.js.map'",
88
79
  "compile-lib": "tsc -p lib",
89
80
  "compile-test": "tsc -p test",
90
- "compile": "npm run compile-lib && npm run compile-test",
91
- "eslint": "eslint lib/**/*.ts --ignore-pattern lib/**/*.d.ts test/**/*.ts",
81
+ "compile": "yarn run compile-lib && yarn run compile-test",
92
82
  "lint-md": "remark -u preset-lint-recommended .",
93
- "lint": "npm run lint-md && npm run eslint",
83
+ "lint-ts": "biome check",
84
+ "lint": "yarn run lint-md && yarn run lint-ts",
94
85
  "test": "mocha",
95
- "build": "npm run clean && npm run compile",
96
- "start": "npm-run-all compile lint cover-test",
97
- "test-coverage": "c8 npm run test",
86
+ "build": "yarn run clean && yarn run compile",
87
+ "start": "yarn run compile && yarn run lint && yarn run cover-test",
88
+ "test-coverage": "c8 yarn run test",
98
89
  "send-codacy": "nyc report --reporter=text-lcov | codacy-coverage"
99
90
  },
100
91
  "nyc": {
@@ -111,5 +102,6 @@
111
102
  "text"
112
103
  ],
113
104
  "report-dir": "coverage"
114
- }
105
+ },
106
+ "packageManager": "yarn@4.1.1"
115
107
  }