soundcloud-api-ts-next 1.0.0 → 1.1.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.
- package/README.md +102 -78
- package/dist/index.cjs +327 -1
- package/dist/index.d.cts +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/index.mjs +327 -1
- package/dist/server.cjs +112 -0
- package/dist/server.d.cts +11 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.mjs +113 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,38 +1,56 @@
|
|
|
1
1
|
# soundcloud-api-ts-next
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Next.js integration for [soundcloud-api-ts](https://github.com/twin-paws/soundcloud-api-ts) — React hooks + secure API route handlers.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Install
|
|
5
|
+
## Installation
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
|
-
|
|
8
|
+
npm install soundcloud-api-ts-next
|
|
9
|
+
# or
|
|
10
|
+
pnpm add soundcloud-api-ts-next
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
### 1. Server Routes
|
|
16
|
+
|
|
17
|
+
Create an API route handler that proxies SoundCloud requests (keeps your credentials server-side).
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
**App Router** (`app/api/soundcloud/[...route]/route.ts`):
|
|
16
20
|
|
|
17
21
|
```ts
|
|
18
|
-
// app/api/soundcloud/[...route]/route.ts
|
|
19
22
|
import { createSoundCloudRoutes } from "soundcloud-api-ts-next/server";
|
|
20
23
|
|
|
21
24
|
const sc = createSoundCloudRoutes({
|
|
22
|
-
clientId: process.env.
|
|
23
|
-
clientSecret: process.env.
|
|
25
|
+
clientId: process.env.SOUNDCLOUD_CLIENT_ID!,
|
|
26
|
+
clientSecret: process.env.SOUNDCLOUD_CLIENT_SECRET!,
|
|
24
27
|
});
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
const handler = sc.handler();
|
|
30
|
+
export const GET = handler;
|
|
27
31
|
```
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
**Pages Router** (`pages/api/soundcloud/[...route].ts`):
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { createSoundCloudRoutes } from "soundcloud-api-ts-next/server";
|
|
37
|
+
|
|
38
|
+
const sc = createSoundCloudRoutes({
|
|
39
|
+
clientId: process.env.SOUNDCLOUD_CLIENT_ID!,
|
|
40
|
+
clientSecret: process.env.SOUNDCLOUD_CLIENT_SECRET!,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export default sc.pagesHandler();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2. Client Provider
|
|
47
|
+
|
|
48
|
+
Wrap your app with the `SoundCloudProvider`:
|
|
30
49
|
|
|
31
50
|
```tsx
|
|
32
|
-
// app/layout.tsx
|
|
33
51
|
import { SoundCloudProvider } from "soundcloud-api-ts-next";
|
|
34
52
|
|
|
35
|
-
export default function
|
|
53
|
+
export default function Layout({ children }) {
|
|
36
54
|
return (
|
|
37
55
|
<SoundCloudProvider apiPrefix="/api/soundcloud">
|
|
38
56
|
{children}
|
|
@@ -41,94 +59,100 @@ export default function RootLayout({ children }) {
|
|
|
41
59
|
}
|
|
42
60
|
```
|
|
43
61
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
```tsx
|
|
47
|
-
"use client";
|
|
48
|
-
import { useTrackSearch } from "soundcloud-api-ts-next";
|
|
62
|
+
## Hooks
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
const { data, loading, error } = useTrackSearch("lofi beats", { limit: 10 });
|
|
64
|
+
All hooks return `{ data, loading, error }`.
|
|
52
65
|
|
|
53
|
-
|
|
54
|
-
if (error) return <p>Error: {error.message}</p>;
|
|
66
|
+
### Tracks
|
|
55
67
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
```
|
|
68
|
+
| Hook | Arguments | Description |
|
|
69
|
+
|------|-----------|-------------|
|
|
70
|
+
| `useTrack(trackId)` | `string \| number \| undefined` | Fetch a single track |
|
|
71
|
+
| `useTrackSearch(query, options?)` | `string`, `{ limit? }` | Search tracks |
|
|
72
|
+
| `useTrackComments(trackId)` | `string \| number \| undefined` | Get track comments |
|
|
73
|
+
| `useTrackLikes(trackId)` | `string \| number \| undefined` | Get users who liked a track |
|
|
74
|
+
| `useRelatedTracks(trackId)` | `string \| number \| undefined` | Get related tracks |
|
|
65
75
|
|
|
66
|
-
|
|
76
|
+
### Users
|
|
67
77
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
78
|
+
| Hook | Arguments | Description |
|
|
79
|
+
|------|-----------|-------------|
|
|
80
|
+
| `useUser(userId)` | `string \| number \| undefined` | Fetch a single user |
|
|
81
|
+
| `useUserSearch(query)` | `string` | Search users |
|
|
82
|
+
| `useUserTracks(userId)` | `string \| number \| undefined` | Get a user's tracks |
|
|
83
|
+
| `useUserPlaylists(userId)` | `string \| number \| undefined` | Get a user's playlists |
|
|
84
|
+
| `useUserLikes(userId)` | `string \| number \| undefined` | Get a user's liked tracks |
|
|
85
|
+
| `useUserFollowers(userId)` | `string \| number \| undefined` | Get a user's followers |
|
|
86
|
+
| `useUserFollowings(userId)` | `string \| number \| undefined` | Get a user's followings |
|
|
71
87
|
|
|
72
|
-
|
|
73
|
-
clientId: process.env.SC_CLIENT_ID!,
|
|
74
|
-
clientSecret: process.env.SC_CLIENT_SECRET!,
|
|
75
|
-
});
|
|
88
|
+
### Playlists
|
|
76
89
|
|
|
77
|
-
|
|
78
|
-
|
|
90
|
+
| Hook | Arguments | Description |
|
|
91
|
+
|------|-----------|-------------|
|
|
92
|
+
| `usePlaylist(playlistId)` | `string \| number \| undefined` | Fetch a single playlist |
|
|
93
|
+
| `usePlaylistTracks(playlistId)` | `string \| number \| undefined` | Get tracks in a playlist |
|
|
94
|
+
| `usePlaylistSearch(query)` | `string` | Search playlists |
|
|
79
95
|
|
|
80
|
-
|
|
96
|
+
### Player
|
|
81
97
|
|
|
82
|
-
|
|
98
|
+
| Hook | Arguments | Description |
|
|
99
|
+
|------|-----------|-------------|
|
|
100
|
+
| `usePlayer(streamUrl)` | `string \| undefined` | Audio player with play/pause/seek |
|
|
83
101
|
|
|
84
|
-
|
|
102
|
+
## Server Routes
|
|
85
103
|
|
|
86
|
-
|
|
104
|
+
All routes are available via the catch-all handler and as individual methods on the routes object.
|
|
87
105
|
|
|
88
|
-
|
|
106
|
+
### Search
|
|
89
107
|
|
|
90
|
-
|
|
108
|
+
| Route | Method | Description |
|
|
109
|
+
|-------|--------|-------------|
|
|
110
|
+
| `GET /search/tracks?q=...` | `searchTracks(q, page?)` | Search tracks |
|
|
111
|
+
| `GET /search/users?q=...` | `searchUsers(q)` | Search users |
|
|
112
|
+
| `GET /search/playlists?q=...` | `searchPlaylists(q)` | Search playlists |
|
|
91
113
|
|
|
92
|
-
|
|
114
|
+
### Tracks
|
|
93
115
|
|
|
94
|
-
|
|
116
|
+
| Route | Method | Description |
|
|
117
|
+
|-------|--------|-------------|
|
|
118
|
+
| `GET /tracks/:id` | `getTrack(id)` | Get track details |
|
|
119
|
+
| `GET /tracks/:id/stream` | `getTrackStreams(id)` | Get stream URLs |
|
|
120
|
+
| `GET /tracks/:id/comments` | `getTrackComments(id)` | Get track comments |
|
|
121
|
+
| `GET /tracks/:id/likes` | `getTrackLikes(id)` | Get track likes |
|
|
122
|
+
| `GET /tracks/:id/related` | `getRelatedTracks(id)` | Get related tracks |
|
|
95
123
|
|
|
96
|
-
|
|
124
|
+
### Users
|
|
97
125
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
seek(time: number): void;
|
|
107
|
-
}
|
|
108
|
-
```
|
|
126
|
+
| Route | Method | Description |
|
|
127
|
+
|-------|--------|-------------|
|
|
128
|
+
| `GET /users/:id` | `getUser(id)` | Get user details |
|
|
129
|
+
| `GET /users/:id/tracks` | `getUserTracks(id, limit?)` | Get user's tracks |
|
|
130
|
+
| `GET /users/:id/playlists` | `getUserPlaylists(id)` | Get user's playlists |
|
|
131
|
+
| `GET /users/:id/likes/tracks` | `getUserLikesTracks(id)` | Get user's liked tracks |
|
|
132
|
+
| `GET /users/:id/followers` | `getFollowers(id)` | Get user's followers |
|
|
133
|
+
| `GET /users/:id/followings` | `getFollowings(id)` | Get user's followings |
|
|
109
134
|
|
|
110
|
-
|
|
135
|
+
### Playlists
|
|
111
136
|
|
|
112
|
-
|
|
137
|
+
| Route | Method | Description |
|
|
138
|
+
|-------|--------|-------------|
|
|
139
|
+
| `GET /playlists/:id` | `getPlaylist(id)` | Get playlist details |
|
|
140
|
+
| `GET /playlists/:id/tracks` | `getPlaylistTracks(id)` | Get playlist tracks |
|
|
113
141
|
|
|
114
|
-
|
|
115
|
-
|---|---|
|
|
116
|
-
| `/search/tracks?q=...&page=...` | Search tracks |
|
|
117
|
-
| `/tracks/:id` | Get track by ID |
|
|
118
|
-
| `/tracks/:id/stream` | Get stream URLs for a track |
|
|
119
|
-
| `/users/:id` | Get user by ID |
|
|
120
|
-
| `/users/:id/tracks` | Get user's tracks |
|
|
142
|
+
## Types
|
|
121
143
|
|
|
122
|
-
|
|
144
|
+
All SoundCloud types are re-exported from `soundcloud-api-ts`:
|
|
123
145
|
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
146
|
+
```ts
|
|
147
|
+
import type {
|
|
148
|
+
SoundCloudTrack,
|
|
149
|
+
SoundCloudUser,
|
|
150
|
+
SoundCloudPlaylist,
|
|
151
|
+
SoundCloudComment,
|
|
152
|
+
SoundCloudStreams,
|
|
153
|
+
} from "soundcloud-api-ts-next";
|
|
128
154
|
```
|
|
129
155
|
|
|
130
|
-
The `apiPrefix` prop configures where the hooks send requests. Default: `"/api/soundcloud"`.
|
|
131
|
-
|
|
132
156
|
## License
|
|
133
157
|
|
|
134
158
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -170,10 +170,336 @@ function usePlayer(trackId) {
|
|
|
170
170
|
return { playing, progress, duration, play, pause, toggle, seek };
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
// src/client/hooks/useUserTracks.ts
|
|
174
|
+
|
|
175
|
+
function useUserTracks(userId) {
|
|
176
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
177
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
178
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
179
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
180
|
+
_react.useEffect.call(void 0, () => {
|
|
181
|
+
if (userId == null) {
|
|
182
|
+
setData(null);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const controller = new AbortController();
|
|
186
|
+
setLoading(true);
|
|
187
|
+
setError(null);
|
|
188
|
+
fetch(`${apiPrefix}/users/${userId}/tracks`, { signal: controller.signal }).then((res) => {
|
|
189
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
190
|
+
return res.json();
|
|
191
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
192
|
+
if (err.name !== "AbortError") setError(err);
|
|
193
|
+
}).finally(() => setLoading(false));
|
|
194
|
+
return () => controller.abort();
|
|
195
|
+
}, [userId, apiPrefix]);
|
|
196
|
+
return { data, loading, error };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// src/client/hooks/useUserPlaylists.ts
|
|
200
|
+
|
|
201
|
+
function useUserPlaylists(userId) {
|
|
202
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
203
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
204
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
205
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
206
|
+
_react.useEffect.call(void 0, () => {
|
|
207
|
+
if (userId == null) {
|
|
208
|
+
setData(null);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const controller = new AbortController();
|
|
212
|
+
setLoading(true);
|
|
213
|
+
setError(null);
|
|
214
|
+
fetch(`${apiPrefix}/users/${userId}/playlists`, { signal: controller.signal }).then((res) => {
|
|
215
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
216
|
+
return res.json();
|
|
217
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
218
|
+
if (err.name !== "AbortError") setError(err);
|
|
219
|
+
}).finally(() => setLoading(false));
|
|
220
|
+
return () => controller.abort();
|
|
221
|
+
}, [userId, apiPrefix]);
|
|
222
|
+
return { data, loading, error };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/client/hooks/useUserLikes.ts
|
|
226
|
+
|
|
227
|
+
function useUserLikes(userId) {
|
|
228
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
229
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
230
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
231
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
232
|
+
_react.useEffect.call(void 0, () => {
|
|
233
|
+
if (userId == null) {
|
|
234
|
+
setData(null);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const controller = new AbortController();
|
|
238
|
+
setLoading(true);
|
|
239
|
+
setError(null);
|
|
240
|
+
fetch(`${apiPrefix}/users/${userId}/likes/tracks`, { signal: controller.signal }).then((res) => {
|
|
241
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
242
|
+
return res.json();
|
|
243
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
244
|
+
if (err.name !== "AbortError") setError(err);
|
|
245
|
+
}).finally(() => setLoading(false));
|
|
246
|
+
return () => controller.abort();
|
|
247
|
+
}, [userId, apiPrefix]);
|
|
248
|
+
return { data, loading, error };
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// src/client/hooks/useUserFollowers.ts
|
|
252
|
+
|
|
253
|
+
function useUserFollowers(userId) {
|
|
254
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
255
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
256
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
257
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
258
|
+
_react.useEffect.call(void 0, () => {
|
|
259
|
+
if (userId == null) {
|
|
260
|
+
setData(null);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const controller = new AbortController();
|
|
264
|
+
setLoading(true);
|
|
265
|
+
setError(null);
|
|
266
|
+
fetch(`${apiPrefix}/users/${userId}/followers`, { signal: controller.signal }).then((res) => {
|
|
267
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
268
|
+
return res.json();
|
|
269
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
270
|
+
if (err.name !== "AbortError") setError(err);
|
|
271
|
+
}).finally(() => setLoading(false));
|
|
272
|
+
return () => controller.abort();
|
|
273
|
+
}, [userId, apiPrefix]);
|
|
274
|
+
return { data, loading, error };
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/client/hooks/useUserFollowings.ts
|
|
278
|
+
|
|
279
|
+
function useUserFollowings(userId) {
|
|
280
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
281
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
282
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
283
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
284
|
+
_react.useEffect.call(void 0, () => {
|
|
285
|
+
if (userId == null) {
|
|
286
|
+
setData(null);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const controller = new AbortController();
|
|
290
|
+
setLoading(true);
|
|
291
|
+
setError(null);
|
|
292
|
+
fetch(`${apiPrefix}/users/${userId}/followings`, { signal: controller.signal }).then((res) => {
|
|
293
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
294
|
+
return res.json();
|
|
295
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
296
|
+
if (err.name !== "AbortError") setError(err);
|
|
297
|
+
}).finally(() => setLoading(false));
|
|
298
|
+
return () => controller.abort();
|
|
299
|
+
}, [userId, apiPrefix]);
|
|
300
|
+
return { data, loading, error };
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// src/client/hooks/useTrackComments.ts
|
|
304
|
+
|
|
305
|
+
function useTrackComments(trackId) {
|
|
306
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
307
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
308
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
309
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
310
|
+
_react.useEffect.call(void 0, () => {
|
|
311
|
+
if (trackId == null) {
|
|
312
|
+
setData(null);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const controller = new AbortController();
|
|
316
|
+
setLoading(true);
|
|
317
|
+
setError(null);
|
|
318
|
+
fetch(`${apiPrefix}/tracks/${trackId}/comments`, { signal: controller.signal }).then((res) => {
|
|
319
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
320
|
+
return res.json();
|
|
321
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
322
|
+
if (err.name !== "AbortError") setError(err);
|
|
323
|
+
}).finally(() => setLoading(false));
|
|
324
|
+
return () => controller.abort();
|
|
325
|
+
}, [trackId, apiPrefix]);
|
|
326
|
+
return { data, loading, error };
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/client/hooks/useTrackLikes.ts
|
|
330
|
+
|
|
331
|
+
function useTrackLikes(trackId) {
|
|
332
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
333
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
334
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
335
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
336
|
+
_react.useEffect.call(void 0, () => {
|
|
337
|
+
if (trackId == null) {
|
|
338
|
+
setData(null);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const controller = new AbortController();
|
|
342
|
+
setLoading(true);
|
|
343
|
+
setError(null);
|
|
344
|
+
fetch(`${apiPrefix}/tracks/${trackId}/likes`, { signal: controller.signal }).then((res) => {
|
|
345
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
346
|
+
return res.json();
|
|
347
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
348
|
+
if (err.name !== "AbortError") setError(err);
|
|
349
|
+
}).finally(() => setLoading(false));
|
|
350
|
+
return () => controller.abort();
|
|
351
|
+
}, [trackId, apiPrefix]);
|
|
352
|
+
return { data, loading, error };
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// src/client/hooks/useRelatedTracks.ts
|
|
356
|
+
|
|
357
|
+
function useRelatedTracks(trackId) {
|
|
358
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
359
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
360
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
361
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
362
|
+
_react.useEffect.call(void 0, () => {
|
|
363
|
+
if (trackId == null) {
|
|
364
|
+
setData(null);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const controller = new AbortController();
|
|
368
|
+
setLoading(true);
|
|
369
|
+
setError(null);
|
|
370
|
+
fetch(`${apiPrefix}/tracks/${trackId}/related`, { signal: controller.signal }).then((res) => {
|
|
371
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
372
|
+
return res.json();
|
|
373
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
374
|
+
if (err.name !== "AbortError") setError(err);
|
|
375
|
+
}).finally(() => setLoading(false));
|
|
376
|
+
return () => controller.abort();
|
|
377
|
+
}, [trackId, apiPrefix]);
|
|
378
|
+
return { data, loading, error };
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// src/client/hooks/usePlaylist.ts
|
|
382
|
+
|
|
383
|
+
function usePlaylist(playlistId) {
|
|
384
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
385
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
386
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
387
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
388
|
+
_react.useEffect.call(void 0, () => {
|
|
389
|
+
if (playlistId == null) {
|
|
390
|
+
setData(null);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const controller = new AbortController();
|
|
394
|
+
setLoading(true);
|
|
395
|
+
setError(null);
|
|
396
|
+
fetch(`${apiPrefix}/playlists/${playlistId}`, { signal: controller.signal }).then((res) => {
|
|
397
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
398
|
+
return res.json();
|
|
399
|
+
}).then(setData).catch((err) => {
|
|
400
|
+
if (err.name !== "AbortError") setError(err);
|
|
401
|
+
}).finally(() => setLoading(false));
|
|
402
|
+
return () => controller.abort();
|
|
403
|
+
}, [playlistId, apiPrefix]);
|
|
404
|
+
return { data, loading, error };
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// src/client/hooks/usePlaylistTracks.ts
|
|
408
|
+
|
|
409
|
+
function usePlaylistTracks(playlistId) {
|
|
410
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
411
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
412
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
413
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
414
|
+
_react.useEffect.call(void 0, () => {
|
|
415
|
+
if (playlistId == null) {
|
|
416
|
+
setData(null);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const controller = new AbortController();
|
|
420
|
+
setLoading(true);
|
|
421
|
+
setError(null);
|
|
422
|
+
fetch(`${apiPrefix}/playlists/${playlistId}/tracks`, { signal: controller.signal }).then((res) => {
|
|
423
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
424
|
+
return res.json();
|
|
425
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
426
|
+
if (err.name !== "AbortError") setError(err);
|
|
427
|
+
}).finally(() => setLoading(false));
|
|
428
|
+
return () => controller.abort();
|
|
429
|
+
}, [playlistId, apiPrefix]);
|
|
430
|
+
return { data, loading, error };
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// src/client/hooks/usePlaylistSearch.ts
|
|
434
|
+
|
|
435
|
+
function usePlaylistSearch(query) {
|
|
436
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
437
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
438
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
439
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
440
|
+
_react.useEffect.call(void 0, () => {
|
|
441
|
+
if (!query) {
|
|
442
|
+
setData(null);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const controller = new AbortController();
|
|
446
|
+
setLoading(true);
|
|
447
|
+
setError(null);
|
|
448
|
+
const params = new URLSearchParams({ q: query });
|
|
449
|
+
fetch(`${apiPrefix}/search/playlists?${params}`, { signal: controller.signal }).then((res) => {
|
|
450
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
451
|
+
return res.json();
|
|
452
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
453
|
+
if (err.name !== "AbortError") setError(err);
|
|
454
|
+
}).finally(() => setLoading(false));
|
|
455
|
+
return () => controller.abort();
|
|
456
|
+
}, [query, apiPrefix]);
|
|
457
|
+
return { data, loading, error };
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// src/client/hooks/useUserSearch.ts
|
|
461
|
+
|
|
462
|
+
function useUserSearch(query) {
|
|
463
|
+
const { apiPrefix } = useSoundCloudContext();
|
|
464
|
+
const [data, setData] = _react.useState.call(void 0, null);
|
|
465
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
466
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
467
|
+
_react.useEffect.call(void 0, () => {
|
|
468
|
+
if (!query) {
|
|
469
|
+
setData(null);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
const controller = new AbortController();
|
|
473
|
+
setLoading(true);
|
|
474
|
+
setError(null);
|
|
475
|
+
const params = new URLSearchParams({ q: query });
|
|
476
|
+
fetch(`${apiPrefix}/search/users?${params}`, { signal: controller.signal }).then((res) => {
|
|
477
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
478
|
+
return res.json();
|
|
479
|
+
}).then((json) => setData(_nullishCoalesce(json.collection, () => ( json)))).catch((err) => {
|
|
480
|
+
if (err.name !== "AbortError") setError(err);
|
|
481
|
+
}).finally(() => setLoading(false));
|
|
482
|
+
return () => controller.abort();
|
|
483
|
+
}, [query, apiPrefix]);
|
|
484
|
+
return { data, loading, error };
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
|
|
173
499
|
|
|
174
500
|
|
|
175
501
|
|
|
176
502
|
|
|
177
503
|
|
|
178
504
|
|
|
179
|
-
exports.SoundCloudProvider = SoundCloudProvider; exports.usePlayer = usePlayer; exports.useSoundCloudContext = useSoundCloudContext; exports.useTrack = useTrack; exports.useTrackSearch = useTrackSearch; exports.useUser = useUser;
|
|
505
|
+
exports.SoundCloudProvider = SoundCloudProvider; exports.usePlayer = usePlayer; exports.usePlaylist = usePlaylist; exports.usePlaylistSearch = usePlaylistSearch; exports.usePlaylistTracks = usePlaylistTracks; exports.useRelatedTracks = useRelatedTracks; exports.useSoundCloudContext = useSoundCloudContext; exports.useTrack = useTrack; exports.useTrackComments = useTrackComments; exports.useTrackLikes = useTrackLikes; exports.useTrackSearch = useTrackSearch; exports.useUser = useUser; exports.useUserFollowers = useUserFollowers; exports.useUserFollowings = useUserFollowings; exports.useUserLikes = useUserLikes; exports.useUserPlaylists = useUserPlaylists; exports.useUserSearch = useUserSearch; exports.useUserTracks = useUserTracks;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { SoundCloudTrack, SoundCloudUser } from 'soundcloud-api-ts';
|
|
3
|
+
import { SoundCloudTrack, SoundCloudUser, SoundCloudPlaylist, SoundCloudComment } from 'soundcloud-api-ts';
|
|
4
4
|
export { SoundCloudActivitiesResponse, SoundCloudActivity, SoundCloudComment, SoundCloudMe, SoundCloudPaginatedResponse, SoundCloudPlaylist, SoundCloudStreams, SoundCloudTrack, SoundCloudUser, SoundCloudWebProfile } from 'soundcloud-api-ts';
|
|
5
5
|
|
|
6
6
|
interface SoundCloudContextValue {
|
|
@@ -49,4 +49,28 @@ declare function useUser(userId: string | number | undefined): HookResult<SoundC
|
|
|
49
49
|
|
|
50
50
|
declare function usePlayer(trackId: string | number | undefined): PlayerState;
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
declare function useUserTracks(userId: string | number | undefined): HookResult<SoundCloudTrack[]>;
|
|
53
|
+
|
|
54
|
+
declare function useUserPlaylists(userId: string | number | undefined): HookResult<SoundCloudPlaylist[]>;
|
|
55
|
+
|
|
56
|
+
declare function useUserLikes(userId: string | number | undefined): HookResult<SoundCloudTrack[]>;
|
|
57
|
+
|
|
58
|
+
declare function useUserFollowers(userId: string | number | undefined): HookResult<SoundCloudUser[]>;
|
|
59
|
+
|
|
60
|
+
declare function useUserFollowings(userId: string | number | undefined): HookResult<SoundCloudUser[]>;
|
|
61
|
+
|
|
62
|
+
declare function useTrackComments(trackId: string | number | undefined): HookResult<SoundCloudComment[]>;
|
|
63
|
+
|
|
64
|
+
declare function useTrackLikes(trackId: string | number | undefined): HookResult<SoundCloudUser[]>;
|
|
65
|
+
|
|
66
|
+
declare function useRelatedTracks(trackId: string | number | undefined): HookResult<SoundCloudTrack[]>;
|
|
67
|
+
|
|
68
|
+
declare function usePlaylist(playlistId: string | number | undefined): HookResult<SoundCloudPlaylist>;
|
|
69
|
+
|
|
70
|
+
declare function usePlaylistTracks(playlistId: string | number | undefined): HookResult<SoundCloudTrack[]>;
|
|
71
|
+
|
|
72
|
+
declare function usePlaylistSearch(query: string): HookResult<SoundCloudPlaylist[]>;
|
|
73
|
+
|
|
74
|
+
declare function useUserSearch(query: string): HookResult<SoundCloudUser[]>;
|
|
75
|
+
|
|
76
|
+
export { type HookResult, type PlayerState, SoundCloudProvider, type SoundCloudProviderProps, type SoundCloudRoutesConfig, type UseTrackSearchOptions, usePlayer, usePlaylist, usePlaylistSearch, usePlaylistTracks, useRelatedTracks, useSoundCloudContext, useTrack, useTrackComments, useTrackLikes, useTrackSearch, useUser, useUserFollowers, useUserFollowings, useUserLikes, useUserPlaylists, useUserSearch, useUserTracks };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { SoundCloudTrack, SoundCloudUser } from 'soundcloud-api-ts';
|
|
3
|
+
import { SoundCloudTrack, SoundCloudUser, SoundCloudPlaylist, SoundCloudComment } from 'soundcloud-api-ts';
|
|
4
4
|
export { SoundCloudActivitiesResponse, SoundCloudActivity, SoundCloudComment, SoundCloudMe, SoundCloudPaginatedResponse, SoundCloudPlaylist, SoundCloudStreams, SoundCloudTrack, SoundCloudUser, SoundCloudWebProfile } from 'soundcloud-api-ts';
|
|
5
5
|
|
|
6
6
|
interface SoundCloudContextValue {
|
|
@@ -49,4 +49,28 @@ declare function useUser(userId: string | number | undefined): HookResult<SoundC
|
|
|
49
49
|
|
|
50
50
|
declare function usePlayer(trackId: string | number | undefined): PlayerState;
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
declare function useUserTracks(userId: string | number | undefined): HookResult<SoundCloudTrack[]>;
|
|
53
|
+
|
|
54
|
+
declare function useUserPlaylists(userId: string | number | undefined): HookResult<SoundCloudPlaylist[]>;
|
|
55
|
+
|
|
56
|
+
declare function useUserLikes(userId: string | number | undefined): HookResult<SoundCloudTrack[]>;
|
|
57
|
+
|
|
58
|
+
declare function useUserFollowers(userId: string | number | undefined): HookResult<SoundCloudUser[]>;
|
|
59
|
+
|
|
60
|
+
declare function useUserFollowings(userId: string | number | undefined): HookResult<SoundCloudUser[]>;
|
|
61
|
+
|
|
62
|
+
declare function useTrackComments(trackId: string | number | undefined): HookResult<SoundCloudComment[]>;
|
|
63
|
+
|
|
64
|
+
declare function useTrackLikes(trackId: string | number | undefined): HookResult<SoundCloudUser[]>;
|
|
65
|
+
|
|
66
|
+
declare function useRelatedTracks(trackId: string | number | undefined): HookResult<SoundCloudTrack[]>;
|
|
67
|
+
|
|
68
|
+
declare function usePlaylist(playlistId: string | number | undefined): HookResult<SoundCloudPlaylist>;
|
|
69
|
+
|
|
70
|
+
declare function usePlaylistTracks(playlistId: string | number | undefined): HookResult<SoundCloudTrack[]>;
|
|
71
|
+
|
|
72
|
+
declare function usePlaylistSearch(query: string): HookResult<SoundCloudPlaylist[]>;
|
|
73
|
+
|
|
74
|
+
declare function useUserSearch(query: string): HookResult<SoundCloudUser[]>;
|
|
75
|
+
|
|
76
|
+
export { type HookResult, type PlayerState, SoundCloudProvider, type SoundCloudProviderProps, type SoundCloudRoutesConfig, type UseTrackSearchOptions, usePlayer, usePlaylist, usePlaylistSearch, usePlaylistTracks, useRelatedTracks, useSoundCloudContext, useTrack, useTrackComments, useTrackLikes, useTrackSearch, useUser, useUserFollowers, useUserFollowings, useUserLikes, useUserPlaylists, useUserSearch, useUserTracks };
|