@nuclearplayer/plugin-sdk 1.0.0 → 1.1.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/dist/index.d.ts CHANGED
@@ -99,6 +99,53 @@ export declare type EnumWidget = {
99
99
  type: 'radio';
100
100
  };
101
101
 
102
+ export declare type FavoriteEntry<T> = {
103
+ ref: T;
104
+ addedAtIso: string;
105
+ };
106
+
107
+ export declare class FavoritesAPI {
108
+ #private;
109
+ constructor(host?: FavoritesHost);
110
+ getTracks(): Promise<FavoriteEntry<Track>[]>;
111
+ getAlbums(): Promise<FavoriteEntry<AlbumRef>[]>;
112
+ getArtists(): Promise<FavoriteEntry<ArtistRef>[]>;
113
+ addTrack(track: Track): Promise<void>;
114
+ removeTrack(source: ProviderRef): Promise<void>;
115
+ isTrackFavorite(source: ProviderRef): Promise<boolean>;
116
+ addAlbum(ref: AlbumRef): Promise<void>;
117
+ removeAlbum(source: ProviderRef): Promise<void>;
118
+ isAlbumFavorite(source: ProviderRef): Promise<boolean>;
119
+ addArtist(ref: ArtistRef): Promise<void>;
120
+ removeArtist(source: ProviderRef): Promise<void>;
121
+ isArtistFavorite(source: ProviderRef): Promise<boolean>;
122
+ subscribe(listener: FavoritesListener): () => void;
123
+ }
124
+
125
+ export declare type FavoritesData = {
126
+ tracks: FavoriteEntry<Track>[];
127
+ albums: FavoriteEntry<AlbumRef>[];
128
+ artists: FavoriteEntry<ArtistRef>[];
129
+ };
130
+
131
+ export declare type FavoritesHost = {
132
+ getTracks: () => Promise<FavoriteEntry<Track>[]>;
133
+ getAlbums: () => Promise<FavoriteEntry<AlbumRef>[]>;
134
+ getArtists: () => Promise<FavoriteEntry<ArtistRef>[]>;
135
+ addTrack: (track: Track) => Promise<void>;
136
+ removeTrack: (source: ProviderRef) => Promise<void>;
137
+ isTrackFavorite: (source: ProviderRef) => Promise<boolean>;
138
+ addAlbum: (ref: AlbumRef) => Promise<void>;
139
+ removeAlbum: (source: ProviderRef) => Promise<void>;
140
+ isAlbumFavorite: (source: ProviderRef) => Promise<boolean>;
141
+ addArtist: (ref: ArtistRef) => Promise<void>;
142
+ removeArtist: (source: ProviderRef) => Promise<void>;
143
+ isArtistFavorite: (source: ProviderRef) => Promise<boolean>;
144
+ subscribe: (listener: FavoritesListener) => () => void;
145
+ };
146
+
147
+ export declare type FavoritesListener = (favorites: FavoritesData) => void;
148
+
102
149
  export declare type FetchFunction = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
103
150
 
104
151
  export declare class HttpAPI {
@@ -187,6 +234,7 @@ export declare class NuclearAPI {
187
234
  readonly Metadata: MetadataAPI;
188
235
  readonly Http: HttpAPI;
189
236
  readonly Ytdlp: YtdlpAPI;
237
+ readonly Favorites: FavoritesAPI;
190
238
  constructor(opts?: {
191
239
  settingsHost?: SettingsHost;
192
240
  providersHost?: ProvidersHost;
@@ -195,6 +243,7 @@ export declare class NuclearAPI {
195
243
  metadataHost?: MetadataHost;
196
244
  httpHost?: HttpHost;
197
245
  ytdlpHost?: YtdlpHost;
246
+ favoritesHost?: FavoritesHost;
198
247
  });
199
248
  }
200
249
 
package/dist/index.js CHANGED
@@ -1,5 +1,56 @@
1
1
  import { useState as l, useEffect as f, useMemo as g } from "react";
2
- const b = (s) => {
2
+ class b {
3
+ #e;
4
+ constructor(t) {
5
+ this.#e = t;
6
+ }
7
+ #t(t) {
8
+ const e = this.#e;
9
+ if (!e)
10
+ throw new Error("Favorites host not available");
11
+ return t(e);
12
+ }
13
+ getTracks() {
14
+ return this.#t((t) => t.getTracks());
15
+ }
16
+ getAlbums() {
17
+ return this.#t((t) => t.getAlbums());
18
+ }
19
+ getArtists() {
20
+ return this.#t((t) => t.getArtists());
21
+ }
22
+ addTrack(t) {
23
+ return this.#t((e) => e.addTrack(t));
24
+ }
25
+ removeTrack(t) {
26
+ return this.#t((e) => e.removeTrack(t));
27
+ }
28
+ isTrackFavorite(t) {
29
+ return this.#t((e) => e.isTrackFavorite(t));
30
+ }
31
+ addAlbum(t) {
32
+ return this.#t((e) => e.addAlbum(t));
33
+ }
34
+ removeAlbum(t) {
35
+ return this.#t((e) => e.removeAlbum(t));
36
+ }
37
+ isAlbumFavorite(t) {
38
+ return this.#t((e) => e.isAlbumFavorite(t));
39
+ }
40
+ addArtist(t) {
41
+ return this.#t((e) => e.addArtist(t));
42
+ }
43
+ removeArtist(t) {
44
+ return this.#t((e) => e.removeArtist(t));
45
+ }
46
+ isArtistFavorite(t) {
47
+ return this.#t((e) => e.isArtistFavorite(t));
48
+ }
49
+ subscribe(t) {
50
+ return this.#t((e) => e.subscribe(t));
51
+ }
52
+ }
53
+ const m = (s) => {
3
54
  if (s instanceof Headers) {
4
55
  const t = {};
5
56
  return s.forEach((e, r) => {
@@ -8,12 +59,12 @@ const b = (s) => {
8
59
  }
9
60
  return Array.isArray(s) ? Object.fromEntries(s) : s;
10
61
  };
11
- function m(s) {
62
+ function A(s) {
12
63
  return async (t, e) => {
13
- const r = String(t instanceof Request ? t.url : t), a = e?.headers ? b(e.headers) : void 0, o = typeof e?.body == "string" ? e.body : void 0, u = await s.fetch(r, {
64
+ const r = String(t instanceof Request ? t.url : t), a = e?.headers ? m(e.headers) : void 0, n = typeof e?.body == "string" ? e.body : void 0, u = await s.fetch(r, {
14
65
  method: e?.method,
15
66
  headers: a,
16
- body: o
67
+ body: n
17
68
  });
18
69
  return new Response(u.body, {
19
70
  status: u.status,
@@ -21,20 +72,20 @@ function m(s) {
21
72
  });
22
73
  };
23
74
  }
24
- const A = {
75
+ const v = {
25
76
  fetch: async () => ({
26
77
  status: 501,
27
78
  headers: {},
28
79
  body: "HTTP host not configured"
29
80
  })
30
81
  };
31
- class p {
82
+ class w {
32
83
  fetch;
33
84
  constructor(t) {
34
- this.fetch = m(t ?? A);
85
+ this.fetch = A(t ?? v);
35
86
  }
36
87
  }
37
- class v {
88
+ class T {
38
89
  #e;
39
90
  constructor(t) {
40
91
  this.#e = t;
@@ -66,7 +117,7 @@ class v {
66
117
  return this.#t((r) => r.fetchAlbumDetails(t, e));
67
118
  }
68
119
  }
69
- class w {
120
+ class p {
70
121
  #e;
71
122
  constructor(t) {
72
123
  this.#e = t;
@@ -156,7 +207,7 @@ class I {
156
207
  return this.#t((e) => e.subscribeToCurrentItem(t));
157
208
  }
158
209
  }
159
- class T {
210
+ class H {
160
211
  #e;
161
212
  constructor(t) {
162
213
  this.#e = t;
@@ -198,7 +249,7 @@ class y {
198
249
  return this.#t((e) => e.resolveStreamForCandidate(t));
199
250
  }
200
251
  }
201
- class H {
252
+ class S {
202
253
  host;
203
254
  constructor(t) {
204
255
  this.host = t;
@@ -217,7 +268,7 @@ class H {
217
268
  return this.host.getStream(t);
218
269
  }
219
270
  }
220
- class S {
271
+ class F {
221
272
  Settings;
222
273
  Providers;
223
274
  Queue;
@@ -225,12 +276,12 @@ class S {
225
276
  Metadata;
226
277
  Http;
227
278
  Ytdlp;
228
- // All these are optional so we don't have to provide all of them in tests
279
+ Favorites;
229
280
  constructor(t) {
230
- this.Settings = new T(t?.settingsHost), this.Providers = new w(t?.providersHost), this.Queue = new I(t?.queueHost), this.Streaming = new y(t?.streamingHost), this.Metadata = new v(t?.metadataHost), this.Http = new p(t?.httpHost), this.Ytdlp = new H(t?.ytdlpHost);
281
+ this.Settings = new H(t?.settingsHost), this.Providers = new p(t?.providersHost), this.Queue = new I(t?.queueHost), this.Streaming = new y(t?.streamingHost), this.Metadata = new T(t?.metadataHost), this.Http = new w(t?.httpHost), this.Ytdlp = new S(t?.ytdlpHost), this.Favorites = new b(t?.favoritesHost);
231
282
  }
232
283
  }
233
- class P extends S {
284
+ class P extends F {
234
285
  }
235
286
  class M extends Error {
236
287
  constructor(t) {
@@ -242,19 +293,19 @@ const C = (s, t) => {
242
293
  f(() => {
243
294
  if (!s)
244
295
  return;
245
- let o = !0, u = !1;
246
- const i = s.subscribe(t, (n) => {
247
- o && (u = !0, r(n));
296
+ let n = !0, u = !1;
297
+ const i = s.subscribe(t, (o) => {
298
+ n && (u = !0, r(o));
248
299
  });
249
- return s.get(t).then((n) => {
250
- o && (u || r(n));
300
+ return s.get(t).then((o) => {
301
+ n && (u || r(o));
251
302
  }), () => {
252
- o = !1, i && i();
303
+ n = !1, i && i();
253
304
  };
254
305
  }, [t, s]);
255
306
  const a = g(
256
- () => (o) => {
257
- s && s.set(t, o);
307
+ () => (n) => {
308
+ s && s.set(t, n);
258
309
  },
259
310
  [t, s]
260
311
  );
@@ -280,19 +331,20 @@ function R(s, t, e) {
280
331
  }
281
332
  })(t);
282
333
  return r.map((i) => {
283
- const n = Math.min(i.width || 0, i.height || 0), h = Math.abs(a(i) - u), c = Math.abs(n - e), d = n < e ? e / n : 1;
334
+ const o = Math.min(i.width || 0, i.height || 0), h = Math.abs(a(i) - u), c = Math.abs(o - e), d = o < e ? e / o : 1;
284
335
  return {
285
336
  artwork: i,
286
337
  score: (d > 1.5 ? -1e3 : 0) + -h * 50 + -c * 0.1
287
338
  };
288
- }).sort((i, n) => n.score - i.score)[0]?.artwork;
339
+ }).sort((i, o) => o.score - i.score)[0]?.artwork;
289
340
  }
290
341
  export {
291
- p as HttpAPI,
342
+ b as FavoritesAPI,
343
+ w as HttpAPI,
292
344
  M as MissingCapabilityError,
293
- S as NuclearAPI,
345
+ F as NuclearAPI,
294
346
  P as NuclearPluginAPI,
295
- H as YtdlpAPI,
347
+ S as YtdlpAPI,
296
348
  R as pickArtwork,
297
349
  C as useSetting
298
350
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuclearplayer/plugin-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Plugin SDK for Nuclear music player",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,8 +38,8 @@
38
38
  "vite": "^7.1.3",
39
39
  "vite-plugin-dts": "^4.5.4",
40
40
  "vitest": "^3.2.4",
41
- "@nuclearplayer/tailwind-config": "0.0.10",
42
- "@nuclearplayer/eslint-config": "0.0.10"
41
+ "@nuclearplayer/eslint-config": "0.0.10",
42
+ "@nuclearplayer/tailwind-config": "0.0.10"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "react": "^18.3.1"