@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
package/README.md CHANGED
@@ -81,6 +81,21 @@ npm run dev -- status
81
81
 
82
82
  ## Usage
83
83
 
84
+ Run `spoti` with no command to see the complete command overview:
85
+
86
+ ```bash
87
+ spoti
88
+ ```
89
+
90
+ Open the interactive multi-category search explicitly:
91
+
92
+ ```bash
93
+ spoti interactive
94
+ # alias: spoti i
95
+ ```
96
+
97
+ Type a query and press Enter. Use `Tab` or left/right to switch between tracks, albums, artists, and playlists; use up/down to select; press Enter to play; press Esc to exit. Type or backspace after a search to edit the query. Category results are cached while the query remains unchanged, and temporary search or playback failures can be retried without reopening the command. The terminal is always restored when the interaction ends.
98
+
84
99
  Authenticate once through Spotify's browser authorization page:
85
100
 
86
101
  ```bash
@@ -104,8 +119,10 @@ spoti previous
104
119
  spoti volume 50
105
120
  spoti volume +10
106
121
  spoti volume -10
122
+ spoti shuffle
107
123
  spoti shuffle on
108
124
  spoti shuffle off
125
+ spoti repeat
109
126
  spoti repeat off
110
127
  spoti repeat track
111
128
  spoti repeat context
@@ -121,7 +138,7 @@ spoti device "My Computer"
121
138
 
122
139
  Use the displayed one-based number, exact device name, or Spotify device ID.
123
140
 
124
- When playback has no active device, `spoti play` and `spoti resume` automatically target it if exactly one controllable device is available.
141
+ When playback reports no active device, `spoti play` and `spoti resume` retry the one active controllable device if Spotify reports one, or the only controllable device when exactly one is available. If several inactive devices are available, `spoti` asks you to select one explicitly.
125
142
 
126
143
  Seek within the current track:
127
144
 
@@ -131,7 +148,7 @@ spoti seek +30
131
148
  spoti seek -10
132
149
  ```
133
150
 
134
- View the queue or search for a track to add:
151
+ View the queue or search for a track to add. When Spotify represents an otherwise empty queue by repeating only the current track, `spoti` reports the queue as empty instead of printing duplicate entries:
135
152
 
136
153
  ```bash
137
154
  spoti queue
@@ -161,7 +178,7 @@ spoti play playlist "Workout"
161
178
  spoti play playlist 1
162
179
  ```
163
180
 
164
- User playlists are sorted consistently by name, so the displayed number can be reused with `spoti playlist <number>` or `spoti play playlist <number>`.
181
+ User playlists are sorted consistently by name, so the displayed number can be reused with `spoti playlist <number>` or `spoti play playlist <number>`. In an interactive terminal, `spoti playlists` also lets you select a displayed playlist to play immediately; press Enter to leave playback unchanged.
165
182
 
166
183
  In an interactive terminal, `spoti album` can play the entire album or a selected track after showing its details. `spoti artist` can play the artist context or let you select one of the artist’s albums, and `spoti playlist` can start the selected playlist. Non-interactive runs remain display-only and never start playback implicitly.
167
184
 
@@ -178,7 +195,7 @@ spoti recent
178
195
  spoti recent --limit 10
179
196
  ```
180
197
 
181
- `spoti like` and `spoti unlike` operate on the currently playing track. Episodes, advertisements, local files, and unavailable items are ignored safely.
198
+ `spoti like` and `spoti unlike` operate on the currently playing track. Episodes, advertisements, local files, and unavailable items are ignored safely. In an interactive terminal, both `spoti liked` and `spoti recent` show a numbered list and then let you select a track to play. Press Enter without a number to leave playback unchanged; non-interactive runs remain display-only.
182
199
 
183
200
  Check for updates or install the latest npm release:
184
201
 
@@ -197,7 +214,50 @@ spoti logout
197
214
 
198
215
  When attached to an interactive terminal, `spoti play <query>` asks you to select a result. In non-interactive usage it chooses the first result automatically; `--first` makes that behavior explicit.
199
216
 
200
- Watch mode continuously refreshes the current track and progress until `Ctrl+C` is pressed. `--watch` enables it for one command, while `--no-watch` overrides a saved preference.
217
+ Watch mode continuously refreshes the current track and progress until `Ctrl+C` is pressed. `--watch` enables it for one command, while `--no-watch` overrides a saved preference. Run `spoti shuffle` or `spoti repeat` without a value to inspect the current state. Use `spoti shuffle on|off` or `spoti repeat off|track|context` to change it.
218
+
219
+
220
+ ### Command aliases
221
+
222
+ Common aliases include:
223
+
224
+ ```text
225
+ i interactive p play pa pause
226
+ r resume np now q queue s search
227
+ vol volume dev device devs devices
228
+ pl playlist pls playlists rep repeat
229
+ rec recent n next prev previous
230
+ ```
231
+
232
+ ### Shell completions
233
+
234
+ Generate a static completion script without invoking Spotify or making network requests:
235
+
236
+ ```bash
237
+ spoti completion bash
238
+ spoti completion zsh
239
+ spoti completion fish
240
+ ```
241
+
242
+ For the current shell session:
243
+
244
+ ```bash
245
+ source <(spoti completion bash) # Bash
246
+ source <(spoti completion zsh) # Zsh
247
+ spoti completion fish | source # Fish
248
+ ```
249
+
250
+ Interactive network operations display a spinner on stderr. Indicators remain disabled outside a TTY.
251
+
252
+ ### Terminal formatting
253
+
254
+ Interactive terminals use restrained styling for names, metadata, headings, and playback progress. Redirected output remains plain text. Set the standard `NO_COLOR` environment variable to disable decorative styling:
255
+
256
+ ```bash
257
+ NO_COLOR=1 spoti now
258
+ ```
259
+
260
+ Spotify-provided names and descriptions are normalized to safe single-line terminal text before display.
201
261
 
202
262
  ## Configuration
203
263
 
@@ -215,6 +275,8 @@ spoti config set spotifyClientId "your-client-id"
215
275
  spoti config get watchAfterPlay
216
276
  spoti config set watchAfterPlay true
217
277
  spoti config set refreshIntervalMs 2000
278
+ spoti config unset spotifyClientId
279
+ spoti config path
218
280
  spoti config reset
219
281
  ```
220
282
 
@@ -274,4 +336,4 @@ The release workflow attaches the npm package tarball and a `SHA256SUMS` file, a
274
336
 
275
337
  ## Current scope
276
338
 
277
- Version `0.3.0` supports authentication and persistent client-ID setup; track, album, artist, and playlist discovery and playback; guided playback actions; current playback and watch mode; pause/resume and next/previous; volume, seek, shuffle, and repeat; queue and library management; recently played tracks; deterministic numeric device and playlist selection; and cached update notifications with explicit update commands. JSON output and a TUI remain planned for later releases.
339
+ Version `0.5.0` improves TTY-aware terminal formatting, interactive-search editing, retries and cancellation, terminal-safe Spotify metadata, collection playback selection, player-state visibility, device fallback, and API error handling. A full Ink-based TUI remains planned for `v1.0.0`.
package/dist/app.d.ts CHANGED
@@ -10,8 +10,10 @@ import type { RecentService } from './services/recent.service.js';
10
10
  import type { SearchService } from './services/search.service.js';
11
11
  import { type UpdateService } from './services/update.service.js';
12
12
  import { type ConfigStore } from './storage/config.js';
13
- import { type Output } from './ui/output.js';
14
- import { confirmUpdate, promptSpotifyClientId, selectAlbum, selectAlbumAction, selectArtist, selectArtistAction, selectPlaylist, selectPlaylistAction, selectTrack } from './ui/prompts.js';
13
+ import { type Output, type OutputStyles } from './ui/output.js';
14
+ import { confirmUpdate, promptSpotifyClientId, selectAlbum, selectAlbumAction, selectArtist, selectArtistAction, selectLikedTrack, selectListedPlaylist, selectPlaylist, selectPlaylistAction, selectRecentTrack, selectTrack } from './ui/prompts.js';
15
+ import { type ProgressRunner } from './ui/progress.js';
16
+ import { type InteractiveSearchResult } from './ui/interactive-search.js';
15
17
  import { type PlaybackWatcher } from './ui/watch.js';
16
18
  export interface AppDependencies {
17
19
  auth: AuthService;
@@ -30,11 +32,17 @@ export interface AppDependencies {
30
32
  chooseAlbum?: typeof selectAlbum;
31
33
  chooseArtist?: typeof selectArtist;
32
34
  choosePlaylist?: typeof selectPlaylist;
35
+ chooseListedPlaylist?: typeof selectListedPlaylist;
33
36
  chooseAlbumAction?: typeof selectAlbumAction;
34
37
  chooseArtistAction?: typeof selectArtistAction;
35
38
  choosePlaylistAction?: typeof selectPlaylistAction;
39
+ chooseLikedTrack?: typeof selectLikedTrack;
40
+ chooseRecentTrack?: typeof selectRecentTrack;
36
41
  requestSpotifyClientId?: typeof promptSpotifyClientId;
37
42
  confirmUpdate?: typeof confirmUpdate;
43
+ interactiveSearch?: () => Promise<InteractiveSearchResult>;
44
+ progress?: ProgressRunner;
45
+ styles?: OutputStyles;
38
46
  watchPlayback?: PlaybackWatcher;
39
47
  }
40
48
  export declare function createProgram(dependencies: AppDependencies): Command;