@bzenky/spoti 0.2.0 → 0.4.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 (70) hide show
  1. package/README.md +122 -4
  2. package/dist/app.d.ts +23 -1
  3. package/dist/app.js +397 -36
  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/cli.js +54 -0
  9. package/dist/cli.js.map +1 -1
  10. package/dist/services/auth.service.d.ts +1 -1
  11. package/dist/services/auth.service.js +9 -3
  12. package/dist/services/auth.service.js.map +1 -1
  13. package/dist/services/catalog.service.d.ts +9 -0
  14. package/dist/services/catalog.service.js +22 -0
  15. package/dist/services/catalog.service.js.map +1 -0
  16. package/dist/services/device.service.js +22 -2
  17. package/dist/services/device.service.js.map +1 -1
  18. package/dist/services/library.service.d.ts +13 -0
  19. package/dist/services/library.service.js +46 -0
  20. package/dist/services/library.service.js.map +1 -0
  21. package/dist/services/mappers.d.ts +10 -0
  22. package/dist/services/mappers.js +104 -0
  23. package/dist/services/mappers.js.map +1 -0
  24. package/dist/services/models.d.ts +45 -0
  25. package/dist/services/player.service.d.ts +4 -1
  26. package/dist/services/player.service.js +21 -14
  27. package/dist/services/player.service.js.map +1 -1
  28. package/dist/services/playlist.service.d.ts +9 -0
  29. package/dist/services/playlist.service.js +33 -0
  30. package/dist/services/playlist.service.js.map +1 -0
  31. package/dist/services/recent.service.d.ts +7 -0
  32. package/dist/services/recent.service.js +24 -0
  33. package/dist/services/recent.service.js.map +1 -0
  34. package/dist/services/search.service.d.ts +5 -1
  35. package/dist/services/search.service.js +32 -17
  36. package/dist/services/search.service.js.map +1 -1
  37. package/dist/services/update.service.d.ts +57 -0
  38. package/dist/services/update.service.js +313 -0
  39. package/dist/services/update.service.js.map +1 -0
  40. package/dist/spotify/client.js +14 -1
  41. package/dist/spotify/client.js.map +1 -1
  42. package/dist/spotify/scopes.d.ts +1 -1
  43. package/dist/spotify/scopes.js +4 -0
  44. package/dist/spotify/scopes.js.map +1 -1
  45. package/dist/spotify/types.d.ts +110 -8
  46. package/dist/storage/config.d.ts +5 -1
  47. package/dist/storage/config.js +21 -1
  48. package/dist/storage/config.js.map +1 -1
  49. package/dist/storage/update-cache.d.ts +29 -0
  50. package/dist/storage/update-cache.js +135 -0
  51. package/dist/storage/update-cache.js.map +1 -0
  52. package/dist/ui/completions.d.ts +3 -0
  53. package/dist/ui/completions.js +237 -0
  54. package/dist/ui/completions.js.map +1 -0
  55. package/dist/ui/interactive-search.d.ts +33 -0
  56. package/dist/ui/interactive-search.js +174 -0
  57. package/dist/ui/interactive-search.js.map +1 -0
  58. package/dist/ui/output.d.ts +10 -1
  59. package/dist/ui/output.js +60 -0
  60. package/dist/ui/output.js.map +1 -1
  61. package/dist/ui/progress.d.ts +6 -0
  62. package/dist/ui/progress.js +25 -0
  63. package/dist/ui/progress.js.map +1 -0
  64. package/dist/ui/prompts.d.ts +12 -1
  65. package/dist/ui/prompts.js +73 -6
  66. package/dist/ui/prompts.js.map +1 -1
  67. package/dist/update-worker.d.ts +9 -0
  68. package/dist/update-worker.js +91 -0
  69. package/dist/update-worker.js.map +1 -0
  70. package/package.json +1 -1
package/README.md CHANGED
@@ -21,13 +21,27 @@ Create an application in the [Spotify Developer Dashboard](https://developer.spo
21
21
  http://127.0.0.1:43821/callback
22
22
  ```
23
23
 
24
- Export the application's client ID before running authentication:
24
+ After installing `spoti`, save the application's client ID once:
25
+
26
+ ```bash
27
+ spoti setup
28
+ spoti login
29
+ ```
30
+
31
+ When developing from source, use:
32
+
33
+ ```bash
34
+ npm run dev -- setup
35
+ npm run dev -- login
36
+ ```
37
+
38
+ The setup command stores the public client ID in your local `spoti` configuration. For temporary sessions, CI, or an explicit override, you can still use:
25
39
 
26
40
  ```bash
27
41
  export SPOTIFY_CLIENT_ID="your-client-id"
28
42
  ```
29
43
 
30
- To use a different local callback, register it in the same Spotify application and set:
44
+ The environment variable takes precedence over the stored value. To use a different local callback, register it in the same Spotify application and set:
31
45
 
32
46
  ```bash
33
47
  export SPOTIFY_REDIRECT_URI="http://127.0.0.1:5000/callback"
@@ -67,6 +81,21 @@ npm run dev -- status
67
81
 
68
82
  ## Usage
69
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. The terminal is restored even when a request fails.
98
+
70
99
  Authenticate once through Spotify's browser authorization page:
71
100
 
72
101
  ```bash
@@ -90,15 +119,23 @@ spoti previous
90
119
  spoti volume 50
91
120
  spoti volume +10
92
121
  spoti volume -10
122
+ spoti shuffle on
123
+ spoti shuffle off
124
+ spoti repeat off
125
+ spoti repeat track
126
+ spoti repeat context
93
127
  ```
94
128
 
95
129
  Manage playback devices:
96
130
 
97
131
  ```bash
98
132
  spoti devices
133
+ spoti device 2
99
134
  spoti device "My Computer"
100
135
  ```
101
136
 
137
+ Use the displayed one-based number, exact device name, or Spotify device ID.
138
+
102
139
  When playback has no active device, `spoti play` and `spoti resume` automatically target it if exactly one controllable device is available.
103
140
 
104
141
  Seek within the current track:
@@ -124,6 +161,49 @@ spoti search "Breaking the Habit"
124
161
  spoti search "Breaking the Habit" --limit 5
125
162
  ```
126
163
 
164
+ Search, inspect, and play Spotify contexts:
165
+
166
+ ```bash
167
+ spoti album "Meteora"
168
+ spoti artist "Linkin Park"
169
+ spoti playlists
170
+ spoti playlist 1
171
+ spoti playlist "Workout"
172
+ spoti play track "Numb"
173
+ spoti play album "Meteora"
174
+ spoti play artist "Linkin Park"
175
+ spoti play playlist "Workout"
176
+ spoti play playlist 1
177
+ ```
178
+
179
+ User playlists are sorted consistently by name, so the displayed number can be reused with `spoti playlist <number>` or `spoti play playlist <number>`.
180
+
181
+ 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.
182
+
183
+ `spoti play <query>` remains shorthand for track playback. The words `track`, `album`, `artist`, and `playlist` are treated as explicit types when followed by another argument. For a track query that starts with one of those reserved words, use `spoti play track <query>` (or quote the complete query as one shell argument). Context commands support `--first` to skip interactive selection.
184
+
185
+ Manage and inspect your Spotify library:
186
+
187
+ ```bash
188
+ spoti liked
189
+ spoti liked --limit 10
190
+ spoti like
191
+ spoti unlike
192
+ spoti recent
193
+ spoti recent --limit 10
194
+ ```
195
+
196
+ `spoti like` and `spoti unlike` operate on the currently playing track. Episodes, advertisements, local files, and unavailable items are ignored safely.
197
+
198
+ Check for updates or install the latest npm release:
199
+
200
+ ```bash
201
+ spoti update --check
202
+ spoti update
203
+ ```
204
+
205
+ `spoti update` asks for confirmation before installing the exact version returned by the update check. It never installs an update silently. Normal commands use a cached update result and refresh it in a detached process at most once every 24 hours, so npm availability does not delay or break Spotify controls.
206
+
127
207
  Remove local credentials:
128
208
 
129
209
  ```bash
@@ -134,6 +214,39 @@ When attached to an interactive terminal, `spoti play <query>` asks you to selec
134
214
 
135
215
  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.
136
216
 
217
+
218
+ ### Command aliases
219
+
220
+ Common aliases include:
221
+
222
+ ```text
223
+ i interactive p play pa pause
224
+ r resume np now q queue s search
225
+ vol volume dev device devs devices
226
+ pl playlist pls playlists rep repeat
227
+ rec recent n next prev previous
228
+ ```
229
+
230
+ ### Shell completions
231
+
232
+ Generate a static completion script without invoking Spotify or making network requests:
233
+
234
+ ```bash
235
+ spoti completion bash
236
+ spoti completion zsh
237
+ spoti completion fish
238
+ ```
239
+
240
+ For the current shell session:
241
+
242
+ ```bash
243
+ source <(spoti completion bash) # Bash
244
+ source <(spoti completion zsh) # Zsh
245
+ spoti completion fish | source # Fish
246
+ ```
247
+
248
+ Interactive network operations display a spinner on stderr. Indicators remain disabled outside a TTY.
249
+
137
250
  ## Configuration
138
251
 
139
252
  View all settings:
@@ -145,9 +258,13 @@ spoti config
145
258
  Read, update, or reset settings:
146
259
 
147
260
  ```bash
261
+ spoti config get spotifyClientId
262
+ spoti config set spotifyClientId "your-client-id"
148
263
  spoti config get watchAfterPlay
149
264
  spoti config set watchAfterPlay true
150
265
  spoti config set refreshIntervalMs 2000
266
+ spoti config unset spotifyClientId
267
+ spoti config path
151
268
  spoti config reset
152
269
  ```
153
270
 
@@ -155,6 +272,7 @@ Available settings:
155
272
 
156
273
  | Setting | Default | Description |
157
274
  | --- | ---: | --- |
275
+ | `spotifyClientId` | `null` | Public Spotify application client ID saved by `spoti setup`. |
158
276
  | `watchAfterPlay` | `false` | Keep `spoti play` open in watch mode after playback starts. |
159
277
  | `refreshIntervalMs` | `1000` | Watch refresh interval from `1000` to `30000` milliseconds. |
160
278
 
@@ -174,7 +292,7 @@ or, when `XDG_CONFIG_HOME` is not set:
174
292
  ~/.config/spoti/credentials.json
175
293
  ```
176
294
 
177
- The credentials file is created with user-only permissions (`0600`). Access tokens refresh automatically. Version `0.2.0` adds the `user-read-currently-playing` scope for queue access; credentials created by `0.1.0` require one new `spoti login` authorization. Keep `SPOTIFY_CLIENT_ID` available in the environment because Spotify requires it during token refresh. Never provide or store a Spotify client secret in `spoti`.
295
+ The credentials file is created with user-only permissions (`0600`). Access tokens refresh automatically using the environment client ID when present, otherwise the client ID saved by `spoti setup`. Version `0.3.0` adds minimum permissions for private playlist listing, liked-track access, library modification, and recently played tracks. Existing installations will be asked to run `spoti login` once after upgrading. Never provide or store a Spotify client secret in `spoti`.
178
296
 
179
297
  ## Spotify API policy
180
298
 
@@ -206,4 +324,4 @@ The release workflow attaches the npm package tarball and a `SHA256SUMS` file, a
206
324
 
207
325
  ## Current scope
208
326
 
209
- Version `0.2.0` supports authentication, track search and playback, current playback and watch mode, pause/resume, next/previous, persistent configuration, volume and seek controls, queue management, device listing and selection, and automatic single-device fallback. Shuffle, repeat, album/artist/playlist context playback, library features, JSON output, update notifications, and a TUI are planned for later releases.
327
+ 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; player, queue, library, device, and update controls. The current development branch adds explicit interactive search, aliases, loading indicators, shell completions, configuration polish, and Node 24-based GitHub Actions. A full Ink-based TUI remains planned for `v1.0.0`.
package/dist/app.d.ts CHANGED
@@ -1,22 +1,44 @@
1
1
  import { Command } from 'commander';
2
2
  import type { AuthService } from './services/auth.service.js';
3
+ import type { CatalogService } from './services/catalog.service.js';
3
4
  import type { DeviceService } from './services/device.service.js';
5
+ import type { LibraryService } from './services/library.service.js';
4
6
  import type { PlayerService } from './services/player.service.js';
7
+ import type { PlaylistService } from './services/playlist.service.js';
5
8
  import type { QueueService } from './services/queue.service.js';
9
+ import type { RecentService } from './services/recent.service.js';
6
10
  import type { SearchService } from './services/search.service.js';
11
+ import { type UpdateService } from './services/update.service.js';
7
12
  import { type ConfigStore } from './storage/config.js';
8
13
  import { type Output } from './ui/output.js';
9
- import { selectTrack } from './ui/prompts.js';
14
+ import { confirmUpdate, promptSpotifyClientId, selectAlbum, selectAlbumAction, selectArtist, selectArtistAction, selectPlaylist, selectPlaylistAction, selectTrack } from './ui/prompts.js';
15
+ import { type ProgressRunner } from './ui/progress.js';
16
+ import { type InteractiveSearchResult } from './ui/interactive-search.js';
10
17
  import { type PlaybackWatcher } from './ui/watch.js';
11
18
  export interface AppDependencies {
12
19
  auth: AuthService;
20
+ catalog: CatalogService;
13
21
  player: PlayerService;
14
22
  search: SearchService;
23
+ playlist: PlaylistService;
24
+ library: LibraryService;
25
+ recent: RecentService;
15
26
  device: DeviceService;
16
27
  queue: QueueService;
28
+ update: UpdateService;
17
29
  config: ConfigStore;
18
30
  output: Output;
19
31
  chooseTrack?: typeof selectTrack;
32
+ chooseAlbum?: typeof selectAlbum;
33
+ chooseArtist?: typeof selectArtist;
34
+ choosePlaylist?: typeof selectPlaylist;
35
+ chooseAlbumAction?: typeof selectAlbumAction;
36
+ chooseArtistAction?: typeof selectArtistAction;
37
+ choosePlaylistAction?: typeof selectPlaylistAction;
38
+ requestSpotifyClientId?: typeof promptSpotifyClientId;
39
+ confirmUpdate?: typeof confirmUpdate;
40
+ interactiveSearch?: () => Promise<InteractiveSearchResult>;
41
+ progress?: ProgressRunner;
20
42
  watchPlayback?: PlaybackWatcher;
21
43
  }
22
44
  export declare function createProgram(dependencies: AppDependencies): Command;