@lucaperret/tidal-cli 1.1.0 → 1.2.2
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.
- package/README.md +13 -1
- package/dist/album.d.ts +4 -0
- package/dist/album.js +69 -50
- package/dist/artist.d.ts +7 -0
- package/dist/artist.js +139 -91
- package/dist/history.d.ts +3 -2
- package/dist/history.js +27 -17
- package/dist/index.js +96 -1
- package/dist/library.d.ts +25 -2
- package/dist/library.js +97 -48
- package/dist/mix.d.ts +4 -0
- package/dist/mix.js +59 -0
- package/dist/playback.d.ts +4 -0
- package/dist/playback.js +62 -46
- package/dist/playlist.d.ts +43 -0
- package/dist/playlist.js +183 -104
- package/dist/recommend.d.ts +4 -1
- package/dist/recommend.js +71 -19
- package/dist/saved.d.ts +16 -0
- package/dist/saved.js +107 -0
- package/dist/search-history.d.ts +13 -0
- package/dist/search-history.js +94 -0
- package/dist/search.d.ts +4 -2
- package/dist/search.js +66 -45
- package/dist/session.js +17 -7
- package/dist/share.d.ts +5 -0
- package/dist/share.js +53 -0
- package/dist/track.d.ts +14 -0
- package/dist/track.js +128 -91
- package/dist/types.d.ts +158 -0
- package/dist/types.js +4 -0
- package/dist/user.d.ts +3 -0
- package/dist/user.js +27 -18
- package/package.json +12 -6
package/dist/saved.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listSavedItemsData = listSavedItemsData;
|
|
4
|
+
exports.listSavedItems = listSavedItems;
|
|
5
|
+
exports.addSavedItemData = addSavedItemData;
|
|
6
|
+
exports.addSavedItem = addSavedItem;
|
|
7
|
+
exports.removeSavedItemData = removeSavedItemData;
|
|
8
|
+
exports.removeSavedItem = removeSavedItem;
|
|
9
|
+
const auth_1 = require("./auth");
|
|
10
|
+
async function listSavedItemsData(client) {
|
|
11
|
+
const { data, error } = await client.GET('/userCollectionSaveForLaters/{id}/relationships/items', {
|
|
12
|
+
params: {
|
|
13
|
+
path: { id: 'me' },
|
|
14
|
+
query: { include: ['items'] },
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
if (error || !data) {
|
|
18
|
+
throw new Error(`Failed to list saved items — ${JSON.stringify(error)}`);
|
|
19
|
+
}
|
|
20
|
+
const included = data.included ?? [];
|
|
21
|
+
return included.map((item) => {
|
|
22
|
+
const attrs = item.attributes ?? {};
|
|
23
|
+
return {
|
|
24
|
+
id: item.id,
|
|
25
|
+
type: item.type,
|
|
26
|
+
name: attrs.title ?? attrs.name ?? 'Untitled',
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async function listSavedItems(json) {
|
|
31
|
+
const client = await (0, auth_1.getApiClient)();
|
|
32
|
+
try {
|
|
33
|
+
const items = await listSavedItemsData(client);
|
|
34
|
+
if (json) {
|
|
35
|
+
console.log(JSON.stringify(items, null, 2));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (items.length === 0) {
|
|
39
|
+
console.log('No saved items found.');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
console.log('\nSaved for later:\n');
|
|
43
|
+
for (const item of items) {
|
|
44
|
+
console.log(` [${item.id}] (${item.type}) ${item.name}`);
|
|
45
|
+
}
|
|
46
|
+
console.log();
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
console.error(`Error: ${err.message}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function addSavedItemData(itemType, itemId, client) {
|
|
54
|
+
const { error } = await client.POST('/userCollectionSaveForLaters/{id}/relationships/items', {
|
|
55
|
+
params: { path: { id: 'me' } },
|
|
56
|
+
body: {
|
|
57
|
+
data: [{ id: itemId, type: itemType }],
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
if (error) {
|
|
61
|
+
throw new Error(`Failed to save item — ${JSON.stringify(error)}`);
|
|
62
|
+
}
|
|
63
|
+
return { id: itemId, type: itemType, added: true };
|
|
64
|
+
}
|
|
65
|
+
async function addSavedItem(itemType, itemId, json) {
|
|
66
|
+
const client = await (0, auth_1.getApiClient)();
|
|
67
|
+
try {
|
|
68
|
+
const result = await addSavedItemData(itemType, itemId, client);
|
|
69
|
+
if (json) {
|
|
70
|
+
console.log(JSON.stringify(result, null, 2));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
console.log(`\n${itemType} ${itemId} saved for later.`);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
console.error(`Error: ${err.message}`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function removeSavedItemData(itemType, itemId, client) {
|
|
81
|
+
const { error } = await client.DELETE('/userCollectionSaveForLaters/{id}/relationships/items', {
|
|
82
|
+
params: { path: { id: 'me' } },
|
|
83
|
+
body: {
|
|
84
|
+
data: [{ id: itemId, type: itemType }],
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
if (error) {
|
|
88
|
+
throw new Error(`Failed to remove saved item — ${JSON.stringify(error)}`);
|
|
89
|
+
}
|
|
90
|
+
return { id: itemId, type: itemType, removed: true };
|
|
91
|
+
}
|
|
92
|
+
async function removeSavedItem(itemType, itemId, json) {
|
|
93
|
+
const client = await (0, auth_1.getApiClient)();
|
|
94
|
+
try {
|
|
95
|
+
const result = await removeSavedItemData(itemType, itemId, client);
|
|
96
|
+
if (json) {
|
|
97
|
+
console.log(JSON.stringify(result, null, 2));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
console.log(`\n${itemType} ${itemId} removed from saved.`);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
console.error(`Error: ${err.message}`);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=saved.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SearchHistoryEntry } from './types';
|
|
2
|
+
export type { SearchHistoryEntry };
|
|
3
|
+
export declare function listSearchHistoryData(client: any, countryCode: string): Promise<SearchHistoryEntry[]>;
|
|
4
|
+
export declare function listSearchHistory(json: boolean): Promise<void>;
|
|
5
|
+
export declare function deleteSearchHistoryEntryData(entryId: string, client: any): Promise<{
|
|
6
|
+
id: string;
|
|
7
|
+
deleted: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
export declare function deleteSearchHistoryEntry(entryId: string, json: boolean): Promise<void>;
|
|
10
|
+
export declare function clearSearchHistoryData(client: any, countryCode: string): Promise<{
|
|
11
|
+
deleted: number;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function clearSearchHistory(json: boolean): Promise<void>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listSearchHistoryData = listSearchHistoryData;
|
|
4
|
+
exports.listSearchHistory = listSearchHistory;
|
|
5
|
+
exports.deleteSearchHistoryEntryData = deleteSearchHistoryEntryData;
|
|
6
|
+
exports.deleteSearchHistoryEntry = deleteSearchHistoryEntry;
|
|
7
|
+
exports.clearSearchHistoryData = clearSearchHistoryData;
|
|
8
|
+
exports.clearSearchHistory = clearSearchHistory;
|
|
9
|
+
const auth_1 = require("./auth");
|
|
10
|
+
async function listSearchHistoryData(client, countryCode) {
|
|
11
|
+
const { data, error } = await client.GET('/searchHistoryEntries', {
|
|
12
|
+
params: {
|
|
13
|
+
query: { countryCode },
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
if (error || !data) {
|
|
17
|
+
throw new Error(`Failed to list search history — ${JSON.stringify(error)}`);
|
|
18
|
+
}
|
|
19
|
+
const items = data.data ?? [];
|
|
20
|
+
return items.map((item) => ({
|
|
21
|
+
id: item.id,
|
|
22
|
+
query: item.attributes?.query ?? '',
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
async function listSearchHistory(json) {
|
|
26
|
+
const client = await (0, auth_1.getApiClient)();
|
|
27
|
+
const countryCode = await (0, auth_1.getCountryCode)();
|
|
28
|
+
try {
|
|
29
|
+
const entries = await listSearchHistoryData(client, countryCode);
|
|
30
|
+
if (json) {
|
|
31
|
+
console.log(JSON.stringify(entries, null, 2));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (entries.length === 0) {
|
|
35
|
+
console.log('No search history found.');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
console.log('\nYour search history:\n');
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
console.log(` [${entry.id}] ${entry.query}`);
|
|
41
|
+
}
|
|
42
|
+
console.log();
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.error(`Error: ${err.message}`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function deleteSearchHistoryEntryData(entryId, client) {
|
|
50
|
+
const { error } = await client.DELETE('/searchHistoryEntries/{id}', {
|
|
51
|
+
params: { path: { id: entryId } },
|
|
52
|
+
});
|
|
53
|
+
if (error) {
|
|
54
|
+
throw new Error(`Failed to delete search history entry — ${JSON.stringify(error)}`);
|
|
55
|
+
}
|
|
56
|
+
return { id: entryId, deleted: true };
|
|
57
|
+
}
|
|
58
|
+
async function deleteSearchHistoryEntry(entryId, json) {
|
|
59
|
+
const client = await (0, auth_1.getApiClient)();
|
|
60
|
+
try {
|
|
61
|
+
const result = await deleteSearchHistoryEntryData(entryId, client);
|
|
62
|
+
if (json) {
|
|
63
|
+
console.log(JSON.stringify(result, null, 2));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
console.log(`\nSearch history entry ${entryId} deleted.`);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
console.error(`Error: ${err.message}`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function clearSearchHistoryData(client, countryCode) {
|
|
74
|
+
const entries = await listSearchHistoryData(client, countryCode);
|
|
75
|
+
await Promise.all(entries.map((e) => deleteSearchHistoryEntryData(e.id, client)));
|
|
76
|
+
return { deleted: entries.length };
|
|
77
|
+
}
|
|
78
|
+
async function clearSearchHistory(json) {
|
|
79
|
+
const client = await (0, auth_1.getApiClient)();
|
|
80
|
+
const countryCode = await (0, auth_1.getCountryCode)();
|
|
81
|
+
try {
|
|
82
|
+
const result = await clearSearchHistoryData(client, countryCode);
|
|
83
|
+
if (json) {
|
|
84
|
+
console.log(JSON.stringify(result, null, 2));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log(`\nCleared ${result.deleted} search history entries.`);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
console.error(`Error: ${err.message}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=search-history.js.map
|
package/dist/search.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
type SearchType
|
|
1
|
+
import type { SearchType, SearchResult, SearchSuggestionsResult } from './types';
|
|
2
|
+
export type { SearchType, SearchResult, SearchSuggestionsResult };
|
|
3
|
+
export declare function searchData(type: SearchType, query: string, client: any, countryCode: string): Promise<SearchResult[]>;
|
|
2
4
|
export declare function search(type: SearchType, query: string, json: boolean): Promise<void>;
|
|
5
|
+
export declare function searchSuggestionsData(query: string, client: any, countryCode: string): Promise<SearchSuggestionsResult>;
|
|
3
6
|
export declare function searchSuggestions(query: string, json: boolean): Promise<void>;
|
|
4
|
-
export {};
|
package/dist/search.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.searchData = searchData;
|
|
3
4
|
exports.search = search;
|
|
5
|
+
exports.searchSuggestionsData = searchSuggestionsData;
|
|
4
6
|
exports.searchSuggestions = searchSuggestions;
|
|
5
7
|
const auth_1 = require("./auth");
|
|
6
8
|
function formatDuration(isoDuration) {
|
|
@@ -15,8 +17,7 @@ function formatDuration(isoDuration) {
|
|
|
15
17
|
const s = (match[3] ?? '0').padStart(2, '0');
|
|
16
18
|
return `${h}${m}:${s}`;
|
|
17
19
|
}
|
|
18
|
-
async function
|
|
19
|
-
const client = await (0, auth_1.getApiClient)();
|
|
20
|
+
async function searchData(type, query, client, countryCode) {
|
|
20
21
|
const includeMap = {
|
|
21
22
|
artist: 'artists',
|
|
22
23
|
album: 'albums',
|
|
@@ -28,14 +29,13 @@ async function search(type, query, json) {
|
|
|
28
29
|
params: {
|
|
29
30
|
path: { id: query },
|
|
30
31
|
query: {
|
|
31
|
-
countryCode
|
|
32
|
+
countryCode,
|
|
32
33
|
include: [includeMap[type]],
|
|
33
34
|
},
|
|
34
35
|
},
|
|
35
36
|
});
|
|
36
37
|
if (error || !data) {
|
|
37
|
-
|
|
38
|
-
process.exit(1);
|
|
38
|
+
throw new Error(`Search failed — ${JSON.stringify(error)}`);
|
|
39
39
|
}
|
|
40
40
|
const included = data.included ?? [];
|
|
41
41
|
const results = [];
|
|
@@ -111,41 +111,51 @@ async function search(type, query, json) {
|
|
|
111
111
|
return pb - pa;
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
return results;
|
|
115
|
+
}
|
|
116
|
+
async function search(type, query, json) {
|
|
117
|
+
const client = await (0, auth_1.getApiClient)();
|
|
118
|
+
const countryCode = await (0, auth_1.getCountryCode)();
|
|
119
|
+
try {
|
|
120
|
+
const results = await searchData(type, query, client, countryCode);
|
|
121
|
+
if (json) {
|
|
122
|
+
console.log(JSON.stringify(results, null, 2));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (results.length === 0) {
|
|
126
|
+
console.log(`No ${type}s found for "${query}".`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const typeLabel = type === 'playlist' ? 'playlists' : `${type}s`;
|
|
130
|
+
console.log(`\nSearch results for "${query}" (${typeLabel}):\n`);
|
|
131
|
+
for (const r of results) {
|
|
132
|
+
const extras = r.extra
|
|
133
|
+
? Object.entries(r.extra)
|
|
134
|
+
.filter(([, v]) => v !== undefined && v !== null)
|
|
135
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
136
|
+
.join(', ')
|
|
137
|
+
: '';
|
|
138
|
+
console.log(` [${r.id}] ${r.name}${extras ? ` (${extras})` : ''}`);
|
|
139
|
+
}
|
|
140
|
+
console.log();
|
|
121
141
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const extras = r.extra
|
|
126
|
-
? Object.entries(r.extra)
|
|
127
|
-
.filter(([, v]) => v !== undefined && v !== null)
|
|
128
|
-
.map(([k, v]) => `${k}: ${v}`)
|
|
129
|
-
.join(', ')
|
|
130
|
-
: '';
|
|
131
|
-
console.log(` [${r.id}] ${r.name}${extras ? ` (${extras})` : ''}`);
|
|
142
|
+
catch (err) {
|
|
143
|
+
console.error(`Error: ${err.message}`);
|
|
144
|
+
process.exit(1);
|
|
132
145
|
}
|
|
133
|
-
console.log();
|
|
134
146
|
}
|
|
135
|
-
async function
|
|
136
|
-
const client = await (0, auth_1.getApiClient)();
|
|
147
|
+
async function searchSuggestionsData(query, client, countryCode) {
|
|
137
148
|
const { data, error } = await client.GET('/searchSuggestions/{id}', {
|
|
138
149
|
params: {
|
|
139
150
|
path: { id: query },
|
|
140
151
|
query: {
|
|
141
|
-
countryCode
|
|
152
|
+
countryCode,
|
|
142
153
|
include: ['directHits'],
|
|
143
154
|
},
|
|
144
155
|
},
|
|
145
156
|
});
|
|
146
157
|
if (error || !data) {
|
|
147
|
-
|
|
148
|
-
process.exit(1);
|
|
158
|
+
throw new Error(`Failed to get search suggestions — ${JSON.stringify(error)}`);
|
|
149
159
|
}
|
|
150
160
|
const attrs = data.data?.attributes ?? {};
|
|
151
161
|
const suggestions = (attrs.suggestions ?? []).map((s) => s.query ?? s);
|
|
@@ -158,26 +168,37 @@ async function searchSuggestions(query, json) {
|
|
|
158
168
|
name: itemAttrs?.title ?? itemAttrs?.name ?? 'Unknown',
|
|
159
169
|
};
|
|
160
170
|
});
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
console.log(
|
|
171
|
+
return { suggestions, directHits };
|
|
172
|
+
}
|
|
173
|
+
async function searchSuggestions(query, json) {
|
|
174
|
+
const client = await (0, auth_1.getApiClient)();
|
|
175
|
+
const countryCode = await (0, auth_1.getCountryCode)();
|
|
176
|
+
try {
|
|
177
|
+
const result = await searchSuggestionsData(query, client, countryCode);
|
|
178
|
+
if (json) {
|
|
179
|
+
console.log(JSON.stringify(result, null, 2));
|
|
180
|
+
return;
|
|
170
181
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
182
|
+
if (result.suggestions.length > 0) {
|
|
183
|
+
console.log(`\nSuggestions for "${query}":\n`);
|
|
184
|
+
for (const s of result.suggestions) {
|
|
185
|
+
console.log(` ${s}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (result.directHits.length > 0) {
|
|
189
|
+
console.log(`\nDirect hits:\n`);
|
|
190
|
+
for (const h of result.directHits) {
|
|
191
|
+
console.log(` [${h.id}] (${h.type}) ${h.name}`);
|
|
192
|
+
}
|
|
176
193
|
}
|
|
194
|
+
if (result.suggestions.length === 0 && result.directHits.length === 0) {
|
|
195
|
+
console.log(`No suggestions found for "${query}".`);
|
|
196
|
+
}
|
|
197
|
+
console.log();
|
|
177
198
|
}
|
|
178
|
-
|
|
179
|
-
console.
|
|
199
|
+
catch (err) {
|
|
200
|
+
console.error(`Error: ${err.message}`);
|
|
201
|
+
process.exit(1);
|
|
180
202
|
}
|
|
181
|
-
console.log();
|
|
182
203
|
}
|
|
183
204
|
//# sourceMappingURL=search.js.map
|
package/dist/session.js
CHANGED
|
@@ -42,15 +42,20 @@ const os = __importStar(require("os"));
|
|
|
42
42
|
const SESSION_DIR = path.join(os.homedir(), '.tidal-cli');
|
|
43
43
|
const SESSION_FILE = path.join(SESSION_DIR, 'session.json');
|
|
44
44
|
function ensureDir() {
|
|
45
|
-
|
|
46
|
-
fs.
|
|
45
|
+
try {
|
|
46
|
+
if (!fs.existsSync(SESSION_DIR)) {
|
|
47
|
+
fs.mkdirSync(SESSION_DIR, { mode: 0o700 });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Serverless / read-only filesystem — skip
|
|
47
52
|
}
|
|
48
53
|
}
|
|
49
54
|
function loadStorage() {
|
|
50
|
-
ensureDir();
|
|
51
|
-
if (!fs.existsSync(SESSION_FILE))
|
|
52
|
-
return {};
|
|
53
55
|
try {
|
|
56
|
+
ensureDir();
|
|
57
|
+
if (!fs.existsSync(SESSION_FILE))
|
|
58
|
+
return {};
|
|
54
59
|
return JSON.parse(fs.readFileSync(SESSION_FILE, 'utf-8'));
|
|
55
60
|
}
|
|
56
61
|
catch {
|
|
@@ -58,8 +63,13 @@ function loadStorage() {
|
|
|
58
63
|
}
|
|
59
64
|
}
|
|
60
65
|
function saveStorage(data) {
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
try {
|
|
67
|
+
ensureDir();
|
|
68
|
+
fs.writeFileSync(SESSION_FILE, JSON.stringify(data, null, 2), { mode: 0o600 });
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Serverless / read-only filesystem — skip
|
|
72
|
+
}
|
|
63
73
|
}
|
|
64
74
|
/**
|
|
65
75
|
* Install a globalThis.localStorage polyfill backed by ~/.tidal-cli/session.json.
|
package/dist/share.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ShareLink } from './types';
|
|
2
|
+
export type { ShareLink };
|
|
3
|
+
export type ShareableType = 'tracks' | 'albums';
|
|
4
|
+
export declare function createShareData(resourceType: ShareableType, resourceId: string, client: any): Promise<ShareLink>;
|
|
5
|
+
export declare function createShare(resourceType: ShareableType, resourceId: string, json: boolean): Promise<void>;
|
package/dist/share.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createShareData = createShareData;
|
|
4
|
+
exports.createShare = createShare;
|
|
5
|
+
const auth_1 = require("./auth");
|
|
6
|
+
async function createShareData(resourceType, resourceId, client) {
|
|
7
|
+
const { data, error } = await client.POST('/shares', {
|
|
8
|
+
body: {
|
|
9
|
+
data: {
|
|
10
|
+
type: 'shares',
|
|
11
|
+
relationships: {
|
|
12
|
+
sharedResources: {
|
|
13
|
+
data: [{ id: resourceId, type: resourceType }],
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
if (error || !data) {
|
|
20
|
+
throw new Error(`Failed to create share — ${JSON.stringify(error)}`);
|
|
21
|
+
}
|
|
22
|
+
const created = data.data ?? {};
|
|
23
|
+
const attrs = created.attributes ?? {};
|
|
24
|
+
const tidalLink = (attrs.externalLinks ?? []).find((l) => /tidal\.com/i.test(l?.href ?? ''));
|
|
25
|
+
return {
|
|
26
|
+
id: created.id,
|
|
27
|
+
code: attrs.code ?? '',
|
|
28
|
+
createdAt: attrs.createdAt,
|
|
29
|
+
url: tidalLink?.href ?? attrs.externalLinks?.[0]?.href,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
async function createShare(resourceType, resourceId, json) {
|
|
33
|
+
const client = await (0, auth_1.getApiClient)();
|
|
34
|
+
try {
|
|
35
|
+
const result = await createShareData(resourceType, resourceId, client);
|
|
36
|
+
if (json) {
|
|
37
|
+
console.log(JSON.stringify(result, null, 2));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log(`\nShare created for ${resourceType} ${resourceId}:`);
|
|
41
|
+
console.log(` Code: ${result.code}`);
|
|
42
|
+
if (result.url)
|
|
43
|
+
console.log(` URL: ${result.url}`);
|
|
44
|
+
if (result.createdAt)
|
|
45
|
+
console.log(` Created: ${result.createdAt}`);
|
|
46
|
+
console.log();
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
console.error(`Error: ${err.message}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=share.js.map
|
package/dist/track.d.ts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
+
import type { TrackInfo, SimilarTrack, RadioPlaylist } from './types';
|
|
2
|
+
export type { TrackInfo, SimilarTrack };
|
|
3
|
+
export declare function getTrackInfoData(trackId: string, client: any, countryCode: string): Promise<TrackInfo>;
|
|
1
4
|
export declare function getTrackInfo(trackId: string, json: boolean): Promise<void>;
|
|
5
|
+
export declare function getTrackRadioData(trackId: string, client: any, countryCode: string): Promise<RadioPlaylist[]>;
|
|
2
6
|
export declare function getTrackRadio(trackId: string, json: boolean): Promise<void>;
|
|
7
|
+
interface TrackByIsrcResult {
|
|
8
|
+
id: string;
|
|
9
|
+
title: string;
|
|
10
|
+
artists: string[];
|
|
11
|
+
duration: string;
|
|
12
|
+
isrc?: string;
|
|
13
|
+
popularity?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function getTrackByIsrcData(isrc: string, client: any, countryCode: string): Promise<TrackByIsrcResult[]>;
|
|
3
16
|
export declare function getTrackByIsrc(isrc: string, json: boolean): Promise<void>;
|
|
17
|
+
export declare function getSimilarTracksData(trackId: string, client: any, countryCode: string): Promise<SimilarTrack[]>;
|
|
4
18
|
export declare function getSimilarTracks(trackId: string, json: boolean): Promise<void>;
|