@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
@@ -0,0 +1,36 @@
1
+ import type { PlayerService } from '../services/player.service.js';
2
+ import type { SearchService } from '../services/search.service.js';
3
+ import { type OutputStyles } from './output.js';
4
+ export type SearchCategory = 'track' | 'album' | 'artist' | 'playlist';
5
+ export type InteractiveSearchKey = {
6
+ type: 'character';
7
+ value: string;
8
+ } | {
9
+ type: 'backspace' | 'enter' | 'escape' | 'up' | 'down' | 'left' | 'right' | 'tab' | 'other';
10
+ };
11
+ export interface InteractiveSearchTerminal {
12
+ readonly isTTY: boolean;
13
+ setup(): void;
14
+ cleanup(): void;
15
+ readKey(signal?: AbortSignal): Promise<InteractiveSearchKey>;
16
+ write(value: string): void;
17
+ }
18
+ export interface InteractiveSearchServices {
19
+ search: Pick<SearchService, 'searchTracks' | 'searchAlbums' | 'searchArtists' | 'searchPlaylists'>;
20
+ player: Pick<PlayerService, 'playTrack' | 'playContext'>;
21
+ }
22
+ export interface InteractiveSearchOptions extends InteractiveSearchServices {
23
+ terminal?: InteractiveSearchTerminal;
24
+ limit?: number;
25
+ styles?: OutputStyles;
26
+ }
27
+ export type InteractiveSearchResult = {
28
+ status: 'not-interactive' | 'cancelled';
29
+ } | {
30
+ status: 'played';
31
+ category: SearchCategory;
32
+ uri: string;
33
+ label: string;
34
+ };
35
+ export declare function runInteractiveSearch(options: InteractiveSearchOptions): Promise<InteractiveSearchResult>;
36
+ export declare function createNodeInteractiveSearchTerminal(): InteractiveSearchTerminal;
@@ -0,0 +1,337 @@
1
+ import { emitKeypressEvents } from 'node:readline';
2
+ import { stdin, stdout } from 'node:process';
3
+ import { toError } from '../utils/errors.js';
4
+ import { formatAlbum, formatArtist, formatPlaylist, formatTrack, plainOutputStyles, sanitizeOneLineText, } from './output.js';
5
+ const CATEGORIES = ['track', 'album', 'artist', 'playlist'];
6
+ const CATEGORY_LABELS = {
7
+ track: 'Tracks',
8
+ album: 'Albums',
9
+ artist: 'Artists',
10
+ playlist: 'Playlists',
11
+ };
12
+ const CLEAR_SCREEN = '\u001B[2J\u001B[H';
13
+ export async function runInteractiveSearch(options) {
14
+ const terminal = options.terminal ?? createNodeInteractiveSearchTerminal();
15
+ if (!terminal.isTTY)
16
+ return { status: 'not-interactive' };
17
+ const styles = options.styles ?? plainOutputStyles;
18
+ const cache = new Map();
19
+ let query = '';
20
+ let category = 'track';
21
+ let items = null;
22
+ let selectedIndex = 0;
23
+ let submitted = false;
24
+ let errorMessage = null;
25
+ const finish = (result) => {
26
+ terminal.cleanup();
27
+ return result;
28
+ };
29
+ try {
30
+ terminal.setup();
31
+ render(terminal, { query, category, items, selectedIndex, submitted, errorMessage, styles });
32
+ while (true) {
33
+ const key = await terminal.readKey();
34
+ if (key.type === 'escape')
35
+ return finish({ status: 'cancelled' });
36
+ if (key.type === 'character') {
37
+ query += key.value;
38
+ items = null;
39
+ selectedIndex = 0;
40
+ submitted = false;
41
+ errorMessage = null;
42
+ cache.clear();
43
+ }
44
+ else if (key.type === 'backspace') {
45
+ query = removeLastCharacter(query);
46
+ items = null;
47
+ selectedIndex = 0;
48
+ submitted = false;
49
+ errorMessage = null;
50
+ cache.clear();
51
+ }
52
+ else if (isCategoryKey(key)) {
53
+ category = moveCategory(category, key.type === 'left' ? -1 : 1);
54
+ selectedIndex = 0;
55
+ errorMessage = null;
56
+ if (submitted && query.trim()) {
57
+ const result = await loadResults(terminal, options, cache, query, category);
58
+ if (result.status === 'cancelled')
59
+ return finish({ status: 'cancelled' });
60
+ items = result.items;
61
+ errorMessage = result.errorMessage;
62
+ }
63
+ else {
64
+ items = null;
65
+ }
66
+ }
67
+ else if (key.type === 'enter' && items === null && query.trim()) {
68
+ submitted = true;
69
+ const result = await loadResults(terminal, options, cache, query, category);
70
+ if (result.status === 'cancelled')
71
+ return finish({ status: 'cancelled' });
72
+ items = result.items;
73
+ errorMessage = result.errorMessage;
74
+ selectedIndex = 0;
75
+ }
76
+ else if (key.type === 'up' && items && items.length > 0) {
77
+ selectedIndex = (selectedIndex - 1 + items.length) % items.length;
78
+ errorMessage = null;
79
+ }
80
+ else if (key.type === 'down' && items && items.length > 0) {
81
+ selectedIndex = (selectedIndex + 1) % items.length;
82
+ errorMessage = null;
83
+ }
84
+ else if (key.type === 'enter' && items && items.length > 0) {
85
+ const selected = items[selectedIndex];
86
+ if (!selected)
87
+ continue;
88
+ renderStartingPlayback(terminal, selected, category, styles);
89
+ const playback = await runCancellableOperation(terminal, (signal) => category === 'track'
90
+ ? options.player.playTrack(selected.uri, signal)
91
+ : options.player.playContext(selected.uri, signal));
92
+ if (playback.status === 'cancelled')
93
+ return finish({ status: 'cancelled' });
94
+ if (playback.status === 'failed') {
95
+ errorMessage = sanitizeOneLineText(toError(playback.error).message) || 'Playback failed.';
96
+ }
97
+ else {
98
+ return finish({
99
+ status: 'played',
100
+ category,
101
+ uri: selected.uri,
102
+ label: playbackLabel(selected, category),
103
+ });
104
+ }
105
+ }
106
+ render(terminal, { query, category, items, selectedIndex, submitted, errorMessage, styles });
107
+ }
108
+ }
109
+ catch (error) {
110
+ try {
111
+ terminal.cleanup();
112
+ }
113
+ catch {
114
+ // Preserve the original setup, rendering, search, or playback error.
115
+ }
116
+ throw error;
117
+ }
118
+ }
119
+ export function createNodeInteractiveSearchTerminal() {
120
+ let wasRaw = false;
121
+ let rawModeChanged = false;
122
+ let inputResumed = false;
123
+ let screenOpened = false;
124
+ let cleanedUp = true;
125
+ return {
126
+ isTTY: Boolean(stdin.isTTY && stdout.isTTY),
127
+ setup() {
128
+ if (!cleanedUp)
129
+ return;
130
+ cleanedUp = false;
131
+ wasRaw = Boolean(stdin.isRaw);
132
+ emitKeypressEvents(stdin);
133
+ stdin.setRawMode(true);
134
+ rawModeChanged = true;
135
+ stdin.resume();
136
+ inputResumed = true;
137
+ screenOpened = true;
138
+ stdout.write('\u001B[?1049h\u001B[?25l');
139
+ },
140
+ cleanup() {
141
+ if (cleanedUp)
142
+ return;
143
+ cleanedUp = true;
144
+ let firstError;
145
+ if (rawModeChanged && stdin.isTTY) {
146
+ try {
147
+ stdin.setRawMode(wasRaw);
148
+ }
149
+ catch (error) {
150
+ firstError = error;
151
+ }
152
+ }
153
+ rawModeChanged = false;
154
+ if (inputResumed) {
155
+ try {
156
+ stdin.pause();
157
+ }
158
+ catch (error) {
159
+ firstError ??= error;
160
+ }
161
+ }
162
+ inputResumed = false;
163
+ if (screenOpened) {
164
+ try {
165
+ stdout.write('\u001B[?25h\u001B[?1049l');
166
+ }
167
+ catch (error) {
168
+ firstError ??= error;
169
+ }
170
+ }
171
+ screenOpened = false;
172
+ if (firstError !== undefined)
173
+ throw firstError;
174
+ },
175
+ readKey(signal) {
176
+ return new Promise((resolve) => {
177
+ let settled = false;
178
+ const finish = (key) => {
179
+ if (settled)
180
+ return;
181
+ settled = true;
182
+ stdin.removeListener('keypress', listener);
183
+ signal?.removeEventListener('abort', abortListener);
184
+ resolve(key);
185
+ };
186
+ const listener = (character, key = {}) => {
187
+ finish(mapNodeKey(character, key));
188
+ };
189
+ const abortListener = () => finish({ type: 'other' });
190
+ if (signal?.aborted) {
191
+ abortListener();
192
+ return;
193
+ }
194
+ stdin.once('keypress', listener);
195
+ signal?.addEventListener('abort', abortListener, { once: true });
196
+ });
197
+ },
198
+ write(value) {
199
+ stdout.write(value);
200
+ },
201
+ };
202
+ }
203
+ function render(terminal, state) {
204
+ const categoryBar = CATEGORIES.map((entry) => entry === state.category
205
+ ? state.styles.heading(`[${CATEGORY_LABELS[entry]}]`)
206
+ : CATEGORY_LABELS[entry]).join(' ');
207
+ const lines = [
208
+ state.styles.heading('Spotify search'),
209
+ '',
210
+ categoryBar,
211
+ '',
212
+ `Search: ${sanitizeOneLineText(state.query)}${state.items === null ? '▌' : ''}`,
213
+ '',
214
+ ];
215
+ if (state.errorMessage) {
216
+ lines.push(`Error: ${state.errorMessage}`, '');
217
+ }
218
+ if (state.items === null) {
219
+ lines.push(state.submitted
220
+ ? 'Press Enter to retry. Type to edit the query; Tab changes category; Esc exits.'
221
+ : 'Type a query and press Enter. Tab changes category; Esc exits.');
222
+ }
223
+ else if (state.items.length === 0) {
224
+ lines.push(`No ${CATEGORY_LABELS[state.category].toLowerCase()} found for "${sanitizeOneLineText(state.query.trim())}".`);
225
+ lines.push('', 'Type to edit the query; Tab changes category; Esc exits.');
226
+ }
227
+ else {
228
+ lines.push(...state.items.map((item, index) => `${index === state.selectedIndex ? '›' : ' '} ${formatItem(item, state.category, state.styles)}`), '', '↑/↓ selects; Enter plays; type to edit; Tab changes category; Esc exits.');
229
+ }
230
+ terminal.write(`${CLEAR_SCREEN}${lines.join('\n')}\n`);
231
+ }
232
+ async function loadResults(terminal, options, cache, query, category) {
233
+ const key = `${category}:${query.trim().toLocaleLowerCase()}`;
234
+ const cached = cache.get(key);
235
+ if (cached)
236
+ return { status: 'loaded', items: cached, errorMessage: null };
237
+ renderSearching(terminal, query, category, options.styles ?? plainOutputStyles);
238
+ const result = await runCancellableOperation(terminal, (signal) => search(options.search, category, query, options.limit, signal));
239
+ if (result.status === 'cancelled')
240
+ return result;
241
+ if (result.status === 'failed') {
242
+ return {
243
+ status: 'loaded',
244
+ items: null,
245
+ errorMessage: sanitizeOneLineText(toError(result.error).message) || 'Search failed.',
246
+ };
247
+ }
248
+ cache.set(key, result.value);
249
+ return { status: 'loaded', items: result.value, errorMessage: null };
250
+ }
251
+ function renderSearching(terminal, query, category, styles) {
252
+ terminal.write(`${CLEAR_SCREEN}${styles.heading(`Searching ${CATEGORY_LABELS[category].toLowerCase()}`)} for "${sanitizeOneLineText(query.trim())}"…\n\nEsc cancels and exits.\n`);
253
+ }
254
+ function renderStartingPlayback(terminal, item, category, styles) {
255
+ terminal.write(`${CLEAR_SCREEN}${styles.heading('Starting playback')}\n\n${formatItem(item, category, styles)}\n`);
256
+ }
257
+ async function search(service, category, query, limit, signal) {
258
+ if (category === 'track')
259
+ return service.searchTracks(query, limit, signal);
260
+ if (category === 'album')
261
+ return service.searchAlbums(query, limit, signal);
262
+ if (category === 'artist')
263
+ return service.searchArtists(query, limit, signal);
264
+ return service.searchPlaylists(query, limit, signal);
265
+ }
266
+ async function runCancellableOperation(terminal, operation) {
267
+ const operationController = new AbortController();
268
+ const operationResult = operation(operationController.signal).then((value) => ({ status: 'completed', value }), (error) => ({ status: 'failed', error }));
269
+ while (true) {
270
+ const keyController = new AbortController();
271
+ const keyResult = terminal.readKey(keyController.signal).then((key) => ({
272
+ status: 'key',
273
+ key,
274
+ }));
275
+ const result = await Promise.race([operationResult, keyResult]);
276
+ if (result.status !== 'key') {
277
+ keyController.abort();
278
+ return result;
279
+ }
280
+ if (result.key.type === 'escape') {
281
+ operationController.abort();
282
+ return { status: 'cancelled' };
283
+ }
284
+ }
285
+ }
286
+ function formatItem(item, category, styles) {
287
+ if (category === 'track')
288
+ return formatTrack(item, undefined, styles);
289
+ if (category === 'album')
290
+ return formatAlbum(item, undefined, styles);
291
+ if (category === 'artist')
292
+ return formatArtist(item, undefined, styles);
293
+ return formatPlaylist(item, undefined, styles);
294
+ }
295
+ function playbackLabel(item, category) {
296
+ if (category === 'track') {
297
+ const track = item;
298
+ return `${sanitizeOneLineText(track.name)} — ${track.artists.map(sanitizeOneLineText).join(', ')}`;
299
+ }
300
+ return sanitizeOneLineText(item.name);
301
+ }
302
+ function removeLastCharacter(value) {
303
+ return Array.from(value).slice(0, -1).join('');
304
+ }
305
+ function isCategoryKey(key) {
306
+ return key.type === 'tab' || key.type === 'left' || key.type === 'right';
307
+ }
308
+ function moveCategory(category, offset) {
309
+ const currentIndex = CATEGORIES.indexOf(category);
310
+ return CATEGORIES[(currentIndex + offset + CATEGORIES.length) % CATEGORIES.length] ?? 'track';
311
+ }
312
+ function mapNodeKey(character, key) {
313
+ if (key.name === 'escape' || (key.ctrl && key.name === 'c'))
314
+ return { type: 'escape' };
315
+ if (key.name === 'return' || key.name === 'enter')
316
+ return { type: 'enter' };
317
+ if (key.name === 'backspace')
318
+ return { type: 'backspace' };
319
+ if (key.name === 'up')
320
+ return { type: 'up' };
321
+ if (key.name === 'down')
322
+ return { type: 'down' };
323
+ if (key.name === 'left')
324
+ return { type: 'left' };
325
+ if (key.name === 'right')
326
+ return { type: 'right' };
327
+ if (key.name === 'tab')
328
+ return { type: 'tab' };
329
+ if (!key.ctrl && !key.meta && character && isPrintable(character)) {
330
+ return { type: 'character', value: character };
331
+ }
332
+ return { type: 'other' };
333
+ }
334
+ function isPrintable(value) {
335
+ return Array.from(value).every((character) => character >= ' ' && character !== '\u007F');
336
+ }
337
+ //# sourceMappingURL=interactive-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive-search.js","sourceRoot":"","sources":["../../src/ui/interactive-search.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,33 @@
1
1
  import type { Album, AlbumDetail, Artist, CurrentPlayback, Playlist, PlaylistDetail, RecentlyPlayedTrack, SavedTrack, Track } from '../services/models.js';
2
+ export { sanitizeOneLineText } from '../utils/text.js';
2
3
  export interface Output {
3
4
  log(message: string): void;
4
5
  error(message: string): void;
5
6
  }
6
7
  export declare const consoleOutput: Output;
7
- export declare function formatPlayback(playback: CurrentPlayback): string;
8
- export declare function formatTrack(track: Track, index?: number): string;
9
- export declare function formatAlbum(album: Album, index?: number): string;
10
- export declare function formatAlbumDetail(album: AlbumDetail): string;
11
- export declare function formatArtist(artist: Artist, index?: number): string;
12
- export declare function formatArtistDetail(artist: Artist): string;
13
- export declare function formatPlaylist(playlist: Playlist, index?: number): string;
14
- export declare function formatPlaylistOverview(playlist: Playlist): string;
15
- export declare function formatPlaylistDetail(playlist: PlaylistDetail): string;
16
- export declare function formatSavedTrack(item: SavedTrack, index?: number): string;
17
- export declare function formatRecentlyPlayed(item: RecentlyPlayedTrack, index?: number): string;
8
+ type OutputStyle = (value: string) => string;
9
+ export interface OutputStyles {
10
+ name: OutputStyle;
11
+ heading: OutputStyle;
12
+ metadata: OutputStyle;
13
+ progress: OutputStyle;
14
+ }
15
+ export declare const plainOutputStyles: OutputStyles;
16
+ export declare const plainStyles: OutputStyles;
17
+ interface OutputStyleOptions {
18
+ isTTY?: boolean | undefined;
19
+ env?: NodeJS.ProcessEnv | undefined;
20
+ }
21
+ export declare function createOutputStyles(isTTY?: boolean, env?: NodeJS.ProcessEnv): OutputStyles;
22
+ export declare function createOutputStyles(options?: OutputStyleOptions): OutputStyles;
23
+ export declare function formatPlayback(playback: CurrentPlayback, styles?: OutputStyles): string;
24
+ export declare function formatTrack(track: Track, index?: number, styles?: OutputStyles): string;
25
+ export declare function formatAlbum(album: Album, index?: number, styles?: OutputStyles): string;
26
+ export declare function formatAlbumDetail(album: AlbumDetail, styles?: OutputStyles): string;
27
+ export declare function formatArtist(artist: Artist, index?: number, styles?: OutputStyles): string;
28
+ export declare function formatArtistDetail(artist: Artist, styles?: OutputStyles): string;
29
+ export declare function formatPlaylist(playlist: Playlist, index?: number, styles?: OutputStyles): string;
30
+ export declare function formatPlaylistOverview(playlist: Playlist, styles?: OutputStyles): string;
31
+ export declare function formatPlaylistDetail(playlist: PlaylistDetail, styles?: OutputStyles): string;
32
+ export declare function formatSavedTrack(item: SavedTrack, index?: number, styles?: OutputStyles): string;
33
+ export declare function formatRecentlyPlayed(item: RecentlyPlayedTrack, index?: number, styles?: OutputStyles): string;
package/dist/ui/output.js CHANGED
@@ -1,81 +1,123 @@
1
+ import { createColors } from 'picocolors';
1
2
  import { createProgressBar, formatDuration } from '../utils/time.js';
3
+ import { sanitizeOneLineText } from '../utils/text.js';
4
+ export { sanitizeOneLineText } from '../utils/text.js';
2
5
  export const consoleOutput = {
3
6
  log: (message) => console.log(message),
4
7
  error: (message) => console.error(message),
5
8
  };
6
- export function formatPlayback(playback) {
9
+ const identity = (value) => value;
10
+ export const plainOutputStyles = Object.freeze({
11
+ name: identity,
12
+ heading: identity,
13
+ metadata: identity,
14
+ progress: identity,
15
+ });
16
+ export const plainStyles = plainOutputStyles;
17
+ export function createOutputStyles(isTTYOrOptions = process.stdout.isTTY, environment = process.env) {
18
+ const isOptions = typeof isTTYOrOptions === 'object';
19
+ const isTTY = isOptions
20
+ ? (isTTYOrOptions.isTTY ?? process.stdout.isTTY)
21
+ : isTTYOrOptions;
22
+ const env = isOptions ? (isTTYOrOptions.env ?? process.env) : environment;
23
+ const colors = createColors(isTTY === true && !('NO_COLOR' in env));
24
+ return {
25
+ name: colors.bold,
26
+ heading: colors.bold,
27
+ metadata: colors.dim,
28
+ progress: colors.green,
29
+ };
30
+ }
31
+ export function formatPlayback(playback, styles = plainOutputStyles) {
7
32
  const indicator = playback.isPlaying ? '▶' : '⏸';
8
- const artists = playback.track.artists.join(', ');
9
- const progress = Math.min(playback.progressMs, playback.track.durationMs);
33
+ const artists = playback.track.artists.map(sanitizeOneLineText).join(', ');
34
+ const duration = Math.max(0, playback.track.durationMs);
35
+ const progress = Math.min(Math.max(0, playback.progressMs), duration);
36
+ const progressLine = `${formatDuration(progress)} ${createProgressBar(progress, duration)} ${formatDuration(duration)}`;
10
37
  return [
11
- `${indicator} ${playback.track.name}`,
12
- `${artists} · ${playback.track.album}`,
38
+ `${indicator} ${styles.name(sanitizeOneLineText(playback.track.name))}`,
39
+ styles.metadata(`${artists} · ${sanitizeOneLineText(playback.track.album)}`),
13
40
  '',
14
- `${formatDuration(progress)} ${createProgressBar(progress, playback.track.durationMs)} ${formatDuration(playback.track.durationMs)}`,
41
+ styles.progress(progressLine),
15
42
  ].join('\n');
16
43
  }
17
- export function formatTrack(track, index) {
44
+ export function formatTrack(track, index, styles = plainOutputStyles) {
18
45
  const prefix = index === undefined ? '' : `${index + 1}. `;
19
- return `${prefix}${track.name} ${track.artists.join(', ')} · ${track.album}`;
46
+ const artists = track.artists.map(sanitizeOneLineText).join(', ');
47
+ return `${prefix}${styles.name(sanitizeOneLineText(track.name))} — ${styles.metadata(artists)} · ${styles.metadata(sanitizeOneLineText(track.album))}`;
20
48
  }
21
- export function formatAlbum(album, index) {
49
+ export function formatAlbum(album, index, styles = plainOutputStyles) {
22
50
  const prefix = index === undefined ? '' : `${index + 1}. `;
23
- const release = album.releaseDate ? ` · ${album.releaseDate}` : '';
24
- return `${prefix}${album.name} ${album.artists.join(', ')} · ${album.totalTracks} tracks${release}`;
51
+ const release = album.releaseDate
52
+ ? ` · ${styles.metadata(sanitizeOneLineText(album.releaseDate))}`
53
+ : '';
54
+ const artists = album.artists.map(sanitizeOneLineText).join(', ');
55
+ return `${prefix}${styles.name(sanitizeOneLineText(album.name))} — ${styles.metadata(artists)} · ${styles.metadata(`${album.totalTracks} tracks`)}${release}`;
25
56
  }
26
- export function formatAlbumDetail(album) {
27
- const lines = [formatAlbum(album), '', 'Tracks:'];
57
+ export function formatAlbumDetail(album, styles = plainOutputStyles) {
58
+ const lines = [formatAlbum(album, undefined, styles), '', styles.heading('Tracks:')];
28
59
  if (album.tracks.length === 0)
29
60
  lines.push('No playable tracks found.');
30
- else
31
- lines.push(...album.tracks.map((track, index) => formatTrack(track, index)));
61
+ else {
62
+ lines.push(...album.tracks.map((track, index) => formatTrack(track, index, styles)));
63
+ }
32
64
  if (album.tracks.length < album.totalTracks) {
33
- lines.push(`Showing ${album.tracks.length} of ${album.totalTracks} tracks.`);
65
+ lines.push(styles.metadata(`Showing ${album.tracks.length} of ${album.totalTracks} tracks.`));
66
+ }
67
+ if (album.externalUrl) {
68
+ lines.push('', styles.metadata(`Spotify: ${sanitizeOneLineText(album.externalUrl)}`));
34
69
  }
35
- if (album.externalUrl)
36
- lines.push('', `Spotify: ${album.externalUrl}`);
37
70
  return lines.join('\n');
38
71
  }
39
- export function formatArtist(artist, index) {
72
+ export function formatArtist(artist, index, styles = plainOutputStyles) {
40
73
  const prefix = index === undefined ? '' : `${index + 1}. `;
41
- return `${prefix}${artist.name}`;
74
+ return `${prefix}${styles.name(sanitizeOneLineText(artist.name))}`;
42
75
  }
43
- export function formatArtistDetail(artist) {
44
- const lines = [formatArtist(artist)];
45
- if (artist.externalUrl)
46
- lines.push(`Spotify: ${artist.externalUrl}`);
76
+ export function formatArtistDetail(artist, styles = plainOutputStyles) {
77
+ const lines = [formatArtist(artist, undefined, styles)];
78
+ if (artist.externalUrl) {
79
+ lines.push(styles.metadata(`Spotify: ${sanitizeOneLineText(artist.externalUrl)}`));
80
+ }
47
81
  return lines.join('\n');
48
82
  }
49
- export function formatPlaylist(playlist, index) {
83
+ export function formatPlaylist(playlist, index, styles = plainOutputStyles) {
50
84
  const prefix = index === undefined ? '' : `${index + 1}. `;
51
85
  const itemLabel = playlist.totalTracks === 1 ? 'item' : 'items';
52
- return `${prefix}${playlist.name} ${playlist.ownerName} · ${playlist.totalTracks} ${itemLabel}`;
86
+ const metadata = `${sanitizeOneLineText(playlist.ownerName)} · ${playlist.totalTracks} ${itemLabel}`;
87
+ return `${prefix}${styles.name(sanitizeOneLineText(playlist.name))} — ${styles.metadata(metadata)}`;
53
88
  }
54
- export function formatPlaylistOverview(playlist) {
55
- const lines = [formatPlaylist(playlist)];
56
- if (playlist.description)
57
- lines.push(playlist.description);
58
- if (playlist.externalUrl)
59
- lines.push(`Spotify: ${playlist.externalUrl}`);
89
+ export function formatPlaylistOverview(playlist, styles = plainOutputStyles) {
90
+ const lines = [formatPlaylist(playlist, undefined, styles)];
91
+ if (playlist.description) {
92
+ lines.push(styles.metadata(sanitizeOneLineText(playlist.description)));
93
+ }
94
+ if (playlist.externalUrl) {
95
+ lines.push(styles.metadata(`Spotify: ${sanitizeOneLineText(playlist.externalUrl)}`));
96
+ }
60
97
  return lines.join('\n');
61
98
  }
62
- export function formatPlaylistDetail(playlist) {
63
- const lines = [formatPlaylist(playlist)];
64
- if (playlist.description)
65
- lines.push(playlist.description);
66
- lines.push('', 'Tracks:');
99
+ export function formatPlaylistDetail(playlist, styles = plainOutputStyles) {
100
+ const lines = [formatPlaylist(playlist, undefined, styles)];
101
+ if (playlist.description) {
102
+ lines.push(styles.metadata(sanitizeOneLineText(playlist.description)));
103
+ }
104
+ lines.push('', styles.heading('Tracks:'));
67
105
  if (playlist.tracks.length === 0)
68
106
  lines.push('No playable tracks found.');
69
- else
70
- lines.push(...playlist.tracks.map((track, index) => formatTrack(track, index)));
71
- if (playlist.externalUrl)
72
- lines.push('', `Spotify: ${playlist.externalUrl}`);
107
+ else {
108
+ lines.push(...playlist.tracks.map((track, index) => formatTrack(track, index, styles)));
109
+ }
110
+ if (playlist.externalUrl) {
111
+ lines.push('', styles.metadata(`Spotify: ${sanitizeOneLineText(playlist.externalUrl)}`));
112
+ }
73
113
  return lines.join('\n');
74
114
  }
75
- export function formatSavedTrack(item, index) {
76
- return `${formatTrack(item.track, index)} · liked ${item.addedAt}`;
115
+ export function formatSavedTrack(item, index, styles = plainOutputStyles) {
116
+ const playedMetadata = styles.metadata(`liked ${sanitizeOneLineText(item.addedAt)}`);
117
+ return `${formatTrack(item.track, index, styles)} · ${playedMetadata}`;
77
118
  }
78
- export function formatRecentlyPlayed(item, index) {
79
- return `${formatTrack(item.track, index)} · played ${item.playedAt}`;
119
+ export function formatRecentlyPlayed(item, index, styles = plainOutputStyles) {
120
+ const playedMetadata = styles.metadata(`played ${sanitizeOneLineText(item.playedAt)}`);
121
+ return `${formatTrack(item.track, index, styles)} · ${playedMetadata}`;
80
122
  }
81
123
  //# sourceMappingURL=output.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/ui/output.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/ui/output.ts"],"names":[],"mappings":"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"}