@bzenky/spoti 0.1.0 → 0.3.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 (80) hide show
  1. package/README.md +144 -4
  2. package/dist/app.d.ts +27 -1
  3. package/dist/app.js +514 -16
  4. package/dist/app.js.map +1 -1
  5. package/dist/auth/config.d.ts +1 -1
  6. package/dist/auth/config.js +3 -3
  7. package/dist/auth/config.js.map +1 -1
  8. package/dist/auth/spotify-auth-client.d.ts +1 -0
  9. package/dist/auth/spotify-auth-client.js +4 -0
  10. package/dist/auth/spotify-auth-client.js.map +1 -1
  11. package/dist/cli.js +61 -1
  12. package/dist/cli.js.map +1 -1
  13. package/dist/services/auth.service.d.ts +1 -1
  14. package/dist/services/auth.service.js +17 -4
  15. package/dist/services/auth.service.js.map +1 -1
  16. package/dist/services/catalog.service.d.ts +9 -0
  17. package/dist/services/catalog.service.js +22 -0
  18. package/dist/services/catalog.service.js.map +1 -0
  19. package/dist/services/device.service.d.ts +20 -0
  20. package/dist/services/device.service.js +81 -0
  21. package/dist/services/device.service.js.map +1 -0
  22. package/dist/services/library.service.d.ts +13 -0
  23. package/dist/services/library.service.js +46 -0
  24. package/dist/services/library.service.js.map +1 -0
  25. package/dist/services/mappers.d.ts +10 -0
  26. package/dist/services/mappers.js +104 -0
  27. package/dist/services/mappers.js.map +1 -0
  28. package/dist/services/models.d.ts +45 -0
  29. package/dist/services/player.service.d.ts +12 -2
  30. package/dist/services/player.service.js +80 -15
  31. package/dist/services/player.service.js.map +1 -1
  32. package/dist/services/playlist.service.d.ts +9 -0
  33. package/dist/services/playlist.service.js +33 -0
  34. package/dist/services/playlist.service.js.map +1 -0
  35. package/dist/services/queue.service.d.ts +18 -0
  36. package/dist/services/queue.service.js +43 -0
  37. package/dist/services/queue.service.js.map +1 -0
  38. package/dist/services/recent.service.d.ts +7 -0
  39. package/dist/services/recent.service.js +24 -0
  40. package/dist/services/recent.service.js.map +1 -0
  41. package/dist/services/search.service.d.ts +5 -1
  42. package/dist/services/search.service.js +32 -17
  43. package/dist/services/search.service.js.map +1 -1
  44. package/dist/services/update.service.d.ts +57 -0
  45. package/dist/services/update.service.js +313 -0
  46. package/dist/services/update.service.js.map +1 -0
  47. package/dist/spotify/client.js +14 -1
  48. package/dist/spotify/client.js.map +1 -1
  49. package/dist/spotify/scopes.d.ts +2 -1
  50. package/dist/spotify/scopes.js +9 -1
  51. package/dist/spotify/scopes.js.map +1 -1
  52. package/dist/spotify/types.d.ts +112 -8
  53. package/dist/storage/config.d.ts +30 -0
  54. package/dist/storage/config.js +128 -0
  55. package/dist/storage/config.js.map +1 -0
  56. package/dist/storage/credentials.d.ts +1 -0
  57. package/dist/storage/credentials.js +1 -0
  58. package/dist/storage/credentials.js.map +1 -1
  59. package/dist/storage/index.d.ts +2 -0
  60. package/dist/storage/index.js +1 -0
  61. package/dist/storage/index.js.map +1 -1
  62. package/dist/storage/update-cache.d.ts +29 -0
  63. package/dist/storage/update-cache.js +135 -0
  64. package/dist/storage/update-cache.js.map +1 -0
  65. package/dist/ui/output.d.ts +10 -1
  66. package/dist/ui/output.js +60 -0
  67. package/dist/ui/output.js.map +1 -1
  68. package/dist/ui/prompts.d.ts +12 -1
  69. package/dist/ui/prompts.js +73 -6
  70. package/dist/ui/prompts.js.map +1 -1
  71. package/dist/ui/watch.d.ts +7 -0
  72. package/dist/ui/watch.js +44 -0
  73. package/dist/ui/watch.js.map +1 -0
  74. package/dist/update-worker.d.ts +9 -0
  75. package/dist/update-worker.js +91 -0
  76. package/dist/update-worker.js.map +1 -0
  77. package/dist/version.d.ts +2 -0
  78. package/dist/version.js +11 -0
  79. package/dist/version.js.map +1 -0
  80. package/package.json +1 -1
@@ -0,0 +1,313 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { FileUpdateCacheStore, } from '../storage/update-cache.js';
3
+ export const SPOTI_PACKAGE_NAME = '@bzenky/spoti';
4
+ export const NPM_REGISTRY_URL = 'https://registry.npmjs.org/%40bzenky%2Fspoti';
5
+ export const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1_000;
6
+ export const UPDATE_CHECK_TIMEOUT_MS = 3_000;
7
+ export const UPDATE_COMMAND = 'npm install -g @bzenky/spoti@latest';
8
+ export class UpdateCheckError extends Error {
9
+ constructor(message, options) {
10
+ super(message, options);
11
+ this.name = 'UpdateCheckError';
12
+ }
13
+ }
14
+ export class UpdateInstallError extends Error {
15
+ constructor(message, options) {
16
+ super(message, options);
17
+ this.name = 'UpdateInstallError';
18
+ }
19
+ }
20
+ export class UpdateService {
21
+ currentVersion;
22
+ cache;
23
+ fetchImplementation;
24
+ clock;
25
+ timeoutMs;
26
+ checkIntervalMs;
27
+ commandRunner;
28
+ constructor(currentVersion, dependencies = {}) {
29
+ this.currentVersion = currentVersion;
30
+ parseSemanticVersion(currentVersion);
31
+ this.cache = dependencies.cache ?? new FileUpdateCacheStore();
32
+ this.fetchImplementation = dependencies.fetch ?? globalThis.fetch;
33
+ this.clock = dependencies.now ?? Date.now;
34
+ this.timeoutMs = dependencies.timeoutMs ?? UPDATE_CHECK_TIMEOUT_MS;
35
+ this.checkIntervalMs = dependencies.checkIntervalMs ?? UPDATE_CHECK_INTERVAL_MS;
36
+ this.commandRunner = dependencies.commandRunner ?? new NodeUpdateCommandRunner();
37
+ if (!Number.isFinite(this.timeoutMs) || this.timeoutMs <= 0) {
38
+ throw new RangeError('Update check timeout must be a positive number.');
39
+ }
40
+ if (!Number.isFinite(this.checkIntervalMs) || this.checkIntervalMs <= 0) {
41
+ throw new RangeError('Update check interval must be a positive number.');
42
+ }
43
+ }
44
+ /** Always contacts npm and reports actionable failures. Intended for `spoti update --check`. */
45
+ async checkForeground() {
46
+ const checkedAt = this.clock();
47
+ try {
48
+ const result = await this.fetchLatest(checkedAt);
49
+ await this.cache.write(successCache(result));
50
+ return result;
51
+ }
52
+ catch (error) {
53
+ await this.recordFailedCheck(checkedAt);
54
+ if (error instanceof UpdateCheckError)
55
+ throw error;
56
+ throw new UpdateCheckError(`Unable to check for updates: ${errorMessage(error)}`, {
57
+ cause: error,
58
+ });
59
+ }
60
+ }
61
+ /** Uses the 24-hour cache and hides failures so normal commands remain unaffected. */
62
+ async checkInBackground() {
63
+ const now = this.clock();
64
+ try {
65
+ const cached = await this.cache.read();
66
+ if (cached && isFresh(cached.lastCheckedAt, now, this.checkIntervalMs)) {
67
+ if (cached.lastFailedCheckAt === cached.lastCheckedAt)
68
+ return null;
69
+ if (cached.lastSuccessfulCheck?.currentVersion === this.currentVersion) {
70
+ try {
71
+ return resultFromSuccessfulCache(cached.lastSuccessfulCheck);
72
+ }
73
+ catch {
74
+ // Invalid cached versions are recoverable; refresh them from the registry.
75
+ }
76
+ }
77
+ }
78
+ try {
79
+ const result = await this.fetchLatest(now);
80
+ await this.cache.write(successCache(result, cached));
81
+ return result;
82
+ }
83
+ catch {
84
+ await this.recordFailedCheck(now, cached);
85
+ return null;
86
+ }
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ }
92
+ /** The caller must obtain explicit user confirmation before setting `confirmed` to true. */
93
+ async installLatest(confirmed, version) {
94
+ if (!confirmed) {
95
+ throw new UpdateInstallError(`Update not installed because confirmation is required. To update manually, run: ${UPDATE_COMMAND}`);
96
+ }
97
+ try {
98
+ parseSemanticVersion(version);
99
+ }
100
+ catch (error) {
101
+ throw new UpdateInstallError(`Refusing to install invalid version ${JSON.stringify(version)}.`, {
102
+ cause: error,
103
+ });
104
+ }
105
+ try {
106
+ await this.commandRunner.run('npm', [
107
+ 'install',
108
+ '--global',
109
+ `${SPOTI_PACKAGE_NAME}@${version}`,
110
+ ]);
111
+ }
112
+ catch (error) {
113
+ throw new UpdateInstallError(`Unable to install the latest spoti version: ${errorMessage(error)}\n\nRun manually: ${UPDATE_COMMAND}`, { cause: error });
114
+ }
115
+ }
116
+ async fetchLatest(checkedAt) {
117
+ const controller = new AbortController();
118
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
119
+ timeout.unref?.();
120
+ let response;
121
+ try {
122
+ response = await this.fetchImplementation(NPM_REGISTRY_URL, {
123
+ headers: { accept: 'application/vnd.npm.install-v1+json' },
124
+ signal: controller.signal,
125
+ });
126
+ }
127
+ catch (error) {
128
+ if (controller.signal.aborted || isAbortError(error)) {
129
+ throw new UpdateCheckError(`Update check timed out after ${this.timeoutMs}ms. Check your network connection and try again.`, { cause: error });
130
+ }
131
+ throw new UpdateCheckError(`Unable to reach the npm registry: ${errorMessage(error)}. Check your network connection and try again.`, { cause: error });
132
+ }
133
+ finally {
134
+ clearTimeout(timeout);
135
+ }
136
+ if (!response.ok) {
137
+ throw new UpdateCheckError(`The npm registry returned HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ''}. Try again later.`);
138
+ }
139
+ let metadata;
140
+ try {
141
+ metadata = await response.json();
142
+ }
143
+ catch (error) {
144
+ throw new UpdateCheckError('The npm registry returned malformed JSON. Try again later or check the npm registry status.', { cause: error });
145
+ }
146
+ const latestVersion = readLatestVersion(metadata);
147
+ let comparison;
148
+ try {
149
+ comparison = compareSemanticVersions(latestVersion, this.currentVersion);
150
+ }
151
+ catch (error) {
152
+ throw new UpdateCheckError(`The npm registry returned an invalid latest version (${JSON.stringify(latestVersion)}). Try again later.`, { cause: error });
153
+ }
154
+ return {
155
+ status: comparison > 0 ? 'update-available' : 'current',
156
+ currentVersion: this.currentVersion,
157
+ latestVersion,
158
+ checkedAt,
159
+ source: 'registry',
160
+ };
161
+ }
162
+ async recordFailedCheck(at, previous) {
163
+ let cache = previous;
164
+ if (cache === undefined) {
165
+ try {
166
+ cache = await this.cache.read();
167
+ }
168
+ catch {
169
+ cache = null;
170
+ }
171
+ }
172
+ await this.cache
173
+ .write({
174
+ version: 1,
175
+ lastCheckedAt: at,
176
+ ...(cache?.lastSuccessfulCheck
177
+ ? { lastSuccessfulCheck: cache.lastSuccessfulCheck }
178
+ : {}),
179
+ lastFailedCheckAt: at,
180
+ })
181
+ .catch(() => undefined);
182
+ }
183
+ }
184
+ export class NodeUpdateCommandRunner {
185
+ run(command, args) {
186
+ return new Promise((resolve, reject) => {
187
+ const child = spawn(command, [...args], { stdio: 'inherit', shell: false });
188
+ child.once('error', reject);
189
+ child.once('exit', (code, signal) => {
190
+ if (code === 0) {
191
+ resolve();
192
+ return;
193
+ }
194
+ reject(new Error(signal
195
+ ? `npm was terminated by signal ${signal}`
196
+ : `npm exited with status ${String(code)}`));
197
+ });
198
+ });
199
+ }
200
+ }
201
+ export function compareSemanticVersions(left, right) {
202
+ const leftVersion = parseSemanticVersion(left);
203
+ const rightVersion = parseSemanticVersion(right);
204
+ for (const key of ['major', 'minor', 'patch']) {
205
+ const comparison = compareNumericIdentifiers(leftVersion[key], rightVersion[key]);
206
+ if (comparison !== 0)
207
+ return comparison;
208
+ }
209
+ if (!leftVersion.prerelease && !rightVersion.prerelease)
210
+ return 0;
211
+ if (!leftVersion.prerelease)
212
+ return 1;
213
+ if (!rightVersion.prerelease)
214
+ return -1;
215
+ const length = Math.max(leftVersion.prerelease.length, rightVersion.prerelease.length);
216
+ for (let index = 0; index < length; index += 1) {
217
+ const leftIdentifier = leftVersion.prerelease[index];
218
+ const rightIdentifier = rightVersion.prerelease[index];
219
+ if (leftIdentifier === undefined)
220
+ return -1;
221
+ if (rightIdentifier === undefined)
222
+ return 1;
223
+ if (leftIdentifier === rightIdentifier)
224
+ continue;
225
+ const leftNumeric = /^\d+$/.test(leftIdentifier);
226
+ const rightNumeric = /^\d+$/.test(rightIdentifier);
227
+ if (leftNumeric && rightNumeric) {
228
+ return compareNumericIdentifiers(leftIdentifier, rightIdentifier);
229
+ }
230
+ if (leftNumeric)
231
+ return -1;
232
+ if (rightNumeric)
233
+ return 1;
234
+ return leftIdentifier < rightIdentifier ? -1 : 1;
235
+ }
236
+ return 0;
237
+ }
238
+ const SEMANTIC_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
239
+ function parseSemanticVersion(value) {
240
+ const match = SEMANTIC_VERSION_PATTERN.exec(value);
241
+ if (!match) {
242
+ throw new TypeError(`Invalid semantic version: ${JSON.stringify(value)}`);
243
+ }
244
+ const major = match[1];
245
+ const minor = match[2];
246
+ const patch = match[3];
247
+ if (major === undefined || minor === undefined || patch === undefined) {
248
+ throw new TypeError(`Invalid semantic version: ${JSON.stringify(value)}`);
249
+ }
250
+ const prerelease = match[4];
251
+ return {
252
+ major,
253
+ minor,
254
+ patch,
255
+ ...(prerelease === undefined ? {} : { prerelease: prerelease.split('.') }),
256
+ };
257
+ }
258
+ function compareNumericIdentifiers(left, right) {
259
+ if (left.length !== right.length)
260
+ return left.length < right.length ? -1 : 1;
261
+ if (left === right)
262
+ return 0;
263
+ return left < right ? -1 : 1;
264
+ }
265
+ function readLatestVersion(metadata) {
266
+ if (typeof metadata !== 'object' ||
267
+ metadata === null ||
268
+ !('dist-tags' in metadata) ||
269
+ typeof metadata['dist-tags'] !== 'object' ||
270
+ metadata['dist-tags'] === null ||
271
+ !('latest' in metadata['dist-tags']) ||
272
+ typeof metadata['dist-tags'].latest !== 'string' ||
273
+ metadata['dist-tags'].latest.length === 0) {
274
+ throw new UpdateCheckError('The npm registry response did not include a latest version. Try again later.');
275
+ }
276
+ return metadata['dist-tags'].latest;
277
+ }
278
+ function successCache(result, previous) {
279
+ return {
280
+ version: 1,
281
+ lastCheckedAt: result.checkedAt,
282
+ lastSuccessfulCheck: {
283
+ checkedAt: result.checkedAt,
284
+ currentVersion: result.currentVersion,
285
+ latestVersion: result.latestVersion,
286
+ },
287
+ ...(previous?.lastFailedCheckAt === undefined
288
+ ? {}
289
+ : { lastFailedCheckAt: previous.lastFailedCheckAt }),
290
+ };
291
+ }
292
+ function resultFromSuccessfulCache(cache) {
293
+ return {
294
+ status: compareSemanticVersions(cache.latestVersion, cache.currentVersion) > 0
295
+ ? 'update-available'
296
+ : 'current',
297
+ currentVersion: cache.currentVersion,
298
+ latestVersion: cache.latestVersion,
299
+ checkedAt: cache.checkedAt,
300
+ source: 'cache',
301
+ };
302
+ }
303
+ function isFresh(checkedAt, now, intervalMs) {
304
+ const age = now - checkedAt;
305
+ return age >= 0 && age < intervalMs;
306
+ }
307
+ function isAbortError(error) {
308
+ return error instanceof Error && error.name === 'AbortError';
309
+ }
310
+ function errorMessage(error) {
311
+ return error instanceof Error ? error.message : String(error);
312
+ }
313
+ //# sourceMappingURL=update.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.service.js","sourceRoot":"","sources":["../../src/services/update.service.ts"],"names":[],"mappings":"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"}
@@ -78,7 +78,20 @@ export class SpotifyClient {
78
78
  if (response.status === 204)
79
79
  return undefined;
80
80
  const text = await response.text();
81
- return (text ? JSON.parse(text) : undefined);
81
+ if (!text)
82
+ return undefined;
83
+ const contentType = response.headers.get('content-type')?.toLocaleLowerCase() ?? '';
84
+ if (!contentType.includes('json')) {
85
+ if (method !== 'GET')
86
+ return undefined;
87
+ throw new SpotifyApiError('Spotify returned an unexpected non-JSON response.', response.status);
88
+ }
89
+ try {
90
+ return JSON.parse(text);
91
+ }
92
+ catch {
93
+ throw new SpotifyApiError('Spotify returned malformed JSON.', response.status);
94
+ }
82
95
  }
83
96
  }
84
97
  function getRetryAfterMilliseconds(response) {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/spotify/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/spotify/client.ts"],"names":[],"mappings":"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"}
@@ -1 +1,2 @@
1
- export declare const SPOTIFY_SCOPES: readonly ["user-read-playback-state", "user-modify-playback-state"];
1
+ export declare const LEGACY_SPOTIFY_SCOPES: readonly ["user-read-playback-state", "user-modify-playback-state"];
2
+ export declare const SPOTIFY_SCOPES: readonly ["user-read-playback-state", "user-modify-playback-state", "user-read-currently-playing", "playlist-read-private", "user-library-read", "user-library-modify", "user-read-recently-played"];
@@ -1,5 +1,13 @@
1
- export const SPOTIFY_SCOPES = [
1
+ export const LEGACY_SPOTIFY_SCOPES = [
2
2
  'user-read-playback-state',
3
3
  'user-modify-playback-state',
4
4
  ];
5
+ export const SPOTIFY_SCOPES = [
6
+ ...LEGACY_SPOTIFY_SCOPES,
7
+ 'user-read-currently-playing',
8
+ 'playlist-read-private',
9
+ 'user-library-read',
10
+ 'user-library-modify',
11
+ 'user-read-recently-played',
12
+ ];
5
13
  //# sourceMappingURL=scopes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/spotify/scopes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,0BAA0B;IAC1B,4BAA4B;CACpB,CAAC"}
1
+ {"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/spotify/scopes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,0BAA0B;IAC1B,4BAA4B;CACpB,CAAC;AAEX,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,GAAG,qBAAqB;IACxB,6BAA6B;IAC7B,uBAAuB;IACvB,mBAAmB;IACnB,qBAAqB;IACrB,2BAA2B;CACnB,CAAC"}
@@ -3,6 +3,9 @@ export interface SpotifyImage {
3
3
  height: number | null;
4
4
  width: number | null;
5
5
  }
6
+ export interface SpotifyExternalUrls {
7
+ spotify?: string;
8
+ }
6
9
  export interface SpotifyUserProfile {
7
10
  id: string;
8
11
  display_name: string | null;
@@ -10,37 +13,138 @@ export interface SpotifyUserProfile {
10
13
  }
11
14
  export interface SpotifyArtist {
12
15
  id: string;
16
+ uri?: string;
17
+ name: string;
18
+ external_urls?: SpotifyExternalUrls;
19
+ }
20
+ export interface SpotifyFullArtist extends SpotifyArtist {
21
+ uri: string;
22
+ images: SpotifyImage[];
23
+ }
24
+ export interface SpotifySimplifiedAlbum {
25
+ id?: string;
26
+ uri?: string;
13
27
  name: string;
28
+ album_type?: string;
29
+ artists?: SpotifyArtist[];
30
+ images: SpotifyImage[];
31
+ release_date?: string;
32
+ total_tracks?: number;
33
+ external_urls?: SpotifyExternalUrls;
14
34
  }
15
35
  export interface SpotifyTrack {
16
- id: string;
36
+ type?: 'track';
37
+ id: string | null;
17
38
  uri: string;
18
39
  name: string;
19
40
  duration_ms: number;
20
41
  artists: SpotifyArtist[];
21
- album: {
22
- name: string;
23
- images: SpotifyImage[];
42
+ album: SpotifySimplifiedAlbum;
43
+ is_local?: boolean;
44
+ is_playable?: boolean;
45
+ external_urls?: SpotifyExternalUrls;
46
+ }
47
+ export interface SpotifySimplifiedTrack {
48
+ type?: 'track';
49
+ id: string | null;
50
+ uri: string;
51
+ name: string;
52
+ duration_ms: number;
53
+ artists: SpotifyArtist[];
54
+ is_local?: boolean;
55
+ is_playable?: boolean;
56
+ external_urls?: SpotifyExternalUrls;
57
+ }
58
+ export interface SpotifyAlbum extends SpotifySimplifiedAlbum {
59
+ id: string;
60
+ uri: string;
61
+ artists: SpotifyArtist[];
62
+ tracks: SpotifyPaging<SpotifySimplifiedTrack>;
63
+ }
64
+ export interface SpotifyPlaylistOwner {
65
+ id: string;
66
+ display_name: string | null;
67
+ }
68
+ export interface SpotifySimplifiedPlaylist {
69
+ id: string;
70
+ uri: string;
71
+ name: string;
72
+ description: string | null;
73
+ public: boolean | null;
74
+ collaborative: boolean;
75
+ owner: SpotifyPlaylistOwner;
76
+ images: SpotifyImage[] | null;
77
+ external_urls?: SpotifyExternalUrls;
78
+ items: {
79
+ total: number;
24
80
  };
25
- external_urls?: {
26
- spotify?: string;
81
+ }
82
+ export interface SpotifyPlaylist extends SpotifySimplifiedPlaylist {
83
+ followers?: {
84
+ total: number;
85
+ };
86
+ }
87
+ export interface SpotifyEpisode {
88
+ type: 'episode';
89
+ id?: string | null;
90
+ uri?: string;
91
+ name?: string;
92
+ }
93
+ export type SpotifyPlaybackItem = SpotifyTrack | SpotifyEpisode | Record<string, unknown>;
94
+ export interface SpotifyPlaylistItem {
95
+ added_at: string | null;
96
+ is_local: boolean;
97
+ item: SpotifyPlaybackItem | null;
98
+ }
99
+ export interface SpotifyRecentlyPlayedItem {
100
+ track: SpotifyPlaybackItem | null;
101
+ played_at: string;
102
+ context: {
103
+ uri: string;
104
+ } | null;
105
+ }
106
+ export interface SpotifyPaging<T> {
107
+ items: T[];
108
+ limit: number;
109
+ offset: number;
110
+ total: number;
111
+ next: string | null;
112
+ previous: string | null;
113
+ }
114
+ export interface SpotifyCursorPaging<T> {
115
+ items: T[];
116
+ limit: number;
117
+ next: string | null;
118
+ cursors?: {
119
+ after?: string;
120
+ before?: string;
27
121
  };
28
122
  }
29
123
  export interface SpotifyPlaybackState {
30
124
  is_playing: boolean;
31
125
  progress_ms: number | null;
32
- item: SpotifyTrack | null;
126
+ item: SpotifyPlaybackItem | null;
33
127
  device: {
34
128
  id: string | null;
35
129
  name: string;
36
130
  is_active: boolean;
131
+ volume_percent: number | null;
132
+ supports_volume: boolean;
37
133
  };
38
134
  }
39
135
  export interface SpotifySearchResponse {
40
- tracks: {
136
+ tracks?: SpotifyPaging<SpotifyTrack> | {
41
137
  items: SpotifyTrack[];
42
138
  };
139
+ albums?: SpotifyPaging<SpotifySimplifiedAlbum>;
140
+ artists?: SpotifyPaging<SpotifyFullArtist>;
141
+ playlists?: SpotifyPaging<SpotifySimplifiedPlaylist | null>;
142
+ }
143
+ export interface SpotifySavedTrack {
144
+ added_at: string;
145
+ track: SpotifyTrack;
43
146
  }
147
+ export type SpotifyRecentlyPlayedResponse = SpotifyCursorPaging<SpotifyRecentlyPlayedItem>;
44
148
  export interface SpotifyErrorBody {
45
149
  error?: {
46
150
  status?: number;
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod';
2
+ declare const configSchema: z.ZodObject<{
3
+ spotifyClientId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
4
+ watchAfterPlay: z.ZodDefault<z.ZodBoolean>;
5
+ refreshIntervalMs: z.ZodDefault<z.ZodNumber>;
6
+ }, z.core.$strict>;
7
+ export type AppConfig = z.infer<typeof configSchema>;
8
+ export declare const CONFIG_KEYS: readonly ["spotifyClientId", "watchAfterPlay", "refreshIntervalMs"];
9
+ export type ConfigKey = (typeof CONFIG_KEYS)[number];
10
+ export declare const DEFAULT_CONFIG: Readonly<AppConfig>;
11
+ export interface ConfigStore {
12
+ read(): Promise<AppConfig>;
13
+ write(config: AppConfig): Promise<void>;
14
+ set<Key extends ConfigKey>(key: Key, value: AppConfig[Key]): Promise<void>;
15
+ reset(): Promise<void>;
16
+ }
17
+ export interface FileConfigStoreOptions {
18
+ directory?: string;
19
+ }
20
+ export declare class FileConfigStore implements ConfigStore {
21
+ readonly path: string;
22
+ private readonly directory;
23
+ constructor(options?: FileConfigStoreOptions);
24
+ read(): Promise<AppConfig>;
25
+ write(config: AppConfig): Promise<void>;
26
+ set<Key extends ConfigKey>(key: Key, value: AppConfig[Key]): Promise<void>;
27
+ reset(): Promise<void>;
28
+ }
29
+ export declare function parseConfigValue<Key extends ConfigKey>(key: Key, value: string): AppConfig[Key];
30
+ export {};