@nuclearplayer/plugin-sdk 0.0.14 → 1.0.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 +190 -13
- package/dist/index.js +212 -34
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export declare type Album = {
|
|
|
11
11
|
source: ProviderRef;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
+
export declare type AlbumMetadataCapability = 'albumDetails';
|
|
15
|
+
|
|
14
16
|
export declare type AlbumRef = {
|
|
15
17
|
title: string;
|
|
16
18
|
artists?: ArtistRef[];
|
|
@@ -97,6 +99,29 @@ export declare type EnumWidget = {
|
|
|
97
99
|
type: 'radio';
|
|
98
100
|
};
|
|
99
101
|
|
|
102
|
+
export declare type FetchFunction = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
103
|
+
|
|
104
|
+
export declare class HttpAPI {
|
|
105
|
+
readonly fetch: FetchFunction;
|
|
106
|
+
constructor(host?: HttpHost);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export declare type HttpHost = {
|
|
110
|
+
fetch: (url: string, init?: HttpRequestInit) => Promise<HttpResponseData>;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export declare type HttpRequestInit = {
|
|
114
|
+
method?: string;
|
|
115
|
+
headers?: Record<string, string>;
|
|
116
|
+
body?: string;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export declare type HttpResponseData = {
|
|
120
|
+
status: number;
|
|
121
|
+
headers: Record<string, string>;
|
|
122
|
+
body: string;
|
|
123
|
+
};
|
|
124
|
+
|
|
100
125
|
export declare type LoadedPlugin = {
|
|
101
126
|
metadata: PluginMetadata;
|
|
102
127
|
instance: NuclearPlugin;
|
|
@@ -114,9 +139,30 @@ export declare type LocalFileInfo = {
|
|
|
114
139
|
scannedAtIso?: string;
|
|
115
140
|
};
|
|
116
141
|
|
|
142
|
+
declare class MetadataAPI {
|
|
143
|
+
#private;
|
|
144
|
+
constructor(host?: MetadataHost);
|
|
145
|
+
search(params: SearchParams, providerId?: string): Promise<SearchResults>;
|
|
146
|
+
fetchArtistDetails(artistId: string, providerId?: string): Promise<Artist>;
|
|
147
|
+
fetchArtistAlbums(artistId: string, providerId?: string): Promise<AlbumRef[]>;
|
|
148
|
+
fetchArtistTopTracks(artistId: string, providerId?: string): Promise<TrackRef[]>;
|
|
149
|
+
fetchArtistRelatedArtists(artistId: string, providerId?: string): Promise<ArtistRef[]>;
|
|
150
|
+
fetchAlbumDetails(albumId: string, providerId?: string): Promise<Album>;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export declare type MetadataHost = {
|
|
154
|
+
search: (params: SearchParams, providerId?: string) => Promise<SearchResults>;
|
|
155
|
+
fetchArtistDetails: (artistId: string, providerId?: string) => Promise<Artist>;
|
|
156
|
+
fetchArtistAlbums: (artistId: string, providerId?: string) => Promise<AlbumRef[]>;
|
|
157
|
+
fetchArtistTopTracks: (artistId: string, providerId?: string) => Promise<TrackRef[]>;
|
|
158
|
+
fetchArtistRelatedArtists: (artistId: string, providerId?: string) => Promise<ArtistRef[]>;
|
|
159
|
+
fetchAlbumDetails: (albumId: string, providerId?: string) => Promise<Album>;
|
|
160
|
+
};
|
|
161
|
+
|
|
117
162
|
export declare type MetadataProvider = ProviderDescriptor<'metadata'> & {
|
|
118
163
|
searchCapabilities?: SearchCapability[];
|
|
119
164
|
artistMetadataCapabilities?: ArtistMetadataCapability[];
|
|
165
|
+
albumMetadataCapabilities?: AlbumMetadataCapability[];
|
|
120
166
|
search?: (params: SearchParams) => Promise<SearchResults>;
|
|
121
167
|
searchArtists?: (params: Omit<SearchParams, 'types'>) => Promise<ArtistRef[]>;
|
|
122
168
|
searchAlbums?: (params: Omit<SearchParams, 'types'>) => Promise<AlbumRef[]>;
|
|
@@ -136,17 +182,27 @@ export declare class MissingCapabilityError extends Error {
|
|
|
136
182
|
export declare class NuclearAPI {
|
|
137
183
|
readonly Settings: Settings;
|
|
138
184
|
readonly Providers: Providers;
|
|
185
|
+
readonly Queue: QueueAPI;
|
|
186
|
+
readonly Streaming: StreamingAPI;
|
|
187
|
+
readonly Metadata: MetadataAPI;
|
|
188
|
+
readonly Http: HttpAPI;
|
|
189
|
+
readonly Ytdlp: YtdlpAPI;
|
|
139
190
|
constructor(opts?: {
|
|
140
191
|
settingsHost?: SettingsHost;
|
|
141
192
|
providersHost?: ProvidersHost;
|
|
193
|
+
queueHost?: QueueHost;
|
|
194
|
+
streamingHost?: StreamingHost;
|
|
195
|
+
metadataHost?: MetadataHost;
|
|
196
|
+
httpHost?: HttpHost;
|
|
197
|
+
ytdlpHost?: YtdlpHost;
|
|
142
198
|
});
|
|
143
199
|
}
|
|
144
200
|
|
|
145
201
|
export declare type NuclearPlugin = {
|
|
146
202
|
onLoad?(api: NuclearPluginAPI): void | Promise<void>;
|
|
147
|
-
onUnload?(): void | Promise<void>;
|
|
203
|
+
onUnload?(api: NuclearPluginAPI): void | Promise<void>;
|
|
148
204
|
onEnable?(api: NuclearPluginAPI): void | Promise<void>;
|
|
149
|
-
onDisable?(): void | Promise<void>;
|
|
205
|
+
onDisable?(api: NuclearPluginAPI): void | Promise<void>;
|
|
150
206
|
};
|
|
151
207
|
|
|
152
208
|
export declare class NuclearPluginAPI extends NuclearAPI {
|
|
@@ -273,18 +329,76 @@ export declare type ProvidersHost = {
|
|
|
273
329
|
clear(): void;
|
|
274
330
|
};
|
|
275
331
|
|
|
332
|
+
export declare type Queue = {
|
|
333
|
+
items: QueueItem[];
|
|
334
|
+
currentIndex: number;
|
|
335
|
+
repeatMode: RepeatMode;
|
|
336
|
+
shuffleEnabled: boolean;
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
declare class QueueAPI {
|
|
340
|
+
#private;
|
|
341
|
+
constructor(host?: QueueHost);
|
|
342
|
+
getQueue(): Promise<Queue>;
|
|
343
|
+
getCurrentItem(): Promise<QueueItem | undefined>;
|
|
344
|
+
addToQueue(tracks: Track[]): Promise<void>;
|
|
345
|
+
addNext(tracks: Track[]): Promise<void>;
|
|
346
|
+
addAt(tracks: Track[], index: number): Promise<void>;
|
|
347
|
+
removeByIds(ids: string[]): Promise<void>;
|
|
348
|
+
removeByIndices(indices: number[]): Promise<void>;
|
|
349
|
+
clearQueue(): Promise<void>;
|
|
350
|
+
reorder(fromIndex: number, toIndex: number): Promise<void>;
|
|
351
|
+
updateItemState(id: string, updates: QueueItemStateUpdate): Promise<void>;
|
|
352
|
+
goToNext(): Promise<void>;
|
|
353
|
+
goToPrevious(): Promise<void>;
|
|
354
|
+
goToIndex(index: number): Promise<void>;
|
|
355
|
+
goToId(id: string): Promise<void>;
|
|
356
|
+
setRepeatMode(mode: RepeatMode): Promise<void>;
|
|
357
|
+
setShuffleEnabled(enabled: boolean): Promise<void>;
|
|
358
|
+
subscribe(listener: (queue: Queue) => void): () => void;
|
|
359
|
+
subscribeToCurrentItem(listener: (item: QueueItem | undefined) => void): () => void;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export declare type QueueHost = {
|
|
363
|
+
getQueue: () => Promise<Queue>;
|
|
364
|
+
getCurrentItem: () => Promise<QueueItem | undefined>;
|
|
365
|
+
addToQueue: (tracks: Track[]) => Promise<void>;
|
|
366
|
+
addNext: (tracks: Track[]) => Promise<void>;
|
|
367
|
+
addAt: (tracks: Track[], index: number) => Promise<void>;
|
|
368
|
+
removeByIds: (ids: string[]) => Promise<void>;
|
|
369
|
+
removeByIndices: (indices: number[]) => Promise<void>;
|
|
370
|
+
clearQueue: () => Promise<void>;
|
|
371
|
+
reorder: (fromIndex: number, toIndex: number) => Promise<void>;
|
|
372
|
+
updateItemState: (id: string, updates: QueueItemStateUpdate) => Promise<void>;
|
|
373
|
+
goToNext: () => Promise<void>;
|
|
374
|
+
goToPrevious: () => Promise<void>;
|
|
375
|
+
goToIndex: (index: number) => Promise<void>;
|
|
376
|
+
goToId: (id: string) => Promise<void>;
|
|
377
|
+
setRepeatMode: (mode: RepeatMode) => Promise<void>;
|
|
378
|
+
setShuffleEnabled: (enabled: boolean) => Promise<void>;
|
|
379
|
+
subscribe: (listener: QueueListener) => () => void;
|
|
380
|
+
subscribeToCurrentItem: (listener: QueueItemListener) => () => void;
|
|
381
|
+
};
|
|
382
|
+
|
|
276
383
|
export declare type QueueItem = {
|
|
277
384
|
id: string;
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
artwork?: ArtworkSet;
|
|
283
|
-
note?: string;
|
|
284
|
-
addedAtIso?: string;
|
|
285
|
-
source: ProviderRef;
|
|
385
|
+
track: Track;
|
|
386
|
+
status: 'idle' | 'loading' | 'success' | 'error';
|
|
387
|
+
error?: string;
|
|
388
|
+
addedAtIso: string;
|
|
286
389
|
};
|
|
287
390
|
|
|
391
|
+
export declare type QueueItemListener = (item: QueueItem | undefined) => void;
|
|
392
|
+
|
|
393
|
+
export declare type QueueItemStateUpdate = Partial<{
|
|
394
|
+
status: QueueItem['status'];
|
|
395
|
+
error: QueueItem['error'];
|
|
396
|
+
}>;
|
|
397
|
+
|
|
398
|
+
export declare type QueueListener = (queue: Queue) => void;
|
|
399
|
+
|
|
400
|
+
export declare type RepeatMode = 'off' | 'all' | 'one';
|
|
401
|
+
|
|
288
402
|
export declare type SearchCapability = SearchCategory | 'unified';
|
|
289
403
|
|
|
290
404
|
export declare type SearchCategory = 'artists' | 'albums' | 'tracks' | 'playlists';
|
|
@@ -309,14 +423,14 @@ export declare type SettingDefinition = BooleanSettingDefinition | NumberSetting
|
|
|
309
423
|
declare class Settings {
|
|
310
424
|
#private;
|
|
311
425
|
constructor(host?: SettingsHost);
|
|
312
|
-
register(defs: SettingDefinition[]
|
|
426
|
+
register(defs: SettingDefinition[]): Promise<SettingsRegistrationResult>;
|
|
313
427
|
get<T extends SettingValue = SettingValue>(id: string): Promise<T | undefined>;
|
|
314
428
|
set<T extends SettingValue = SettingValue>(id: string, value: T): Promise<void>;
|
|
315
429
|
subscribe<T extends SettingValue = SettingValue>(id: string, listener: (value: T | undefined) => void): () => void;
|
|
316
430
|
}
|
|
317
431
|
|
|
318
432
|
export declare type SettingsHost = {
|
|
319
|
-
register(defs: SettingDefinition[]
|
|
433
|
+
register(defs: SettingDefinition[]): Promise<SettingsRegistrationResult>;
|
|
320
434
|
get<T extends SettingValue = SettingValue>(id: string): Promise<T | undefined>;
|
|
321
435
|
set<T extends SettingValue = SettingValue>(id: string, value: T): Promise<void>;
|
|
322
436
|
subscribe<T extends SettingValue = SettingValue>(id: string, listener: (value: T | undefined) => void): () => void;
|
|
@@ -353,6 +467,43 @@ export declare type Stream = {
|
|
|
353
467
|
source: ProviderRef;
|
|
354
468
|
};
|
|
355
469
|
|
|
470
|
+
export declare type StreamCandidate = {
|
|
471
|
+
id: string;
|
|
472
|
+
title: string;
|
|
473
|
+
durationMs?: number;
|
|
474
|
+
thumbnail?: string;
|
|
475
|
+
stream?: Stream;
|
|
476
|
+
lastResolvedAtIso?: string;
|
|
477
|
+
failed: boolean;
|
|
478
|
+
source: ProviderRef;
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
declare class StreamingAPI {
|
|
482
|
+
#private;
|
|
483
|
+
constructor(host?: StreamingHost);
|
|
484
|
+
resolveCandidatesForTrack(track: Track): Promise<StreamResolutionResult>;
|
|
485
|
+
resolveStreamForCandidate(candidate: StreamCandidate): Promise<StreamCandidate | undefined>;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export declare type StreamingHost = {
|
|
489
|
+
resolveCandidatesForTrack: (track: Track) => Promise<StreamResolutionResult>;
|
|
490
|
+
resolveStreamForCandidate: (candidate: StreamCandidate) => Promise<StreamCandidate | undefined>;
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
export declare type StreamingProvider = ProviderDescriptor<'streaming'> & {
|
|
494
|
+
searchForTrack: (artist: string, title: string, album?: string) => Promise<StreamCandidate[]>;
|
|
495
|
+
getStreamUrl: (candidateId: string) => Promise<Stream>;
|
|
496
|
+
supportsLocalFiles?: boolean;
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
export declare type StreamResolutionResult = {
|
|
500
|
+
success: true;
|
|
501
|
+
candidates: StreamCandidate[];
|
|
502
|
+
} | {
|
|
503
|
+
success: false;
|
|
504
|
+
error: string;
|
|
505
|
+
};
|
|
506
|
+
|
|
356
507
|
export declare type StringFormat = 'text' | 'url' | 'path' | 'token' | 'language';
|
|
357
508
|
|
|
358
509
|
export declare type StringSettingDefinition = {
|
|
@@ -394,7 +545,7 @@ export declare type Track = {
|
|
|
394
545
|
tags?: string[];
|
|
395
546
|
source: ProviderRef;
|
|
396
547
|
localFile?: LocalFileInfo;
|
|
397
|
-
|
|
548
|
+
streamCandidates?: StreamCandidate[];
|
|
398
549
|
};
|
|
399
550
|
|
|
400
551
|
export declare type TrackRef = {
|
|
@@ -406,4 +557,30 @@ export declare type TrackRef = {
|
|
|
406
557
|
|
|
407
558
|
export declare const useSetting: <T extends SettingValue = SettingValue>(host: SettingsHost | undefined, id: string) => readonly [T | undefined, (nextValue: T) => void];
|
|
408
559
|
|
|
560
|
+
export declare class YtdlpAPI {
|
|
561
|
+
private host?;
|
|
562
|
+
constructor(host?: YtdlpHost);
|
|
563
|
+
get available(): boolean;
|
|
564
|
+
search(query: string, maxResults?: number): Promise<YtdlpSearchResult[]>;
|
|
565
|
+
getStream(videoId: string): Promise<YtdlpStreamInfo>;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
export declare type YtdlpHost = {
|
|
569
|
+
search: (query: string, maxResults?: number) => Promise<YtdlpSearchResult[]>;
|
|
570
|
+
getStream: (videoId: string) => Promise<YtdlpStreamInfo>;
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
export declare type YtdlpSearchResult = {
|
|
574
|
+
id: string;
|
|
575
|
+
title: string;
|
|
576
|
+
duration: number | null;
|
|
577
|
+
thumbnail: string | null;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
export declare type YtdlpStreamInfo = {
|
|
581
|
+
stream_url: string;
|
|
582
|
+
duration: number | null;
|
|
583
|
+
title: string | null;
|
|
584
|
+
};
|
|
585
|
+
|
|
409
586
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
|
-
import { useState as
|
|
1
|
+
import { useState as l, useEffect as f, useMemo as g } from "react";
|
|
2
|
+
const b = (s) => {
|
|
3
|
+
if (s instanceof Headers) {
|
|
4
|
+
const t = {};
|
|
5
|
+
return s.forEach((e, r) => {
|
|
6
|
+
t[r] = e;
|
|
7
|
+
}), t;
|
|
8
|
+
}
|
|
9
|
+
return Array.isArray(s) ? Object.fromEntries(s) : s;
|
|
10
|
+
};
|
|
11
|
+
function m(s) {
|
|
12
|
+
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, {
|
|
14
|
+
method: e?.method,
|
|
15
|
+
headers: a,
|
|
16
|
+
body: o
|
|
17
|
+
});
|
|
18
|
+
return new Response(u.body, {
|
|
19
|
+
status: u.status,
|
|
20
|
+
headers: new Headers(u.headers)
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const A = {
|
|
25
|
+
fetch: async () => ({
|
|
26
|
+
status: 501,
|
|
27
|
+
headers: {},
|
|
28
|
+
body: "HTTP host not configured"
|
|
29
|
+
})
|
|
30
|
+
};
|
|
2
31
|
class p {
|
|
32
|
+
fetch;
|
|
33
|
+
constructor(t) {
|
|
34
|
+
this.fetch = m(t ?? A);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
class v {
|
|
38
|
+
#e;
|
|
39
|
+
constructor(t) {
|
|
40
|
+
this.#e = t;
|
|
41
|
+
}
|
|
42
|
+
#t(t) {
|
|
43
|
+
const e = this.#e;
|
|
44
|
+
if (!e)
|
|
45
|
+
throw new Error("Metadata host not available");
|
|
46
|
+
return t(e);
|
|
47
|
+
}
|
|
48
|
+
search(t, e) {
|
|
49
|
+
return this.#t((r) => r.search(t, e));
|
|
50
|
+
}
|
|
51
|
+
fetchArtistDetails(t, e) {
|
|
52
|
+
return this.#t((r) => r.fetchArtistDetails(t, e));
|
|
53
|
+
}
|
|
54
|
+
fetchArtistAlbums(t, e) {
|
|
55
|
+
return this.#t((r) => r.fetchArtistAlbums(t, e));
|
|
56
|
+
}
|
|
57
|
+
fetchArtistTopTracks(t, e) {
|
|
58
|
+
return this.#t((r) => r.fetchArtistTopTracks(t, e));
|
|
59
|
+
}
|
|
60
|
+
fetchArtistRelatedArtists(t, e) {
|
|
61
|
+
return this.#t(
|
|
62
|
+
(r) => r.fetchArtistRelatedArtists(t, e)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
fetchAlbumDetails(t, e) {
|
|
66
|
+
return this.#t((r) => r.fetchAlbumDetails(t, e));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
class w {
|
|
3
70
|
#e;
|
|
4
71
|
constructor(t) {
|
|
5
72
|
this.#e = t;
|
|
@@ -23,7 +90,73 @@ class p {
|
|
|
23
90
|
return this.#t((e) => e.get(t));
|
|
24
91
|
}
|
|
25
92
|
}
|
|
26
|
-
class
|
|
93
|
+
class I {
|
|
94
|
+
#e;
|
|
95
|
+
constructor(t) {
|
|
96
|
+
this.#e = t;
|
|
97
|
+
}
|
|
98
|
+
#t(t) {
|
|
99
|
+
const e = this.#e;
|
|
100
|
+
if (!e)
|
|
101
|
+
throw new Error("Queue host not available");
|
|
102
|
+
return t(e);
|
|
103
|
+
}
|
|
104
|
+
getQueue() {
|
|
105
|
+
return this.#t((t) => t.getQueue());
|
|
106
|
+
}
|
|
107
|
+
getCurrentItem() {
|
|
108
|
+
return this.#t((t) => t.getCurrentItem());
|
|
109
|
+
}
|
|
110
|
+
addToQueue(t) {
|
|
111
|
+
return this.#t((e) => e.addToQueue(t));
|
|
112
|
+
}
|
|
113
|
+
addNext(t) {
|
|
114
|
+
return this.#t((e) => e.addNext(t));
|
|
115
|
+
}
|
|
116
|
+
addAt(t, e) {
|
|
117
|
+
return this.#t((r) => r.addAt(t, e));
|
|
118
|
+
}
|
|
119
|
+
removeByIds(t) {
|
|
120
|
+
return this.#t((e) => e.removeByIds(t));
|
|
121
|
+
}
|
|
122
|
+
removeByIndices(t) {
|
|
123
|
+
return this.#t((e) => e.removeByIndices(t));
|
|
124
|
+
}
|
|
125
|
+
clearQueue() {
|
|
126
|
+
return this.#t((t) => t.clearQueue());
|
|
127
|
+
}
|
|
128
|
+
reorder(t, e) {
|
|
129
|
+
return this.#t((r) => r.reorder(t, e));
|
|
130
|
+
}
|
|
131
|
+
updateItemState(t, e) {
|
|
132
|
+
return this.#t((r) => r.updateItemState(t, e));
|
|
133
|
+
}
|
|
134
|
+
goToNext() {
|
|
135
|
+
return this.#t((t) => t.goToNext());
|
|
136
|
+
}
|
|
137
|
+
goToPrevious() {
|
|
138
|
+
return this.#t((t) => t.goToPrevious());
|
|
139
|
+
}
|
|
140
|
+
goToIndex(t) {
|
|
141
|
+
return this.#t((e) => e.goToIndex(t));
|
|
142
|
+
}
|
|
143
|
+
goToId(t) {
|
|
144
|
+
return this.#t((e) => e.goToId(t));
|
|
145
|
+
}
|
|
146
|
+
setRepeatMode(t) {
|
|
147
|
+
return this.#t((e) => e.setRepeatMode(t));
|
|
148
|
+
}
|
|
149
|
+
setShuffleEnabled(t) {
|
|
150
|
+
return this.#t((e) => e.setShuffleEnabled(t));
|
|
151
|
+
}
|
|
152
|
+
subscribe(t) {
|
|
153
|
+
return this.#t((e) => e.subscribe(t));
|
|
154
|
+
}
|
|
155
|
+
subscribeToCurrentItem(t) {
|
|
156
|
+
return this.#t((e) => e.subscribeToCurrentItem(t));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
class T {
|
|
27
160
|
#e;
|
|
28
161
|
constructor(t) {
|
|
29
162
|
this.#e = t;
|
|
@@ -34,64 +167,107 @@ class d {
|
|
|
34
167
|
throw new Error("Settings host not available");
|
|
35
168
|
return t(e);
|
|
36
169
|
}
|
|
37
|
-
register(t
|
|
38
|
-
return this.#t((
|
|
170
|
+
register(t) {
|
|
171
|
+
return this.#t((e) => e.register(t));
|
|
39
172
|
}
|
|
40
173
|
get(t) {
|
|
41
174
|
return this.#t((e) => e.get(t));
|
|
42
175
|
}
|
|
43
176
|
set(t, e) {
|
|
44
|
-
return this.#t((
|
|
177
|
+
return this.#t((r) => r.set(t, e));
|
|
45
178
|
}
|
|
46
179
|
subscribe(t, e) {
|
|
47
|
-
return this.#t((
|
|
180
|
+
return this.#t((r) => r.subscribe(t, e));
|
|
48
181
|
}
|
|
49
182
|
}
|
|
50
|
-
class
|
|
183
|
+
class y {
|
|
184
|
+
#e;
|
|
185
|
+
constructor(t) {
|
|
186
|
+
this.#e = t;
|
|
187
|
+
}
|
|
188
|
+
#t(t) {
|
|
189
|
+
const e = this.#e;
|
|
190
|
+
if (!e)
|
|
191
|
+
throw new Error("Streaming host not available");
|
|
192
|
+
return t(e);
|
|
193
|
+
}
|
|
194
|
+
resolveCandidatesForTrack(t) {
|
|
195
|
+
return this.#t((e) => e.resolveCandidatesForTrack(t));
|
|
196
|
+
}
|
|
197
|
+
resolveStreamForCandidate(t) {
|
|
198
|
+
return this.#t((e) => e.resolveStreamForCandidate(t));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
class H {
|
|
202
|
+
host;
|
|
203
|
+
constructor(t) {
|
|
204
|
+
this.host = t;
|
|
205
|
+
}
|
|
206
|
+
get available() {
|
|
207
|
+
return !!this.host;
|
|
208
|
+
}
|
|
209
|
+
async search(t, e) {
|
|
210
|
+
if (!this.host)
|
|
211
|
+
throw new Error("YtdlpAPI: No host configured");
|
|
212
|
+
return this.host.search(t, e);
|
|
213
|
+
}
|
|
214
|
+
async getStream(t) {
|
|
215
|
+
if (!this.host)
|
|
216
|
+
throw new Error("YtdlpAPI: No host configured");
|
|
217
|
+
return this.host.getStream(t);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
class S {
|
|
51
221
|
Settings;
|
|
52
222
|
Providers;
|
|
223
|
+
Queue;
|
|
224
|
+
Streaming;
|
|
225
|
+
Metadata;
|
|
226
|
+
Http;
|
|
227
|
+
Ytdlp;
|
|
228
|
+
// All these are optional so we don't have to provide all of them in tests
|
|
53
229
|
constructor(t) {
|
|
54
|
-
this.Settings = new
|
|
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);
|
|
55
231
|
}
|
|
56
232
|
}
|
|
57
|
-
class
|
|
233
|
+
class P extends S {
|
|
58
234
|
}
|
|
59
235
|
class M extends Error {
|
|
60
236
|
constructor(t) {
|
|
61
237
|
super(`Missing capability: ${t}`), this.name = "MissingCapabilityError";
|
|
62
238
|
}
|
|
63
239
|
}
|
|
64
|
-
const
|
|
65
|
-
const [e,
|
|
240
|
+
const C = (s, t) => {
|
|
241
|
+
const [e, r] = l(void 0);
|
|
66
242
|
f(() => {
|
|
67
243
|
if (!s)
|
|
68
244
|
return;
|
|
69
|
-
let
|
|
70
|
-
const
|
|
71
|
-
|
|
245
|
+
let o = !0, u = !1;
|
|
246
|
+
const i = s.subscribe(t, (n) => {
|
|
247
|
+
o && (u = !0, r(n));
|
|
72
248
|
});
|
|
73
249
|
return s.get(t).then((n) => {
|
|
74
|
-
|
|
250
|
+
o && (u || r(n));
|
|
75
251
|
}), () => {
|
|
76
|
-
|
|
252
|
+
o = !1, i && i();
|
|
77
253
|
};
|
|
78
254
|
}, [t, s]);
|
|
79
|
-
const
|
|
80
|
-
() => (
|
|
81
|
-
s && s.set(t,
|
|
255
|
+
const a = g(
|
|
256
|
+
() => (o) => {
|
|
257
|
+
s && s.set(t, o);
|
|
82
258
|
},
|
|
83
259
|
[t, s]
|
|
84
260
|
);
|
|
85
|
-
return [e,
|
|
261
|
+
return [e, a];
|
|
86
262
|
};
|
|
87
|
-
function
|
|
263
|
+
function R(s, t, e) {
|
|
88
264
|
if (!s?.items?.length)
|
|
89
265
|
return;
|
|
90
|
-
const
|
|
91
|
-
if (!
|
|
266
|
+
const r = s.items.filter((i) => !(i.purpose && i.purpose !== t || !i.url));
|
|
267
|
+
if (!r.length)
|
|
92
268
|
return s.items[0];
|
|
93
|
-
const
|
|
94
|
-
switch (
|
|
269
|
+
const a = (i) => !i.width || !i.height ? 1 : i.width / i.height, u = ((i) => {
|
|
270
|
+
switch (i) {
|
|
95
271
|
case "avatar":
|
|
96
272
|
case "thumbnail":
|
|
97
273
|
return 1;
|
|
@@ -103,18 +279,20 @@ function E(s, t, e) {
|
|
|
103
279
|
return 1;
|
|
104
280
|
}
|
|
105
281
|
})(t);
|
|
106
|
-
return
|
|
107
|
-
const n = Math.min(
|
|
282
|
+
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;
|
|
108
284
|
return {
|
|
109
|
-
artwork:
|
|
110
|
-
score: (
|
|
285
|
+
artwork: i,
|
|
286
|
+
score: (d > 1.5 ? -1e3 : 0) + -h * 50 + -c * 0.1
|
|
111
287
|
};
|
|
112
|
-
}).sort((
|
|
288
|
+
}).sort((i, n) => n.score - i.score)[0]?.artwork;
|
|
113
289
|
}
|
|
114
290
|
export {
|
|
291
|
+
p as HttpAPI,
|
|
115
292
|
M as MissingCapabilityError,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
293
|
+
S as NuclearAPI,
|
|
294
|
+
P as NuclearPluginAPI,
|
|
295
|
+
H as YtdlpAPI,
|
|
296
|
+
R as pickArtwork,
|
|
297
|
+
C as useSetting
|
|
120
298
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuclearplayer/plugin-sdk",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.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/tailwind-config": "0.0.10",
|
|
42
|
+
"@nuclearplayer/eslint-config": "0.0.10"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"react": "^18.3.1"
|