@bzenky/spoti 0.3.0 → 0.5.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 (47) hide show
  1. package/README.md +68 -6
  2. package/dist/app.d.ts +10 -2
  3. package/dist/app.js +207 -82
  4. package/dist/app.js.map +1 -1
  5. package/dist/cli.js +4 -2
  6. package/dist/cli.js.map +1 -1
  7. package/dist/services/device.service.d.ts +3 -3
  8. package/dist/services/device.service.js +19 -11
  9. package/dist/services/device.service.js.map +1 -1
  10. package/dist/services/player.service.d.ts +4 -2
  11. package/dist/services/player.service.js +35 -5
  12. package/dist/services/player.service.js.map +1 -1
  13. package/dist/services/queue.service.js +11 -6
  14. package/dist/services/queue.service.js.map +1 -1
  15. package/dist/services/search.service.d.ts +4 -4
  16. package/dist/services/search.service.js +10 -9
  17. package/dist/services/search.service.js.map +1 -1
  18. package/dist/spotify/client.d.ts +2 -0
  19. package/dist/spotify/client.js +170 -46
  20. package/dist/spotify/client.js.map +1 -1
  21. package/dist/spotify/types.d.ts +2 -0
  22. package/dist/storage/config.d.ts +3 -0
  23. package/dist/storage/config.js +3 -0
  24. package/dist/storage/config.js.map +1 -1
  25. package/dist/ui/completions.d.ts +3 -0
  26. package/dist/ui/completions.js +237 -0
  27. package/dist/ui/completions.js.map +1 -0
  28. package/dist/ui/interactive-search.d.ts +36 -0
  29. package/dist/ui/interactive-search.js +337 -0
  30. package/dist/ui/interactive-search.js.map +1 -0
  31. package/dist/ui/output.d.ts +27 -11
  32. package/dist/ui/output.js +87 -45
  33. package/dist/ui/output.js.map +1 -1
  34. package/dist/ui/progress.d.ts +6 -0
  35. package/dist/ui/progress.js +25 -0
  36. package/dist/ui/progress.js.map +1 -0
  37. package/dist/ui/prompts.d.ts +11 -1
  38. package/dist/ui/prompts.js +65 -13
  39. package/dist/ui/prompts.js.map +1 -1
  40. package/dist/ui/watch.js +3 -2
  41. package/dist/ui/watch.js.map +1 -1
  42. package/dist/utils/errors.js +2 -1
  43. package/dist/utils/errors.js.map +1 -1
  44. package/dist/utils/text.d.ts +2 -0
  45. package/dist/utils/text.js +10 -0
  46. package/dist/utils/text.js.map +1 -0
  47. package/package.json +2 -1
@@ -1,6 +1,19 @@
1
1
  import { AppError, AuthenticationRequiredError, NoActiveDeviceError, PremiumRequiredError, RateLimitedError, SpotifyApiError, toError, } from '../utils/errors.js';
2
+ import { sanitizeOneLineText } from '../utils/text.js';
2
3
  const API_BASE_URL = 'https://api.spotify.com/v1';
3
4
  const MAX_RATE_LIMIT_RETRIES = 3;
5
+ const PLAYBACK_CONTROL_REQUESTS = new Set([
6
+ 'PUT /me/player',
7
+ 'PUT /me/player/play',
8
+ 'PUT /me/player/pause',
9
+ 'POST /me/player/next',
10
+ 'POST /me/player/previous',
11
+ 'PUT /me/player/seek',
12
+ 'PUT /me/player/repeat',
13
+ 'PUT /me/player/volume',
14
+ 'PUT /me/player/shuffle',
15
+ 'POST /me/player/queue',
16
+ ]);
4
17
  const sleep = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
5
18
  export class SpotifyClient {
6
19
  authService;
@@ -35,83 +48,194 @@ export class SpotifyClient {
35
48
  headers.set('Content-Type', 'application/json');
36
49
  body = JSON.stringify(options.body);
37
50
  }
38
- const execute = async (token) => {
39
- headers.set('Authorization', `Bearer ${token}`);
51
+ throwIfExternallyAborted(options.signal);
52
+ let accessToken = await this.authService.getAccessToken();
53
+ let refreshedToken = false;
54
+ let rateLimitRetries = 0;
55
+ while (true) {
56
+ throwIfExternallyAborted(options.signal);
57
+ headers.set('Authorization', `Bearer ${accessToken}`);
58
+ const attempt = createAttemptSignal(options.signal);
59
+ let shouldRefreshToken = false;
60
+ let retryDelayMs;
40
61
  try {
41
- return await this.fetcher(url, {
62
+ const response = await this.fetcher(url, {
42
63
  method,
43
64
  headers,
44
- signal: AbortSignal.timeout(15_000),
65
+ signal: attempt.signal,
45
66
  ...(body === undefined ? {} : { body }),
46
67
  });
68
+ if (response.status === 401 && !refreshedToken) {
69
+ shouldRefreshToken = true;
70
+ }
71
+ else if (response.status === 429 &&
72
+ rateLimitRetries < MAX_RATE_LIMIT_RETRIES) {
73
+ const retryAfterSeconds = getRetryAfterSeconds(response);
74
+ const exponentialBackoffMs = 500 * 2 ** rateLimitRetries;
75
+ rateLimitRetries += 1;
76
+ retryDelayMs = Math.max(retryAfterSeconds * 1_000, exponentialBackoffMs);
77
+ }
78
+ else {
79
+ if (!response.ok) {
80
+ const mappedError = await mapSpotifyError(response, method, path);
81
+ throwIfAttemptAborted(attempt.signal, options.signal);
82
+ throw mappedError;
83
+ }
84
+ if (response.status === 204)
85
+ return undefined;
86
+ const text = await response.text();
87
+ throwIfAttemptAborted(attempt.signal, options.signal);
88
+ if (!text)
89
+ return undefined;
90
+ const contentType = response.headers.get('content-type')?.toLocaleLowerCase() ?? '';
91
+ if (!contentType.includes('json')) {
92
+ if (method !== 'GET')
93
+ return undefined;
94
+ throw new SpotifyApiError('Spotify returned an unexpected non-JSON response.', response.status);
95
+ }
96
+ try {
97
+ return JSON.parse(text);
98
+ }
99
+ catch {
100
+ throw new SpotifyApiError('Spotify returned malformed JSON.', response.status);
101
+ }
102
+ }
47
103
  }
48
104
  catch (error) {
49
- const normalizedError = toError(error);
50
- if (normalizedError.name === 'TimeoutError') {
51
- throw new AppError('Spotify did not respond within 15 seconds. Try again.');
52
- }
53
- throw new AppError(`Unable to reach Spotify: ${normalizedError.message}`);
105
+ throw normalizeAttemptError(error, attempt.signal, options.signal);
54
106
  }
55
- };
56
- let accessToken = await this.authService.getAccessToken();
57
- let refreshedToken = false;
58
- let rateLimitRetries = 0;
59
- let response;
60
- while (true) {
61
- response = await execute(accessToken);
62
- if (response.status === 401 && !refreshedToken) {
107
+ finally {
108
+ attempt.cleanup();
109
+ }
110
+ if (shouldRefreshToken) {
111
+ throwIfExternallyAborted(options.signal);
63
112
  accessToken = await this.authService.forceRefreshAccessToken();
64
113
  refreshedToken = true;
65
114
  continue;
66
115
  }
67
- if (response.status === 429 && rateLimitRetries < MAX_RATE_LIMIT_RETRIES) {
68
- const retryAfterMs = getRetryAfterMilliseconds(response);
69
- const exponentialBackoffMs = 500 * 2 ** rateLimitRetries;
70
- rateLimitRetries += 1;
71
- await this.sleeper(Math.max(retryAfterMs, exponentialBackoffMs));
116
+ if (retryDelayMs !== undefined) {
117
+ await this.waitForRetry(retryDelayMs, options.signal);
72
118
  continue;
73
119
  }
74
- break;
75
120
  }
76
- if (!response.ok)
77
- throw await mapSpotifyError(response);
78
- if (response.status === 204)
79
- return undefined;
80
- const text = await response.text();
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);
121
+ }
122
+ async waitForRetry(milliseconds, signal) {
123
+ throwIfExternallyAborted(signal);
124
+ if (!signal) {
125
+ await this.sleeper(milliseconds);
126
+ return;
127
+ }
128
+ if (this.sleeper === sleep) {
129
+ await abortableSleep(milliseconds, signal);
130
+ return;
88
131
  }
132
+ let abortListener;
133
+ const aborted = new Promise((_resolve, reject) => {
134
+ abortListener = () => reject(getExternalAbortReason(signal));
135
+ signal.addEventListener('abort', abortListener, { once: true });
136
+ if (signal.aborted)
137
+ abortListener();
138
+ });
89
139
  try {
90
- return JSON.parse(text);
140
+ await Promise.race([this.sleeper(milliseconds), aborted]);
91
141
  }
92
- catch {
93
- throw new SpotifyApiError('Spotify returned malformed JSON.', response.status);
142
+ finally {
143
+ if (abortListener)
144
+ signal.removeEventListener('abort', abortListener);
94
145
  }
95
146
  }
96
147
  }
97
- function getRetryAfterMilliseconds(response) {
98
- const seconds = Number(response.headers.get('retry-after'));
99
- return Number.isFinite(seconds) && seconds >= 0 ? seconds * 1_000 : 0;
148
+ function createAttemptSignal(externalSignal) {
149
+ const controller = new AbortController();
150
+ const abortFromExternalSignal = () => {
151
+ if (externalSignal)
152
+ controller.abort(getExternalAbortReason(externalSignal));
153
+ };
154
+ externalSignal?.addEventListener('abort', abortFromExternalSignal, { once: true });
155
+ if (externalSignal?.aborted)
156
+ abortFromExternalSignal();
157
+ const timeout = setTimeout(() => controller.abort(new DOMException('The operation timed out.', 'TimeoutError')), 15_000);
158
+ timeout.unref();
159
+ let cleanedUp = false;
160
+ return {
161
+ signal: controller.signal,
162
+ cleanup: () => {
163
+ if (cleanedUp)
164
+ return;
165
+ cleanedUp = true;
166
+ clearTimeout(timeout);
167
+ externalSignal?.removeEventListener('abort', abortFromExternalSignal);
168
+ },
169
+ };
170
+ }
171
+ function normalizeAttemptError(error, attemptSignal, externalSignal) {
172
+ if (externalSignal?.aborted)
173
+ return getExternalAbortReason(externalSignal);
174
+ const normalizedError = toError(error);
175
+ if (normalizedError.name === 'TimeoutError' ||
176
+ (attemptSignal.aborted && toError(attemptSignal.reason).name === 'TimeoutError')) {
177
+ return new AppError('Spotify did not respond within 15 seconds. Try again.');
178
+ }
179
+ if (normalizedError instanceof AppError)
180
+ return normalizedError;
181
+ return new AppError(`Unable to reach Spotify: ${sanitizeOneLineText(normalizedError.message)}`);
182
+ }
183
+ function throwIfAttemptAborted(attemptSignal, externalSignal) {
184
+ throwIfExternallyAborted(externalSignal);
185
+ if (attemptSignal.aborted)
186
+ throw attemptSignal.reason;
100
187
  }
101
- async function mapSpotifyError(response) {
188
+ function throwIfExternallyAborted(signal) {
189
+ if (signal?.aborted)
190
+ throw getExternalAbortReason(signal);
191
+ }
192
+ function getExternalAbortReason(signal) {
193
+ const reason = signal.reason;
194
+ if (reason instanceof Error && reason.name === 'AbortError')
195
+ return reason;
196
+ return new DOMException('The operation was aborted.', 'AbortError');
197
+ }
198
+ function abortableSleep(milliseconds, signal) {
199
+ return new Promise((resolve, reject) => {
200
+ const timer = setTimeout(() => {
201
+ signal.removeEventListener('abort', abortListener);
202
+ resolve();
203
+ }, milliseconds);
204
+ const abortListener = () => {
205
+ clearTimeout(timer);
206
+ reject(getExternalAbortReason(signal));
207
+ };
208
+ signal.addEventListener('abort', abortListener, { once: true });
209
+ if (signal.aborted)
210
+ abortListener();
211
+ });
212
+ }
213
+ function getRetryAfterSeconds(response) {
214
+ const header = response.headers.get('retry-after');
215
+ if (header === null)
216
+ return 1;
217
+ const seconds = Number(header);
218
+ if (!Number.isFinite(seconds) || seconds < 0)
219
+ return 1;
220
+ return Math.ceil(seconds);
221
+ }
222
+ async function mapSpotifyError(response, method, path) {
102
223
  const body = await readErrorBody(response);
103
224
  const spotifyMessage = typeof body.error === 'object' ? body.error?.message : body.error_description;
104
- const message = spotifyMessage || `Spotify API request failed with HTTP ${response.status}.`;
225
+ const sanitizedMessage = spotifyMessage ? sanitizeOneLineText(spotifyMessage) : '';
226
+ const message = sanitizedMessage || `Spotify API request failed with HTTP ${response.status}.`;
105
227
  if (response.status === 401) {
106
228
  return new AuthenticationRequiredError('Spotify authentication has expired or was revoked.\n\nRun: spoti login');
107
229
  }
108
230
  if (response.status === 403 && /premium/i.test(message))
109
231
  return new PremiumRequiredError();
110
- if (response.status === 404 && /device/i.test(message))
232
+ if (response.status === 404 &&
233
+ PLAYBACK_CONTROL_REQUESTS.has(`${method} ${path}`) &&
234
+ /\b(?:no active device|device not found)\b/i.test(message)) {
111
235
  return new NoActiveDeviceError();
236
+ }
112
237
  if (response.status === 429) {
113
- const retryAfter = Number(response.headers.get('retry-after') ?? '1');
114
- return new RateLimitedError(Number.isFinite(retryAfter) ? retryAfter : 1);
238
+ return new RateLimitedError(getRetryAfterSeconds(response));
115
239
  }
116
240
  return new SpotifyApiError(message, response.status);
117
241
  }
@@ -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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"}
@@ -122,6 +122,8 @@ export interface SpotifyCursorPaging<T> {
122
122
  }
123
123
  export interface SpotifyPlaybackState {
124
124
  is_playing: boolean;
125
+ repeat_state: string;
126
+ shuffle_state: boolean;
125
127
  progress_ms: number | null;
126
128
  item: SpotifyPlaybackItem | null;
127
129
  device: {
@@ -9,9 +9,11 @@ export declare const CONFIG_KEYS: readonly ["spotifyClientId", "watchAfterPlay",
9
9
  export type ConfigKey = (typeof CONFIG_KEYS)[number];
10
10
  export declare const DEFAULT_CONFIG: Readonly<AppConfig>;
11
11
  export interface ConfigStore {
12
+ readonly path?: string;
12
13
  read(): Promise<AppConfig>;
13
14
  write(config: AppConfig): Promise<void>;
14
15
  set<Key extends ConfigKey>(key: Key, value: AppConfig[Key]): Promise<void>;
16
+ resetKey<Key extends ConfigKey>(key: Key): Promise<void>;
15
17
  reset(): Promise<void>;
16
18
  }
17
19
  export interface FileConfigStoreOptions {
@@ -24,6 +26,7 @@ export declare class FileConfigStore implements ConfigStore {
24
26
  read(): Promise<AppConfig>;
25
27
  write(config: AppConfig): Promise<void>;
26
28
  set<Key extends ConfigKey>(key: Key, value: AppConfig[Key]): Promise<void>;
29
+ resetKey<Key extends ConfigKey>(key: Key): Promise<void>;
27
30
  reset(): Promise<void>;
28
31
  }
29
32
  export declare function parseConfigValue<Key extends ConfigKey>(key: Key, value: string): AppConfig[Key];
@@ -83,6 +83,9 @@ export class FileConfigStore {
83
83
  const current = await this.read();
84
84
  await this.write({ ...current, [key]: value });
85
85
  }
86
+ async resetKey(key) {
87
+ await this.set(key, DEFAULT_CONFIG[key]);
88
+ }
86
89
  async reset() {
87
90
  try {
88
91
  await unlink(this.path);
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/storage/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,qBAAqB,GAAG,CAAC;KAC5B,MAAM,EAAE;KACR,IAAI,EAAE;KACN,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,GAAG,CAAC;KACR,KAAK,CAAC,gBAAgB,CAAC,CAAC;AAE3B,MAAM,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC;IAClC,eAAe,EAAE,qBAAqB,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC/D,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAC1C,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;CAC1E,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,iBAAiB;IACjB,gBAAgB;IAChB,mBAAmB;CACX,CAAC;AAGX,MAAM,CAAC,MAAM,cAAc,GAAwB,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAazF,MAAM,OAAO,eAAe;IACjB,IAAI,CAAS;IACL,SAAS,CAAS;IAEnC,YAAY,UAAkC,EAAE;QAC9C,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,EAAE,CAAC;QAC3D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,QAAgB,CAAC;QACrB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,cAAc,CAAC,KAAK,CAAC;gBAAE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;YACxD,MAAM,IAAI,kBAAkB,CAC1B,6CAA6C,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CACtE,CAAC;QACJ,CAAC;QAED,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAY,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,kBAAkB,CAAC,8CAA8C,CAAC,CAAC;QAC/E,CAAC;QAED,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,kBAAkB,CAAC,kDAAkD,CAAC,CAAC;QACnF,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAiB;QAC3B,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;YACvB,MAAM,IAAI,kBAAkB,CAAC,iDAAiD,CAAC,CAAC;QAClF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9D,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,kBAAkB,CAC1B,8DAA8D,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CACvF,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,UAAU,EAAE,MAAM,CAAC,CAAC;QAC1E,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;gBAC7E,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,KAAK;aACZ,CAAC,CAAC;YACH,MAAM,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;YAClC,MAAM,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACnD,MAAM,IAAI,kBAAkB,CAC1B,8CAA8C,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CACvE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAwB,GAAQ,EAAE,KAAqB;QAC9D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,kBAAkB,CAC1B,8CAA8C,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CACvE,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,MAAM,UAAU,gBAAgB,CAC9B,GAAQ,EACR,KAAa;IAEb,IAAI,GAAG,KAAK,iBAAiB,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,qBAAqB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACxD,IAAI,QAAQ,CAAC,OAAO;YAAE,OAAO,QAAQ,CAAC,IAAsB,CAAC;QAC7D,MAAM,IAAI,kBAAkB,CAC1B,qEAAqE,CACtE,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,KAAK,gBAAgB,EAAE,CAAC;QAC7B,IAAI,KAAK,KAAK,MAAM;YAAE,OAAO,IAAsB,CAAC;QACpD,IAAI,KAAK,KAAK,OAAO;YAAE,OAAO,KAAuB,CAAC;QACtD,MAAM,IAAI,kBAAkB,CAC1B,sEAAsE,CACvE,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,KAAK,mBAAmB,EAAE,CAAC;QAChC,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,IAAI,KAAK,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;gBAC9E,OAAO,QAA0B,CAAC;YACpC,CAAC;QACH,CAAC;QACD,MAAM,IAAI,kBAAkB,CAC1B,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,kBAAkB,CAAC,8BAA8B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,MAAM,IAAI,KAAK;QACf,KAAK,CAAC,IAAI,KAAK,QAAQ,CACxB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/storage/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export type CompletionShell = 'bash' | 'zsh' | 'fish';
2
+ /** Return a self-contained completion definition without running the spoti CLI. */
3
+ export declare function generateCompletionScript(shell: CompletionShell): string;
@@ -0,0 +1,237 @@
1
+ const bashCompletion = `# bash completion for spoti
2
+ _spoti_completion() {
3
+ local cur command
4
+ cur="\${COMP_WORDS[COMP_CWORD]}"
5
+ command="\${COMP_WORDS[1]}"
6
+
7
+ local commands="setup login logout status config interactive now pause resume next previous devices device seek volume queue shuffle repeat album artist playlists playlist liked like unlike recent update search play completion i p pa r np q s vol dev devs pl pls rep rec n prev"
8
+ local global_options="-h --help -V --version"
9
+
10
+ if (( COMP_CWORD == 1 )); then
11
+ COMPREPLY=( $(compgen -W "$commands $global_options" -- "$cur") )
12
+ return
13
+ fi
14
+
15
+ case "$command" in
16
+ config)
17
+ if (( COMP_CWORD == 2 )); then
18
+ COMPREPLY=( $(compgen -W "get set reset path unset -h --help" -- "$cur") )
19
+ elif (( COMP_CWORD == 3 )) && [[ "\${COMP_WORDS[2]}" == get || "\${COMP_WORDS[2]}" == set || "\${COMP_WORDS[2]}" == unset ]]; then
20
+ COMPREPLY=( $(compgen -W "spotifyClientId watchAfterPlay refreshIntervalMs" -- "$cur") )
21
+ elif (( COMP_CWORD == 4 )) && [[ "\${COMP_WORDS[2]}" == set && "\${COMP_WORDS[3]}" == watchAfterPlay ]]; then
22
+ COMPREPLY=( $(compgen -W "true false" -- "$cur") )
23
+ fi
24
+ ;;
25
+ completion)
26
+ COMPREPLY=( $(compgen -W "bash zsh fish -h --help" -- "$cur") )
27
+ ;;
28
+ now|np)
29
+ COMPREPLY=( $(compgen -W "-w --watch -h --help" -- "$cur") )
30
+ ;;
31
+ queue|q|album|artist|playlist|pl)
32
+ COMPREPLY=( $(compgen -W "--first -h --help" -- "$cur") )
33
+ ;;
34
+ playlists|pls|liked|recent|rec|search|s)
35
+ COMPREPLY=( $(compgen -W "-l --limit -h --help" -- "$cur") )
36
+ ;;
37
+ update)
38
+ COMPREPLY=( $(compgen -W "--check -h --help" -- "$cur") )
39
+ ;;
40
+ play|p)
41
+ COMPREPLY=( $(compgen -W "track album artist playlist --first --watch --no-watch -h --help" -- "$cur") )
42
+ ;;
43
+ shuffle)
44
+ COMPREPLY=( $(compgen -W "on off -h --help" -- "$cur") )
45
+ ;;
46
+ repeat|rep)
47
+ COMPREPLY=( $(compgen -W "off track context -h --help" -- "$cur") )
48
+ ;;
49
+ *)
50
+ COMPREPLY=( $(compgen -W "-h --help" -- "$cur") )
51
+ ;;
52
+ esac
53
+ }
54
+
55
+ complete -F _spoti_completion spoti
56
+ `;
57
+ const zshCompletion = `#compdef spoti
58
+ # zsh completion for spoti
59
+
60
+ _spoti() {
61
+ local context state line
62
+ local -a commands
63
+ commands=(
64
+ 'setup:save your Spotify application client ID'
65
+ 'login:log in to Spotify'
66
+ 'logout:remove locally stored Spotify credentials'
67
+ 'status:show authentication status'
68
+ 'config:view and update spoti configuration'
69
+ 'interactive:open the keyboard-driven Spotify search'
70
+ 'now:show the current Spotify playback'
71
+ 'pause:pause playback'
72
+ 'resume:resume playback'
73
+ 'next:skip to the next track'
74
+ 'previous:return to the previous track'
75
+ 'devices:list available Spotify Connect devices'
76
+ 'device:transfer playback to a Spotify Connect device'
77
+ 'seek:seek within the current track'
78
+ 'volume:set or adjust the active device volume'
79
+ 'queue:show the playback queue or add a searched track'
80
+ 'shuffle:show or change the playback shuffle state'
81
+ 'repeat:show or change the playback repeat mode'
82
+ 'album:search for and show an album'
83
+ 'artist:search for and show an artist'
84
+ 'playlists:list and optionally play your Spotify playlists'
85
+ 'playlist:show one of your Spotify playlists'
86
+ 'liked:list and optionally play your liked tracks'
87
+ 'like:add the current track to your Spotify library'
88
+ 'unlike:remove the current track from your Spotify library'
89
+ 'recent:show and optionally play recently played tracks'
90
+ 'update:check for or install the latest spoti version'
91
+ 'search:search Spotify tracks'
92
+ 'play:play a track, album, artist, or playlist'
93
+ 'completion:print a static shell completion script'
94
+ 'i:alias for interactive'
95
+ 'p:alias for play'
96
+ 'pa:alias for pause'
97
+ 'r:alias for resume'
98
+ 'np:alias for now'
99
+ 'q:alias for queue'
100
+ 's:alias for search'
101
+ 'vol:alias for volume'
102
+ 'dev:alias for device'
103
+ 'devs:alias for devices'
104
+ 'pl:alias for playlist'
105
+ 'pls:alias for playlists'
106
+ 'rep:alias for repeat'
107
+ 'rec:alias for recent'
108
+ 'n:alias for next'
109
+ 'prev:alias for previous'
110
+ )
111
+
112
+ _arguments -C \\
113
+ '(-h --help)'{-h,--help}'[display help]' \\
114
+ '(-V --version)'{-V,--version}'[display version]' \
115
+ '1:command:->command' \
116
+ '*::argument:->arguments'
117
+
118
+ case "$state" in
119
+ command)
120
+ _describe 'spoti command' commands
121
+ ;;
122
+ arguments)
123
+ case "$words[2]" in
124
+ config)
125
+ local -a config_commands
126
+ config_commands=(
127
+ 'get:read a configuration value'
128
+ 'set:set a configuration value'
129
+ 'reset:reset configuration to defaults'
130
+ 'path:show the configuration file path'
131
+ 'unset:remove a configuration value'
132
+ )
133
+ if (( CURRENT == 3 )); then
134
+ _describe 'config command' config_commands
135
+ elif [[ "$words[3]" == get || "$words[3]" == set || "$words[3]" == unset ]]; then
136
+ _values 'configuration key' spotifyClientId watchAfterPlay refreshIntervalMs
137
+ fi
138
+ ;;
139
+ completion)
140
+ _values 'shell' bash zsh fish
141
+ ;;
142
+ now|np)
143
+ _arguments '(-w --watch)'{-w,--watch}'[continuously refresh playback information]'
144
+ ;;
145
+ queue|q|album|artist|playlist|pl)
146
+ _arguments '--first[select the first result without prompting]' '*:query:'
147
+ ;;
148
+ playlists|pls|liked|recent|rec|search|s)
149
+ _arguments '(-l --limit)'{-l,--limit}'[maximum number of results]:number:' '*:query:'
150
+ ;;
151
+ update)
152
+ _arguments '--check[check without installing]'
153
+ ;;
154
+ play|p)
155
+ _arguments '--first[play the first result without prompting]' '--watch[continuously refresh playback information]' '--no-watch[return after starting playback]' '1:type:(track album artist playlist)' '*:query:'
156
+ ;;
157
+ shuffle)
158
+ _values 'shuffle state' on off
159
+ ;;
160
+ repeat|rep)
161
+ _values 'repeat mode' off track context
162
+ ;;
163
+ esac
164
+ ;;
165
+ esac
166
+ }
167
+
168
+ _spoti "$@"
169
+ `;
170
+ const fishCompletion = `# fish completion for spoti
171
+ complete -c spoti -f
172
+ complete -c spoti -s h -l help -d 'Display help'
173
+ complete -c spoti -s V -l version -d 'Display version'
174
+
175
+ function __spoti_needs_command
176
+ not __fish_seen_subcommand_from setup login logout status config interactive now pause resume next previous devices device seek volume queue shuffle repeat album artist playlists playlist liked like unlike recent update search play completion i p pa r np q s vol dev devs pl pls rep rec n prev
177
+ end
178
+ complete -c spoti -n __spoti_needs_command -a setup -d 'Save your Spotify application client ID'
179
+ complete -c spoti -n __spoti_needs_command -a login -d 'Log in to Spotify'
180
+ complete -c spoti -n __spoti_needs_command -a logout -d 'Remove locally stored Spotify credentials'
181
+ complete -c spoti -n __spoti_needs_command -a status -d 'Show authentication status'
182
+ complete -c spoti -n __spoti_needs_command -a config -d 'View and update configuration'
183
+ complete -c spoti -n __spoti_needs_command -a interactive -d 'Open the keyboard-driven Spotify search'
184
+ complete -c spoti -n __spoti_needs_command -a now -d 'Show current playback'
185
+ complete -c spoti -n __spoti_needs_command -a pause -d 'Pause playback'
186
+ complete -c spoti -n __spoti_needs_command -a resume -d 'Resume playback'
187
+ complete -c spoti -n __spoti_needs_command -a next -d 'Skip to the next track'
188
+ complete -c spoti -n __spoti_needs_command -a previous -d 'Return to the previous track'
189
+ complete -c spoti -n __spoti_needs_command -a devices -d 'List Spotify Connect devices'
190
+ complete -c spoti -n __spoti_needs_command -a device -d 'Transfer playback to a device'
191
+ complete -c spoti -n __spoti_needs_command -a seek -d 'Seek within the current track'
192
+ complete -c spoti -n __spoti_needs_command -a volume -d 'Set or adjust volume'
193
+ complete -c spoti -n __spoti_needs_command -a queue -d 'Show or add to the queue'
194
+ complete -c spoti -n __spoti_needs_command -a shuffle -d 'Show or change playback shuffle state'
195
+ complete -c spoti -n __spoti_needs_command -a repeat -d 'Show or change playback repeat mode'
196
+ complete -c spoti -n __spoti_needs_command -a album -d 'Search for an album'
197
+ complete -c spoti -n __spoti_needs_command -a artist -d 'Search for an artist'
198
+ complete -c spoti -n __spoti_needs_command -a playlists -d 'List and optionally play your playlists'
199
+ complete -c spoti -n __spoti_needs_command -a playlist -d 'Show a playlist'
200
+ complete -c spoti -n __spoti_needs_command -a liked -d 'List and optionally play liked tracks'
201
+ complete -c spoti -n __spoti_needs_command -a like -d 'Like the current track'
202
+ complete -c spoti -n __spoti_needs_command -a unlike -d 'Unlike the current track'
203
+ complete -c spoti -n __spoti_needs_command -a recent -d 'Show and optionally play recently played tracks'
204
+ complete -c spoti -n __spoti_needs_command -a update -d 'Check for or install updates'
205
+ complete -c spoti -n __spoti_needs_command -a search -d 'Search Spotify tracks'
206
+ complete -c spoti -n __spoti_needs_command -a play -d 'Play a track, album, artist, or playlist'
207
+ complete -c spoti -n __spoti_needs_command -a completion -d 'Print a shell completion script'
208
+ complete -c spoti -n __spoti_needs_command -a 'i p pa r np q s vol dev devs pl pls rep rec n prev' -d 'Command alias'
209
+
210
+ complete -c spoti -n '__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set reset path unset' -a 'get set reset path unset'
211
+ complete -c spoti -n '__fish_seen_subcommand_from config; and __fish_seen_subcommand_from get set unset' -a 'spotifyClientId watchAfterPlay refreshIntervalMs'
212
+ complete -c spoti -n '__fish_seen_subcommand_from completion' -a 'bash zsh fish'
213
+ complete -c spoti -n '__fish_seen_subcommand_from now np' -s w -l watch -d 'Continuously refresh playback information'
214
+ complete -c spoti -n '__fish_seen_subcommand_from queue q album artist playlist pl' -l first -d 'Select the first result without prompting'
215
+ complete -c spoti -n '__fish_seen_subcommand_from playlists pls liked recent rec search s' -s l -l limit -r -d 'Maximum number of results'
216
+ complete -c spoti -n '__fish_seen_subcommand_from update' -l check -d 'Check without installing'
217
+ complete -c spoti -n '__fish_seen_subcommand_from play p' -l first -d 'Play the first result without prompting'
218
+ complete -c spoti -n '__fish_seen_subcommand_from play p' -l watch -d 'Continuously refresh playback information'
219
+ complete -c spoti -n '__fish_seen_subcommand_from play p' -l no-watch -d 'Return after starting playback'
220
+ complete -c spoti -n '__fish_seen_subcommand_from play p' -a 'track album artist playlist'
221
+ complete -c spoti -n '__fish_seen_subcommand_from shuffle' -a 'on off'
222
+ complete -c spoti -n '__fish_seen_subcommand_from repeat rep' -a 'off track context'
223
+ `;
224
+ /** Return a self-contained completion definition without running the spoti CLI. */
225
+ export function generateCompletionScript(shell) {
226
+ switch (shell) {
227
+ case 'bash':
228
+ return bashCompletion;
229
+ case 'zsh':
230
+ return zshCompletion;
231
+ case 'fish':
232
+ return fishCompletion;
233
+ default:
234
+ throw new Error(`Unsupported shell: ${String(shell)}`);
235
+ }
236
+ }
237
+ //# sourceMappingURL=completions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completions.js","sourceRoot":"","sources":["../../src/ui/completions.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuDtB,CAAC;AAEF,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgHrB,CAAC;AAEF,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqDtB,CAAC;AAEF,mFAAmF;AACnF,MAAM,UAAU,wBAAwB,CAAC,KAAsB;IAC7D,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,MAAM;YACT,OAAO,cAAc,CAAC;QACxB,KAAK,KAAK;YACR,OAAO,aAAa,CAAC;QACvB,KAAK,MAAM;YACT,OAAO,cAAc,CAAC;QACxB;YACE,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}