@nuclearplayer/plugin-sdk 1.0.0 → 1.2.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 +68 -0
- package/dist/index.js +152 -70
- package/package.json +3 -3
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 {
|
|
@@ -139,6 +186,23 @@ export declare type LocalFileInfo = {
|
|
|
139
186
|
scannedAtIso?: string;
|
|
140
187
|
};
|
|
141
188
|
|
|
189
|
+
export declare class LoggerAPI {
|
|
190
|
+
private host;
|
|
191
|
+
constructor(host?: LoggerHost);
|
|
192
|
+
trace(message: string): void;
|
|
193
|
+
debug(message: string): void;
|
|
194
|
+
info(message: string): void;
|
|
195
|
+
warn(message: string): void;
|
|
196
|
+
error(message: string): void;
|
|
197
|
+
log(level: LogLevel, message: string): void;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export declare type LoggerHost = {
|
|
201
|
+
log: (level: LogLevel, message: string) => void;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
export declare type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
|
|
205
|
+
|
|
142
206
|
declare class MetadataAPI {
|
|
143
207
|
#private;
|
|
144
208
|
constructor(host?: MetadataHost);
|
|
@@ -187,6 +251,8 @@ export declare class NuclearAPI {
|
|
|
187
251
|
readonly Metadata: MetadataAPI;
|
|
188
252
|
readonly Http: HttpAPI;
|
|
189
253
|
readonly Ytdlp: YtdlpAPI;
|
|
254
|
+
readonly Favorites: FavoritesAPI;
|
|
255
|
+
readonly Logger: LoggerAPI;
|
|
190
256
|
constructor(opts?: {
|
|
191
257
|
settingsHost?: SettingsHost;
|
|
192
258
|
providersHost?: ProvidersHost;
|
|
@@ -195,6 +261,8 @@ export declare class NuclearAPI {
|
|
|
195
261
|
metadataHost?: MetadataHost;
|
|
196
262
|
httpHost?: HttpHost;
|
|
197
263
|
ytdlpHost?: YtdlpHost;
|
|
264
|
+
favoritesHost?: FavoritesHost;
|
|
265
|
+
loggerHost?: LoggerHost;
|
|
198
266
|
});
|
|
199
267
|
}
|
|
200
268
|
|
package/dist/index.js
CHANGED
|
@@ -1,40 +1,119 @@
|
|
|
1
|
-
import { useState as l, useEffect as
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { useState as l, useEffect as g, useMemo as f } from "react";
|
|
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 = (r) => {
|
|
54
|
+
if (r instanceof Headers) {
|
|
4
55
|
const t = {};
|
|
5
|
-
return
|
|
6
|
-
t[
|
|
56
|
+
return r.forEach((e, s) => {
|
|
57
|
+
t[s] = e;
|
|
7
58
|
}), t;
|
|
8
59
|
}
|
|
9
|
-
return Array.isArray(
|
|
60
|
+
return Array.isArray(r) ? Object.fromEntries(r) : r;
|
|
10
61
|
};
|
|
11
|
-
function
|
|
62
|
+
function A(r) {
|
|
12
63
|
return async (t, e) => {
|
|
13
|
-
const
|
|
64
|
+
const s = String(t instanceof Request ? t.url : t), u = e?.headers ? m(e.headers) : void 0, n = typeof e?.body == "string" ? e.body : void 0, a = await r.fetch(s, {
|
|
14
65
|
method: e?.method,
|
|
15
|
-
headers:
|
|
16
|
-
body:
|
|
66
|
+
headers: u,
|
|
67
|
+
body: n
|
|
17
68
|
});
|
|
18
|
-
return new Response(
|
|
19
|
-
status:
|
|
20
|
-
headers: new Headers(
|
|
69
|
+
return new Response(a.body, {
|
|
70
|
+
status: a.status,
|
|
71
|
+
headers: new Headers(a.headers)
|
|
21
72
|
});
|
|
22
73
|
};
|
|
23
74
|
}
|
|
24
|
-
const
|
|
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
|
|
82
|
+
class w {
|
|
32
83
|
fetch;
|
|
33
84
|
constructor(t) {
|
|
34
|
-
this.fetch =
|
|
85
|
+
this.fetch = A(t ?? v);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const T = {
|
|
89
|
+
log: () => {
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
class p {
|
|
93
|
+
host;
|
|
94
|
+
constructor(t) {
|
|
95
|
+
this.host = t ?? T;
|
|
96
|
+
}
|
|
97
|
+
trace(t) {
|
|
98
|
+
this.host.log("trace", t);
|
|
99
|
+
}
|
|
100
|
+
debug(t) {
|
|
101
|
+
this.host.log("debug", t);
|
|
102
|
+
}
|
|
103
|
+
info(t) {
|
|
104
|
+
this.host.log("info", t);
|
|
105
|
+
}
|
|
106
|
+
warn(t) {
|
|
107
|
+
this.host.log("warn", t);
|
|
108
|
+
}
|
|
109
|
+
error(t) {
|
|
110
|
+
this.host.log("error", t);
|
|
111
|
+
}
|
|
112
|
+
log(t, e) {
|
|
113
|
+
this.host.log(t, e);
|
|
35
114
|
}
|
|
36
115
|
}
|
|
37
|
-
class
|
|
116
|
+
class I {
|
|
38
117
|
#e;
|
|
39
118
|
constructor(t) {
|
|
40
119
|
this.#e = t;
|
|
@@ -46,27 +125,27 @@ class v {
|
|
|
46
125
|
return t(e);
|
|
47
126
|
}
|
|
48
127
|
search(t, e) {
|
|
49
|
-
return this.#t((
|
|
128
|
+
return this.#t((s) => s.search(t, e));
|
|
50
129
|
}
|
|
51
130
|
fetchArtistDetails(t, e) {
|
|
52
|
-
return this.#t((
|
|
131
|
+
return this.#t((s) => s.fetchArtistDetails(t, e));
|
|
53
132
|
}
|
|
54
133
|
fetchArtistAlbums(t, e) {
|
|
55
|
-
return this.#t((
|
|
134
|
+
return this.#t((s) => s.fetchArtistAlbums(t, e));
|
|
56
135
|
}
|
|
57
136
|
fetchArtistTopTracks(t, e) {
|
|
58
|
-
return this.#t((
|
|
137
|
+
return this.#t((s) => s.fetchArtistTopTracks(t, e));
|
|
59
138
|
}
|
|
60
139
|
fetchArtistRelatedArtists(t, e) {
|
|
61
140
|
return this.#t(
|
|
62
|
-
(
|
|
141
|
+
(s) => s.fetchArtistRelatedArtists(t, e)
|
|
63
142
|
);
|
|
64
143
|
}
|
|
65
144
|
fetchAlbumDetails(t, e) {
|
|
66
|
-
return this.#t((
|
|
145
|
+
return this.#t((s) => s.fetchAlbumDetails(t, e));
|
|
67
146
|
}
|
|
68
147
|
}
|
|
69
|
-
class
|
|
148
|
+
class H {
|
|
70
149
|
#e;
|
|
71
150
|
constructor(t) {
|
|
72
151
|
this.#e = t;
|
|
@@ -90,7 +169,7 @@ class w {
|
|
|
90
169
|
return this.#t((e) => e.get(t));
|
|
91
170
|
}
|
|
92
171
|
}
|
|
93
|
-
class
|
|
172
|
+
class y {
|
|
94
173
|
#e;
|
|
95
174
|
constructor(t) {
|
|
96
175
|
this.#e = t;
|
|
@@ -114,7 +193,7 @@ class I {
|
|
|
114
193
|
return this.#t((e) => e.addNext(t));
|
|
115
194
|
}
|
|
116
195
|
addAt(t, e) {
|
|
117
|
-
return this.#t((
|
|
196
|
+
return this.#t((s) => s.addAt(t, e));
|
|
118
197
|
}
|
|
119
198
|
removeByIds(t) {
|
|
120
199
|
return this.#t((e) => e.removeByIds(t));
|
|
@@ -126,10 +205,10 @@ class I {
|
|
|
126
205
|
return this.#t((t) => t.clearQueue());
|
|
127
206
|
}
|
|
128
207
|
reorder(t, e) {
|
|
129
|
-
return this.#t((
|
|
208
|
+
return this.#t((s) => s.reorder(t, e));
|
|
130
209
|
}
|
|
131
210
|
updateItemState(t, e) {
|
|
132
|
-
return this.#t((
|
|
211
|
+
return this.#t((s) => s.updateItemState(t, e));
|
|
133
212
|
}
|
|
134
213
|
goToNext() {
|
|
135
214
|
return this.#t((t) => t.goToNext());
|
|
@@ -156,7 +235,7 @@ class I {
|
|
|
156
235
|
return this.#t((e) => e.subscribeToCurrentItem(t));
|
|
157
236
|
}
|
|
158
237
|
}
|
|
159
|
-
class
|
|
238
|
+
class S {
|
|
160
239
|
#e;
|
|
161
240
|
constructor(t) {
|
|
162
241
|
this.#e = t;
|
|
@@ -174,13 +253,13 @@ class T {
|
|
|
174
253
|
return this.#t((e) => e.get(t));
|
|
175
254
|
}
|
|
176
255
|
set(t, e) {
|
|
177
|
-
return this.#t((
|
|
256
|
+
return this.#t((s) => s.set(t, e));
|
|
178
257
|
}
|
|
179
258
|
subscribe(t, e) {
|
|
180
|
-
return this.#t((
|
|
259
|
+
return this.#t((s) => s.subscribe(t, e));
|
|
181
260
|
}
|
|
182
261
|
}
|
|
183
|
-
class
|
|
262
|
+
class F {
|
|
184
263
|
#e;
|
|
185
264
|
constructor(t) {
|
|
186
265
|
this.#e = t;
|
|
@@ -198,7 +277,7 @@ class y {
|
|
|
198
277
|
return this.#t((e) => e.resolveStreamForCandidate(t));
|
|
199
278
|
}
|
|
200
279
|
}
|
|
201
|
-
class
|
|
280
|
+
class P {
|
|
202
281
|
host;
|
|
203
282
|
constructor(t) {
|
|
204
283
|
this.host = t;
|
|
@@ -217,7 +296,7 @@ class H {
|
|
|
217
296
|
return this.host.getStream(t);
|
|
218
297
|
}
|
|
219
298
|
}
|
|
220
|
-
class
|
|
299
|
+
class E {
|
|
221
300
|
Settings;
|
|
222
301
|
Providers;
|
|
223
302
|
Queue;
|
|
@@ -225,48 +304,49 @@ class S {
|
|
|
225
304
|
Metadata;
|
|
226
305
|
Http;
|
|
227
306
|
Ytdlp;
|
|
228
|
-
|
|
307
|
+
Favorites;
|
|
308
|
+
Logger;
|
|
229
309
|
constructor(t) {
|
|
230
|
-
this.Settings = new
|
|
310
|
+
this.Settings = new S(t?.settingsHost), this.Providers = new H(t?.providersHost), this.Queue = new y(t?.queueHost), this.Streaming = new F(t?.streamingHost), this.Metadata = new I(t?.metadataHost), this.Http = new w(t?.httpHost), this.Ytdlp = new P(t?.ytdlpHost), this.Favorites = new b(t?.favoritesHost), this.Logger = new p(t?.loggerHost);
|
|
231
311
|
}
|
|
232
312
|
}
|
|
233
|
-
class
|
|
313
|
+
class C extends E {
|
|
234
314
|
}
|
|
235
|
-
class
|
|
315
|
+
class R extends Error {
|
|
236
316
|
constructor(t) {
|
|
237
317
|
super(`Missing capability: ${t}`), this.name = "MissingCapabilityError";
|
|
238
318
|
}
|
|
239
319
|
}
|
|
240
|
-
const
|
|
241
|
-
const [e,
|
|
242
|
-
|
|
243
|
-
if (!
|
|
320
|
+
const k = (r, t) => {
|
|
321
|
+
const [e, s] = l(void 0);
|
|
322
|
+
g(() => {
|
|
323
|
+
if (!r)
|
|
244
324
|
return;
|
|
245
|
-
let
|
|
246
|
-
const i =
|
|
247
|
-
|
|
325
|
+
let n = !0, a = !1;
|
|
326
|
+
const i = r.subscribe(t, (o) => {
|
|
327
|
+
n && (a = !0, s(o));
|
|
248
328
|
});
|
|
249
|
-
return
|
|
250
|
-
|
|
329
|
+
return r.get(t).then((o) => {
|
|
330
|
+
n && (a || s(o));
|
|
251
331
|
}), () => {
|
|
252
|
-
|
|
332
|
+
n = !1, i && i();
|
|
253
333
|
};
|
|
254
|
-
}, [t,
|
|
255
|
-
const
|
|
256
|
-
() => (
|
|
257
|
-
|
|
334
|
+
}, [t, r]);
|
|
335
|
+
const u = f(
|
|
336
|
+
() => (n) => {
|
|
337
|
+
r && r.set(t, n);
|
|
258
338
|
},
|
|
259
|
-
[t,
|
|
339
|
+
[t, r]
|
|
260
340
|
);
|
|
261
|
-
return [e,
|
|
341
|
+
return [e, u];
|
|
262
342
|
};
|
|
263
|
-
function
|
|
264
|
-
if (!
|
|
343
|
+
function Q(r, t, e) {
|
|
344
|
+
if (!r?.items?.length)
|
|
265
345
|
return;
|
|
266
|
-
const
|
|
267
|
-
if (!
|
|
268
|
-
return
|
|
269
|
-
const
|
|
346
|
+
const s = r.items.filter((i) => !(i.purpose && i.purpose !== t || !i.url));
|
|
347
|
+
if (!s.length)
|
|
348
|
+
return r.items[0];
|
|
349
|
+
const u = (i) => !i.width || !i.height ? 1 : i.width / i.height, a = ((i) => {
|
|
270
350
|
switch (i) {
|
|
271
351
|
case "avatar":
|
|
272
352
|
case "thumbnail":
|
|
@@ -279,20 +359,22 @@ function R(s, t, e) {
|
|
|
279
359
|
return 1;
|
|
280
360
|
}
|
|
281
361
|
})(t);
|
|
282
|
-
return
|
|
283
|
-
const
|
|
362
|
+
return s.map((i) => {
|
|
363
|
+
const o = Math.min(i.width || 0, i.height || 0), h = Math.abs(u(i) - a), c = Math.abs(o - e), d = o < e ? e / o : 1;
|
|
284
364
|
return {
|
|
285
365
|
artwork: i,
|
|
286
366
|
score: (d > 1.5 ? -1e3 : 0) + -h * 50 + -c * 0.1
|
|
287
367
|
};
|
|
288
|
-
}).sort((i,
|
|
368
|
+
}).sort((i, o) => o.score - i.score)[0]?.artwork;
|
|
289
369
|
}
|
|
290
370
|
export {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
371
|
+
b as FavoritesAPI,
|
|
372
|
+
w as HttpAPI,
|
|
373
|
+
p as LoggerAPI,
|
|
374
|
+
R as MissingCapabilityError,
|
|
375
|
+
E as NuclearAPI,
|
|
376
|
+
C as NuclearPluginAPI,
|
|
377
|
+
P as YtdlpAPI,
|
|
378
|
+
Q as pickArtwork,
|
|
379
|
+
k as useSetting
|
|
298
380
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuclearplayer/plugin-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.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/
|
|
42
|
-
"@nuclearplayer/
|
|
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"
|