@nuclearplayer/plugin-sdk 0.0.14 → 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.
Files changed (3) hide show
  1. package/dist/index.d.ts +239 -13
  2. package/dist/index.js +265 -35
  3. 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,76 @@ export declare type EnumWidget = {
97
99
  type: 'radio';
98
100
  };
99
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
+
149
+ export declare type FetchFunction = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
150
+
151
+ export declare class HttpAPI {
152
+ readonly fetch: FetchFunction;
153
+ constructor(host?: HttpHost);
154
+ }
155
+
156
+ export declare type HttpHost = {
157
+ fetch: (url: string, init?: HttpRequestInit) => Promise<HttpResponseData>;
158
+ };
159
+
160
+ export declare type HttpRequestInit = {
161
+ method?: string;
162
+ headers?: Record<string, string>;
163
+ body?: string;
164
+ };
165
+
166
+ export declare type HttpResponseData = {
167
+ status: number;
168
+ headers: Record<string, string>;
169
+ body: string;
170
+ };
171
+
100
172
  export declare type LoadedPlugin = {
101
173
  metadata: PluginMetadata;
102
174
  instance: NuclearPlugin;
@@ -114,9 +186,30 @@ export declare type LocalFileInfo = {
114
186
  scannedAtIso?: string;
115
187
  };
116
188
 
189
+ declare class MetadataAPI {
190
+ #private;
191
+ constructor(host?: MetadataHost);
192
+ search(params: SearchParams, providerId?: string): Promise<SearchResults>;
193
+ fetchArtistDetails(artistId: string, providerId?: string): Promise<Artist>;
194
+ fetchArtistAlbums(artistId: string, providerId?: string): Promise<AlbumRef[]>;
195
+ fetchArtistTopTracks(artistId: string, providerId?: string): Promise<TrackRef[]>;
196
+ fetchArtistRelatedArtists(artistId: string, providerId?: string): Promise<ArtistRef[]>;
197
+ fetchAlbumDetails(albumId: string, providerId?: string): Promise<Album>;
198
+ }
199
+
200
+ export declare type MetadataHost = {
201
+ search: (params: SearchParams, providerId?: string) => Promise<SearchResults>;
202
+ fetchArtistDetails: (artistId: string, providerId?: string) => Promise<Artist>;
203
+ fetchArtistAlbums: (artistId: string, providerId?: string) => Promise<AlbumRef[]>;
204
+ fetchArtistTopTracks: (artistId: string, providerId?: string) => Promise<TrackRef[]>;
205
+ fetchArtistRelatedArtists: (artistId: string, providerId?: string) => Promise<ArtistRef[]>;
206
+ fetchAlbumDetails: (albumId: string, providerId?: string) => Promise<Album>;
207
+ };
208
+
117
209
  export declare type MetadataProvider = ProviderDescriptor<'metadata'> & {
118
210
  searchCapabilities?: SearchCapability[];
119
211
  artistMetadataCapabilities?: ArtistMetadataCapability[];
212
+ albumMetadataCapabilities?: AlbumMetadataCapability[];
120
213
  search?: (params: SearchParams) => Promise<SearchResults>;
121
214
  searchArtists?: (params: Omit<SearchParams, 'types'>) => Promise<ArtistRef[]>;
122
215
  searchAlbums?: (params: Omit<SearchParams, 'types'>) => Promise<AlbumRef[]>;
@@ -136,17 +229,29 @@ export declare class MissingCapabilityError extends Error {
136
229
  export declare class NuclearAPI {
137
230
  readonly Settings: Settings;
138
231
  readonly Providers: Providers;
232
+ readonly Queue: QueueAPI;
233
+ readonly Streaming: StreamingAPI;
234
+ readonly Metadata: MetadataAPI;
235
+ readonly Http: HttpAPI;
236
+ readonly Ytdlp: YtdlpAPI;
237
+ readonly Favorites: FavoritesAPI;
139
238
  constructor(opts?: {
140
239
  settingsHost?: SettingsHost;
141
240
  providersHost?: ProvidersHost;
241
+ queueHost?: QueueHost;
242
+ streamingHost?: StreamingHost;
243
+ metadataHost?: MetadataHost;
244
+ httpHost?: HttpHost;
245
+ ytdlpHost?: YtdlpHost;
246
+ favoritesHost?: FavoritesHost;
142
247
  });
143
248
  }
144
249
 
145
250
  export declare type NuclearPlugin = {
146
251
  onLoad?(api: NuclearPluginAPI): void | Promise<void>;
147
- onUnload?(): void | Promise<void>;
252
+ onUnload?(api: NuclearPluginAPI): void | Promise<void>;
148
253
  onEnable?(api: NuclearPluginAPI): void | Promise<void>;
149
- onDisable?(): void | Promise<void>;
254
+ onDisable?(api: NuclearPluginAPI): void | Promise<void>;
150
255
  };
151
256
 
152
257
  export declare class NuclearPluginAPI extends NuclearAPI {
@@ -273,18 +378,76 @@ export declare type ProvidersHost = {
273
378
  clear(): void;
274
379
  };
275
380
 
381
+ export declare type Queue = {
382
+ items: QueueItem[];
383
+ currentIndex: number;
384
+ repeatMode: RepeatMode;
385
+ shuffleEnabled: boolean;
386
+ };
387
+
388
+ declare class QueueAPI {
389
+ #private;
390
+ constructor(host?: QueueHost);
391
+ getQueue(): Promise<Queue>;
392
+ getCurrentItem(): Promise<QueueItem | undefined>;
393
+ addToQueue(tracks: Track[]): Promise<void>;
394
+ addNext(tracks: Track[]): Promise<void>;
395
+ addAt(tracks: Track[], index: number): Promise<void>;
396
+ removeByIds(ids: string[]): Promise<void>;
397
+ removeByIndices(indices: number[]): Promise<void>;
398
+ clearQueue(): Promise<void>;
399
+ reorder(fromIndex: number, toIndex: number): Promise<void>;
400
+ updateItemState(id: string, updates: QueueItemStateUpdate): Promise<void>;
401
+ goToNext(): Promise<void>;
402
+ goToPrevious(): Promise<void>;
403
+ goToIndex(index: number): Promise<void>;
404
+ goToId(id: string): Promise<void>;
405
+ setRepeatMode(mode: RepeatMode): Promise<void>;
406
+ setShuffleEnabled(enabled: boolean): Promise<void>;
407
+ subscribe(listener: (queue: Queue) => void): () => void;
408
+ subscribeToCurrentItem(listener: (item: QueueItem | undefined) => void): () => void;
409
+ }
410
+
411
+ export declare type QueueHost = {
412
+ getQueue: () => Promise<Queue>;
413
+ getCurrentItem: () => Promise<QueueItem | undefined>;
414
+ addToQueue: (tracks: Track[]) => Promise<void>;
415
+ addNext: (tracks: Track[]) => Promise<void>;
416
+ addAt: (tracks: Track[], index: number) => Promise<void>;
417
+ removeByIds: (ids: string[]) => Promise<void>;
418
+ removeByIndices: (indices: number[]) => Promise<void>;
419
+ clearQueue: () => Promise<void>;
420
+ reorder: (fromIndex: number, toIndex: number) => Promise<void>;
421
+ updateItemState: (id: string, updates: QueueItemStateUpdate) => Promise<void>;
422
+ goToNext: () => Promise<void>;
423
+ goToPrevious: () => Promise<void>;
424
+ goToIndex: (index: number) => Promise<void>;
425
+ goToId: (id: string) => Promise<void>;
426
+ setRepeatMode: (mode: RepeatMode) => Promise<void>;
427
+ setShuffleEnabled: (enabled: boolean) => Promise<void>;
428
+ subscribe: (listener: QueueListener) => () => void;
429
+ subscribeToCurrentItem: (listener: QueueItemListener) => () => void;
430
+ };
431
+
276
432
  export declare type QueueItem = {
277
433
  id: string;
278
- title: string;
279
- artists: ArtistCredit[];
280
- album?: string;
281
- durationMs?: number;
282
- artwork?: ArtworkSet;
283
- note?: string;
284
- addedAtIso?: string;
285
- source: ProviderRef;
434
+ track: Track;
435
+ status: 'idle' | 'loading' | 'success' | 'error';
436
+ error?: string;
437
+ addedAtIso: string;
286
438
  };
287
439
 
440
+ export declare type QueueItemListener = (item: QueueItem | undefined) => void;
441
+
442
+ export declare type QueueItemStateUpdate = Partial<{
443
+ status: QueueItem['status'];
444
+ error: QueueItem['error'];
445
+ }>;
446
+
447
+ export declare type QueueListener = (queue: Queue) => void;
448
+
449
+ export declare type RepeatMode = 'off' | 'all' | 'one';
450
+
288
451
  export declare type SearchCapability = SearchCategory | 'unified';
289
452
 
290
453
  export declare type SearchCategory = 'artists' | 'albums' | 'tracks' | 'playlists';
@@ -309,14 +472,14 @@ export declare type SettingDefinition = BooleanSettingDefinition | NumberSetting
309
472
  declare class Settings {
310
473
  #private;
311
474
  constructor(host?: SettingsHost);
312
- register(defs: SettingDefinition[], source: SettingSource): Promise<SettingsRegistrationResult>;
475
+ register(defs: SettingDefinition[]): Promise<SettingsRegistrationResult>;
313
476
  get<T extends SettingValue = SettingValue>(id: string): Promise<T | undefined>;
314
477
  set<T extends SettingValue = SettingValue>(id: string, value: T): Promise<void>;
315
478
  subscribe<T extends SettingValue = SettingValue>(id: string, listener: (value: T | undefined) => void): () => void;
316
479
  }
317
480
 
318
481
  export declare type SettingsHost = {
319
- register(defs: SettingDefinition[], source: SettingSource): Promise<SettingsRegistrationResult>;
482
+ register(defs: SettingDefinition[]): Promise<SettingsRegistrationResult>;
320
483
  get<T extends SettingValue = SettingValue>(id: string): Promise<T | undefined>;
321
484
  set<T extends SettingValue = SettingValue>(id: string, value: T): Promise<void>;
322
485
  subscribe<T extends SettingValue = SettingValue>(id: string, listener: (value: T | undefined) => void): () => void;
@@ -353,6 +516,43 @@ export declare type Stream = {
353
516
  source: ProviderRef;
354
517
  };
355
518
 
519
+ export declare type StreamCandidate = {
520
+ id: string;
521
+ title: string;
522
+ durationMs?: number;
523
+ thumbnail?: string;
524
+ stream?: Stream;
525
+ lastResolvedAtIso?: string;
526
+ failed: boolean;
527
+ source: ProviderRef;
528
+ };
529
+
530
+ declare class StreamingAPI {
531
+ #private;
532
+ constructor(host?: StreamingHost);
533
+ resolveCandidatesForTrack(track: Track): Promise<StreamResolutionResult>;
534
+ resolveStreamForCandidate(candidate: StreamCandidate): Promise<StreamCandidate | undefined>;
535
+ }
536
+
537
+ export declare type StreamingHost = {
538
+ resolveCandidatesForTrack: (track: Track) => Promise<StreamResolutionResult>;
539
+ resolveStreamForCandidate: (candidate: StreamCandidate) => Promise<StreamCandidate | undefined>;
540
+ };
541
+
542
+ export declare type StreamingProvider = ProviderDescriptor<'streaming'> & {
543
+ searchForTrack: (artist: string, title: string, album?: string) => Promise<StreamCandidate[]>;
544
+ getStreamUrl: (candidateId: string) => Promise<Stream>;
545
+ supportsLocalFiles?: boolean;
546
+ };
547
+
548
+ export declare type StreamResolutionResult = {
549
+ success: true;
550
+ candidates: StreamCandidate[];
551
+ } | {
552
+ success: false;
553
+ error: string;
554
+ };
555
+
356
556
  export declare type StringFormat = 'text' | 'url' | 'path' | 'token' | 'language';
357
557
 
358
558
  export declare type StringSettingDefinition = {
@@ -394,7 +594,7 @@ export declare type Track = {
394
594
  tags?: string[];
395
595
  source: ProviderRef;
396
596
  localFile?: LocalFileInfo;
397
- streams?: Stream[];
597
+ streamCandidates?: StreamCandidate[];
398
598
  };
399
599
 
400
600
  export declare type TrackRef = {
@@ -406,4 +606,30 @@ export declare type TrackRef = {
406
606
 
407
607
  export declare const useSetting: <T extends SettingValue = SettingValue>(host: SettingsHost | undefined, id: string) => readonly [T | undefined, (nextValue: T) => void];
408
608
 
609
+ export declare class YtdlpAPI {
610
+ private host?;
611
+ constructor(host?: YtdlpHost);
612
+ get available(): boolean;
613
+ search(query: string, maxResults?: number): Promise<YtdlpSearchResult[]>;
614
+ getStream(videoId: string): Promise<YtdlpStreamInfo>;
615
+ }
616
+
617
+ export declare type YtdlpHost = {
618
+ search: (query: string, maxResults?: number) => Promise<YtdlpSearchResult[]>;
619
+ getStream: (videoId: string) => Promise<YtdlpStreamInfo>;
620
+ };
621
+
622
+ export declare type YtdlpSearchResult = {
623
+ id: string;
624
+ title: string;
625
+ duration: number | null;
626
+ thumbnail: string | null;
627
+ };
628
+
629
+ export declare type YtdlpStreamInfo = {
630
+ stream_url: string;
631
+ duration: number | null;
632
+ title: string | null;
633
+ };
634
+
409
635
  export { }
package/dist/index.js CHANGED
@@ -1,4 +1,122 @@
1
- import { useState as g, useEffect as f, useMemo as b } from "react";
1
+ import { useState as l, useEffect as f, useMemo as g } 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 = (s) => {
54
+ if (s instanceof Headers) {
55
+ const t = {};
56
+ return s.forEach((e, r) => {
57
+ t[r] = e;
58
+ }), t;
59
+ }
60
+ return Array.isArray(s) ? Object.fromEntries(s) : s;
61
+ };
62
+ function A(s) {
63
+ return async (t, e) => {
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, {
65
+ method: e?.method,
66
+ headers: a,
67
+ body: n
68
+ });
69
+ return new Response(u.body, {
70
+ status: u.status,
71
+ headers: new Headers(u.headers)
72
+ });
73
+ };
74
+ }
75
+ const v = {
76
+ fetch: async () => ({
77
+ status: 501,
78
+ headers: {},
79
+ body: "HTTP host not configured"
80
+ })
81
+ };
82
+ class w {
83
+ fetch;
84
+ constructor(t) {
85
+ this.fetch = A(t ?? v);
86
+ }
87
+ }
88
+ class T {
89
+ #e;
90
+ constructor(t) {
91
+ this.#e = t;
92
+ }
93
+ #t(t) {
94
+ const e = this.#e;
95
+ if (!e)
96
+ throw new Error("Metadata host not available");
97
+ return t(e);
98
+ }
99
+ search(t, e) {
100
+ return this.#t((r) => r.search(t, e));
101
+ }
102
+ fetchArtistDetails(t, e) {
103
+ return this.#t((r) => r.fetchArtistDetails(t, e));
104
+ }
105
+ fetchArtistAlbums(t, e) {
106
+ return this.#t((r) => r.fetchArtistAlbums(t, e));
107
+ }
108
+ fetchArtistTopTracks(t, e) {
109
+ return this.#t((r) => r.fetchArtistTopTracks(t, e));
110
+ }
111
+ fetchArtistRelatedArtists(t, e) {
112
+ return this.#t(
113
+ (r) => r.fetchArtistRelatedArtists(t, e)
114
+ );
115
+ }
116
+ fetchAlbumDetails(t, e) {
117
+ return this.#t((r) => r.fetchAlbumDetails(t, e));
118
+ }
119
+ }
2
120
  class p {
3
121
  #e;
4
122
  constructor(t) {
@@ -23,7 +141,73 @@ class p {
23
141
  return this.#t((e) => e.get(t));
24
142
  }
25
143
  }
26
- class d {
144
+ class I {
145
+ #e;
146
+ constructor(t) {
147
+ this.#e = t;
148
+ }
149
+ #t(t) {
150
+ const e = this.#e;
151
+ if (!e)
152
+ throw new Error("Queue host not available");
153
+ return t(e);
154
+ }
155
+ getQueue() {
156
+ return this.#t((t) => t.getQueue());
157
+ }
158
+ getCurrentItem() {
159
+ return this.#t((t) => t.getCurrentItem());
160
+ }
161
+ addToQueue(t) {
162
+ return this.#t((e) => e.addToQueue(t));
163
+ }
164
+ addNext(t) {
165
+ return this.#t((e) => e.addNext(t));
166
+ }
167
+ addAt(t, e) {
168
+ return this.#t((r) => r.addAt(t, e));
169
+ }
170
+ removeByIds(t) {
171
+ return this.#t((e) => e.removeByIds(t));
172
+ }
173
+ removeByIndices(t) {
174
+ return this.#t((e) => e.removeByIndices(t));
175
+ }
176
+ clearQueue() {
177
+ return this.#t((t) => t.clearQueue());
178
+ }
179
+ reorder(t, e) {
180
+ return this.#t((r) => r.reorder(t, e));
181
+ }
182
+ updateItemState(t, e) {
183
+ return this.#t((r) => r.updateItemState(t, e));
184
+ }
185
+ goToNext() {
186
+ return this.#t((t) => t.goToNext());
187
+ }
188
+ goToPrevious() {
189
+ return this.#t((t) => t.goToPrevious());
190
+ }
191
+ goToIndex(t) {
192
+ return this.#t((e) => e.goToIndex(t));
193
+ }
194
+ goToId(t) {
195
+ return this.#t((e) => e.goToId(t));
196
+ }
197
+ setRepeatMode(t) {
198
+ return this.#t((e) => e.setRepeatMode(t));
199
+ }
200
+ setShuffleEnabled(t) {
201
+ return this.#t((e) => e.setShuffleEnabled(t));
202
+ }
203
+ subscribe(t) {
204
+ return this.#t((e) => e.subscribe(t));
205
+ }
206
+ subscribeToCurrentItem(t) {
207
+ return this.#t((e) => e.subscribeToCurrentItem(t));
208
+ }
209
+ }
210
+ class H {
27
211
  #e;
28
212
  constructor(t) {
29
213
  this.#e = t;
@@ -34,64 +218,107 @@ class d {
34
218
  throw new Error("Settings host not available");
35
219
  return t(e);
36
220
  }
37
- register(t, e) {
38
- return this.#t((i) => i.register(t, e));
221
+ register(t) {
222
+ return this.#t((e) => e.register(t));
39
223
  }
40
224
  get(t) {
41
225
  return this.#t((e) => e.get(t));
42
226
  }
43
227
  set(t, e) {
44
- return this.#t((i) => i.set(t, e));
228
+ return this.#t((r) => r.set(t, e));
45
229
  }
46
230
  subscribe(t, e) {
47
- return this.#t((i) => i.subscribe(t, e));
231
+ return this.#t((r) => r.subscribe(t, e));
232
+ }
233
+ }
234
+ class y {
235
+ #e;
236
+ constructor(t) {
237
+ this.#e = t;
238
+ }
239
+ #t(t) {
240
+ const e = this.#e;
241
+ if (!e)
242
+ throw new Error("Streaming host not available");
243
+ return t(e);
244
+ }
245
+ resolveCandidatesForTrack(t) {
246
+ return this.#t((e) => e.resolveCandidatesForTrack(t));
247
+ }
248
+ resolveStreamForCandidate(t) {
249
+ return this.#t((e) => e.resolveStreamForCandidate(t));
250
+ }
251
+ }
252
+ class S {
253
+ host;
254
+ constructor(t) {
255
+ this.host = t;
256
+ }
257
+ get available() {
258
+ return !!this.host;
259
+ }
260
+ async search(t, e) {
261
+ if (!this.host)
262
+ throw new Error("YtdlpAPI: No host configured");
263
+ return this.host.search(t, e);
264
+ }
265
+ async getStream(t) {
266
+ if (!this.host)
267
+ throw new Error("YtdlpAPI: No host configured");
268
+ return this.host.getStream(t);
48
269
  }
49
270
  }
50
- class v {
271
+ class F {
51
272
  Settings;
52
273
  Providers;
274
+ Queue;
275
+ Streaming;
276
+ Metadata;
277
+ Http;
278
+ Ytdlp;
279
+ Favorites;
53
280
  constructor(t) {
54
- this.Settings = new d(t?.settingsHost), this.Providers = new p(t?.providersHost);
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);
55
282
  }
56
283
  }
57
- class w extends v {
284
+ class P extends F {
58
285
  }
59
286
  class M extends Error {
60
287
  constructor(t) {
61
288
  super(`Missing capability: ${t}`), this.name = "MissingCapabilityError";
62
289
  }
63
290
  }
64
- const A = (s, t) => {
65
- const [e, i] = g(void 0);
291
+ const C = (s, t) => {
292
+ const [e, r] = l(void 0);
66
293
  f(() => {
67
294
  if (!s)
68
295
  return;
69
- let u = !0, c = !1;
70
- const r = s.subscribe(t, (n) => {
71
- u && (c = !0, i(n));
296
+ let n = !0, u = !1;
297
+ const i = s.subscribe(t, (o) => {
298
+ n && (u = !0, r(o));
72
299
  });
73
- return s.get(t).then((n) => {
74
- u && (c || i(n));
300
+ return s.get(t).then((o) => {
301
+ n && (u || r(o));
75
302
  }), () => {
76
- u = !1, r && r();
303
+ n = !1, i && i();
77
304
  };
78
305
  }, [t, s]);
79
- const o = b(
80
- () => (u) => {
81
- s && s.set(t, u);
306
+ const a = g(
307
+ () => (n) => {
308
+ s && s.set(t, n);
82
309
  },
83
310
  [t, s]
84
311
  );
85
- return [e, o];
312
+ return [e, a];
86
313
  };
87
- function E(s, t, e) {
314
+ function R(s, t, e) {
88
315
  if (!s?.items?.length)
89
316
  return;
90
- const i = s.items.filter((r) => !(r.purpose && r.purpose !== t || !r.url));
91
- if (!i.length)
317
+ const r = s.items.filter((i) => !(i.purpose && i.purpose !== t || !i.url));
318
+ if (!r.length)
92
319
  return s.items[0];
93
- const o = (r) => !r.width || !r.height ? 1 : r.width / r.height, c = ((r) => {
94
- switch (r) {
320
+ const a = (i) => !i.width || !i.height ? 1 : i.width / i.height, u = ((i) => {
321
+ switch (i) {
95
322
  case "avatar":
96
323
  case "thumbnail":
97
324
  return 1;
@@ -103,18 +330,21 @@ function E(s, t, e) {
103
330
  return 1;
104
331
  }
105
332
  })(t);
106
- return i.map((r) => {
107
- const n = Math.min(r.width || 0, r.height || 0), a = Math.abs(o(r) - c), h = Math.abs(n - e), l = n < e ? e / n : 1;
333
+ return r.map((i) => {
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;
108
335
  return {
109
- artwork: r,
110
- score: (l > 1.5 ? -1e3 : 0) + -a * 50 + -h * 0.1
336
+ artwork: i,
337
+ score: (d > 1.5 ? -1e3 : 0) + -h * 50 + -c * 0.1
111
338
  };
112
- }).sort((r, n) => n.score - r.score)[0]?.artwork;
339
+ }).sort((i, o) => o.score - i.score)[0]?.artwork;
113
340
  }
114
341
  export {
342
+ b as FavoritesAPI,
343
+ w as HttpAPI,
115
344
  M as MissingCapabilityError,
116
- v as NuclearAPI,
117
- w as NuclearPluginAPI,
118
- E as pickArtwork,
119
- A as useSetting
345
+ F as NuclearAPI,
346
+ P as NuclearPluginAPI,
347
+ S as YtdlpAPI,
348
+ R as pickArtwork,
349
+ C as useSetting
120
350
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuclearplayer/plugin-sdk",
3
- "version": "0.0.14",
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/eslint-config": "0.0.9",
42
- "@nuclearplayer/tailwind-config": "0.0.9"
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"