soundcloud-api-ts 1.13.3 → 1.14.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/dist/index.d.ts CHANGED
@@ -1,6 +1,84 @@
1
1
  import { S as SoundCloudTrack, a as SoundCloudPlaylist, b as SoundCloudToken, c as SoundCloudPaginatedResponse, d as SoundCloudMe, e as SoundCloudActivitiesResponse, f as SoundCloudUser, g as SoundCloudConnection, h as SoundCloudWebProfile, i as SoundCloudStreams, j as SoundCloudComment } from './index-DX6Anc1-.js';
2
2
  export { k as SoundCloudActivity, l as SoundCloudCommentUser, m as SoundCloudError, n as SoundCloudQuota, o as SoundCloudSubscription, p as SoundCloudSubscriptionProduct } from './index-DX6Anc1-.js';
3
3
 
4
+ /**
5
+ * Deduplicates concurrent in-flight requests with the same key.
6
+ *
7
+ * When multiple callers request the same resource simultaneously,
8
+ * only one underlying promise is created — all callers share the result.
9
+ * The key is cleaned up automatically once the promise settles.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const deduper = new InFlightDeduper();
14
+ *
15
+ * // Both calls share a single fetch:
16
+ * const [a, b] = await Promise.all([
17
+ * deduper.add('track:123', () => fetchTrack(123)),
18
+ * deduper.add('track:123', () => fetchTrack(123)),
19
+ * ]);
20
+ * // a === b (same resolved value)
21
+ * ```
22
+ */
23
+ declare class InFlightDeduper {
24
+ private inFlight;
25
+ /**
26
+ * Return an existing in-flight promise for `key`, or start a new one via `factory`.
27
+ * The entry is removed from the map once the promise settles (resolve or reject).
28
+ */
29
+ add<T>(key: string, factory: () => Promise<T>): Promise<T>;
30
+ /** Number of currently in-flight requests */
31
+ get size(): number;
32
+ }
33
+
34
+ /**
35
+ * A cache entry with an expiration timestamp.
36
+ */
37
+ interface SoundCloudCacheEntry<T> {
38
+ /** The cached value */
39
+ value: T;
40
+ /** Unix timestamp (ms) when this entry expires */
41
+ expiresAt: number;
42
+ }
43
+ /**
44
+ * Cache interface for SoundCloud API responses.
45
+ *
46
+ * Implement this interface to plug in any caching backend (in-memory, Redis, etc.).
47
+ * Pass an instance as `cache` in {@link SoundCloudClientConfig} to enable caching.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * // Simple in-memory implementation
52
+ * class SimpleCache implements SoundCloudCache {
53
+ * private store = new Map<string, SoundCloudCacheEntry<unknown>>();
54
+ *
55
+ * get<T>(key: string): T | undefined {
56
+ * const entry = this.store.get(key) as SoundCloudCacheEntry<T> | undefined;
57
+ * if (!entry || Date.now() > entry.expiresAt) return undefined;
58
+ * return entry.value;
59
+ * }
60
+ *
61
+ * set<T>(key: string, value: T, { ttlMs }: { ttlMs: number }): void {
62
+ * this.store.set(key, { value, expiresAt: Date.now() + ttlMs });
63
+ * }
64
+ *
65
+ * delete(key: string): void {
66
+ * this.store.delete(key);
67
+ * }
68
+ * }
69
+ * ```
70
+ */
71
+ interface SoundCloudCache {
72
+ /** Retrieve a cached value by key, or `undefined` if missing or expired */
73
+ get<T>(key: string): Promise<T | undefined> | T | undefined;
74
+ /** Store a value with a TTL in milliseconds */
75
+ set<T>(key: string, value: T, options: {
76
+ ttlMs: number;
77
+ }): Promise<void> | void;
78
+ /** Remove a cached entry */
79
+ delete(key: string): Promise<void> | void;
80
+ }
81
+
4
82
  /**
5
83
  * Options for making a request to the SoundCloud API via {@link scFetch}.
6
84
  */
@@ -81,6 +159,14 @@ interface AutoRefreshContext {
81
159
  retry?: RetryConfig;
82
160
  /** Called after every API request with structured telemetry */
83
161
  onRequest?: (telemetry: SCRequestTelemetry) => void;
162
+ /** Custom fetch implementation (defaults to `globalThis.fetch`) */
163
+ fetchImpl?: typeof globalThis.fetch;
164
+ /** Deduplicates concurrent identical GET requests when set */
165
+ deduper?: InFlightDeduper;
166
+ /** Optional cache backend for GET responses */
167
+ cache?: SoundCloudCache;
168
+ /** TTL in milliseconds for cached GET responses (default: 60000) */
169
+ cacheTtlMs?: number;
84
170
  }
85
171
  /**
86
172
  * Make a request to the SoundCloud API using native `fetch`.
@@ -129,7 +215,7 @@ declare function scFetch<T>(options: RequestOptions, refreshCtx?: AutoRefreshCon
129
215
  * );
130
216
  * ```
131
217
  */
132
- declare function scFetchUrl<T>(url: string, token?: string, retryConfig?: RetryConfig, onRequest?: (telemetry: SCRequestTelemetry) => void): Promise<T>;
218
+ declare function scFetchUrl<T>(url: string, token?: string, retryConfig?: RetryConfig, onRequest?: (telemetry: SCRequestTelemetry) => void, fetchImpl?: typeof globalThis.fetch): Promise<T>;
133
219
 
134
220
  /**
135
221
  * Raw response from the SoundCloud API, including status code and headers.
@@ -180,54 +266,6 @@ declare class RawClient {
180
266
  delete<T = unknown>(path: string): Promise<RawResponse<T>>;
181
267
  }
182
268
 
183
- /**
184
- * A cache entry with an expiration timestamp.
185
- */
186
- interface SoundCloudCacheEntry<T> {
187
- /** The cached value */
188
- value: T;
189
- /** Unix timestamp (ms) when this entry expires */
190
- expiresAt: number;
191
- }
192
- /**
193
- * Cache interface for SoundCloud API responses.
194
- *
195
- * Implement this interface to plug in any caching backend (in-memory, Redis, etc.).
196
- * Pass an instance as `cache` in {@link SoundCloudClientConfig} to enable caching.
197
- *
198
- * @example
199
- * ```ts
200
- * // Simple in-memory implementation
201
- * class SimpleCache implements SoundCloudCache {
202
- * private store = new Map<string, SoundCloudCacheEntry<unknown>>();
203
- *
204
- * get<T>(key: string): T | undefined {
205
- * const entry = this.store.get(key) as SoundCloudCacheEntry<T> | undefined;
206
- * if (!entry || Date.now() > entry.expiresAt) return undefined;
207
- * return entry.value;
208
- * }
209
- *
210
- * set<T>(key: string, value: T, { ttlMs }: { ttlMs: number }): void {
211
- * this.store.set(key, { value, expiresAt: Date.now() + ttlMs });
212
- * }
213
- *
214
- * delete(key: string): void {
215
- * this.store.delete(key);
216
- * }
217
- * }
218
- * ```
219
- */
220
- interface SoundCloudCache {
221
- /** Retrieve a cached value by key, or `undefined` if missing or expired */
222
- get<T>(key: string): Promise<T | undefined> | T | undefined;
223
- /** Store a value with a TTL in milliseconds */
224
- set<T>(key: string, value: T, options: {
225
- ttlMs: number;
226
- }): Promise<void> | void;
227
- /** Remove a cached entry */
228
- delete(key: string): Promise<void> | void;
229
- }
230
-
231
269
  /**
232
270
  * Parameters for updating a track's metadata via {@link updateTrack}.
233
271
  */
@@ -437,11 +475,11 @@ interface SoundCloudClientConfig {
437
475
  onRequest?: (telemetry: SCRequestTelemetry) => void;
438
476
  /** Custom fetch implementation (defaults to `globalThis.fetch`) */
439
477
  fetch?: typeof globalThis.fetch;
440
- /** Deduplicate concurrent identical requests (default: true) */
478
+ /** Deduplicate concurrent identical GET requests (default: true) */
441
479
  dedupe?: boolean;
442
- /** Optional cache backend for API responses */
480
+ /** Optional cache backend for GET responses */
443
481
  cache?: SoundCloudCache;
444
- /** Default TTL in milliseconds for cached responses (default: 60000) */
482
+ /** Default TTL in milliseconds for cached GET responses (default: 60000) */
445
483
  cacheTtlMs?: number;
446
484
  /** Called before each retry attempt with structured retry info */
447
485
  onRetry?: (info: RetryInfo) => void;
@@ -1477,36 +1515,6 @@ declare namespace SoundCloudClient {
1477
1515
  }
1478
1516
  }
1479
1517
 
1480
- /**
1481
- * Deduplicates concurrent in-flight requests with the same key.
1482
- *
1483
- * When multiple callers request the same resource simultaneously,
1484
- * only one underlying promise is created — all callers share the result.
1485
- * The key is cleaned up automatically once the promise settles.
1486
- *
1487
- * @example
1488
- * ```ts
1489
- * const deduper = new InFlightDeduper();
1490
- *
1491
- * // Both calls share a single fetch:
1492
- * const [a, b] = await Promise.all([
1493
- * deduper.add('track:123', () => fetchTrack(123)),
1494
- * deduper.add('track:123', () => fetchTrack(123)),
1495
- * ]);
1496
- * // a === b (same resolved value)
1497
- * ```
1498
- */
1499
- declare class InFlightDeduper {
1500
- private inFlight;
1501
- /**
1502
- * Return an existing in-flight promise for `key`, or start a new one via `factory`.
1503
- * The entry is removed from the map once the promise settles (resolve or reject).
1504
- */
1505
- add<T>(key: string, factory: () => Promise<T>): Promise<T>;
1506
- /** Number of currently in-flight requests */
1507
- get size(): number;
1508
- }
1509
-
1510
1518
  /**
1511
1519
  * List of operation IDs currently implemented by soundcloud-api-ts.
1512
1520
  * Used for OpenAPI coverage reporting.
package/dist/index.js CHANGED
@@ -1,277 +1,277 @@
1
1
  'use strict';
2
2
 
3
- var chunkZOHFLO4B_js = require('./chunk-ZOHFLO4B.js');
3
+ var chunkYBNVXQ2E_js = require('./chunk-YBNVXQ2E.js');
4
4
  var chunkMLVA534Z_js = require('./chunk-MLVA534Z.js');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "IMPLEMENTED_OPERATIONS", {
9
9
  enumerable: true,
10
- get: function () { return chunkZOHFLO4B_js.IMPLEMENTED_OPERATIONS; }
10
+ get: function () { return chunkYBNVXQ2E_js.IMPLEMENTED_OPERATIONS; }
11
11
  });
12
12
  Object.defineProperty(exports, "InFlightDeduper", {
13
13
  enumerable: true,
14
- get: function () { return chunkZOHFLO4B_js.InFlightDeduper; }
14
+ get: function () { return chunkYBNVXQ2E_js.InFlightDeduper; }
15
15
  });
16
16
  Object.defineProperty(exports, "RawClient", {
17
17
  enumerable: true,
18
- get: function () { return chunkZOHFLO4B_js.RawClient; }
18
+ get: function () { return chunkYBNVXQ2E_js.RawClient; }
19
19
  });
20
20
  Object.defineProperty(exports, "SoundCloudClient", {
21
21
  enumerable: true,
22
- get: function () { return chunkZOHFLO4B_js.SoundCloudClient; }
22
+ get: function () { return chunkYBNVXQ2E_js.SoundCloudClient; }
23
23
  });
24
24
  Object.defineProperty(exports, "createPlaylist", {
25
25
  enumerable: true,
26
- get: function () { return chunkZOHFLO4B_js.createPlaylist; }
26
+ get: function () { return chunkYBNVXQ2E_js.createPlaylist; }
27
27
  });
28
28
  Object.defineProperty(exports, "createTrackComment", {
29
29
  enumerable: true,
30
- get: function () { return chunkZOHFLO4B_js.createTrackComment; }
30
+ get: function () { return chunkYBNVXQ2E_js.createTrackComment; }
31
31
  });
32
32
  Object.defineProperty(exports, "deletePlaylist", {
33
33
  enumerable: true,
34
- get: function () { return chunkZOHFLO4B_js.deletePlaylist; }
34
+ get: function () { return chunkYBNVXQ2E_js.deletePlaylist; }
35
35
  });
36
36
  Object.defineProperty(exports, "deleteTrack", {
37
37
  enumerable: true,
38
- get: function () { return chunkZOHFLO4B_js.deleteTrack; }
38
+ get: function () { return chunkYBNVXQ2E_js.deleteTrack; }
39
39
  });
40
40
  Object.defineProperty(exports, "fetchAll", {
41
41
  enumerable: true,
42
- get: function () { return chunkZOHFLO4B_js.fetchAll; }
42
+ get: function () { return chunkYBNVXQ2E_js.fetchAll; }
43
43
  });
44
44
  Object.defineProperty(exports, "followUser", {
45
45
  enumerable: true,
46
- get: function () { return chunkZOHFLO4B_js.followUser; }
46
+ get: function () { return chunkYBNVXQ2E_js.followUser; }
47
47
  });
48
48
  Object.defineProperty(exports, "generateCodeChallenge", {
49
49
  enumerable: true,
50
- get: function () { return chunkZOHFLO4B_js.generateCodeChallenge; }
50
+ get: function () { return chunkYBNVXQ2E_js.generateCodeChallenge; }
51
51
  });
52
52
  Object.defineProperty(exports, "generateCodeVerifier", {
53
53
  enumerable: true,
54
- get: function () { return chunkZOHFLO4B_js.generateCodeVerifier; }
54
+ get: function () { return chunkYBNVXQ2E_js.generateCodeVerifier; }
55
55
  });
56
56
  Object.defineProperty(exports, "getAuthorizationUrl", {
57
57
  enumerable: true,
58
- get: function () { return chunkZOHFLO4B_js.getAuthorizationUrl; }
58
+ get: function () { return chunkYBNVXQ2E_js.getAuthorizationUrl; }
59
59
  });
60
60
  Object.defineProperty(exports, "getClientToken", {
61
61
  enumerable: true,
62
- get: function () { return chunkZOHFLO4B_js.getClientToken; }
62
+ get: function () { return chunkYBNVXQ2E_js.getClientToken; }
63
63
  });
64
64
  Object.defineProperty(exports, "getFollowers", {
65
65
  enumerable: true,
66
- get: function () { return chunkZOHFLO4B_js.getFollowers; }
66
+ get: function () { return chunkYBNVXQ2E_js.getFollowers; }
67
67
  });
68
68
  Object.defineProperty(exports, "getFollowings", {
69
69
  enumerable: true,
70
- get: function () { return chunkZOHFLO4B_js.getFollowings; }
70
+ get: function () { return chunkYBNVXQ2E_js.getFollowings; }
71
71
  });
72
72
  Object.defineProperty(exports, "getMe", {
73
73
  enumerable: true,
74
- get: function () { return chunkZOHFLO4B_js.getMe; }
74
+ get: function () { return chunkYBNVXQ2E_js.getMe; }
75
75
  });
76
76
  Object.defineProperty(exports, "getMeActivities", {
77
77
  enumerable: true,
78
- get: function () { return chunkZOHFLO4B_js.getMeActivities; }
78
+ get: function () { return chunkYBNVXQ2E_js.getMeActivities; }
79
79
  });
80
80
  Object.defineProperty(exports, "getMeActivitiesOwn", {
81
81
  enumerable: true,
82
- get: function () { return chunkZOHFLO4B_js.getMeActivitiesOwn; }
82
+ get: function () { return chunkYBNVXQ2E_js.getMeActivitiesOwn; }
83
83
  });
84
84
  Object.defineProperty(exports, "getMeActivitiesTracks", {
85
85
  enumerable: true,
86
- get: function () { return chunkZOHFLO4B_js.getMeActivitiesTracks; }
86
+ get: function () { return chunkYBNVXQ2E_js.getMeActivitiesTracks; }
87
87
  });
88
88
  Object.defineProperty(exports, "getMeConnections", {
89
89
  enumerable: true,
90
- get: function () { return chunkZOHFLO4B_js.getMeConnections; }
90
+ get: function () { return chunkYBNVXQ2E_js.getMeConnections; }
91
91
  });
92
92
  Object.defineProperty(exports, "getMeFollowers", {
93
93
  enumerable: true,
94
- get: function () { return chunkZOHFLO4B_js.getMeFollowers; }
94
+ get: function () { return chunkYBNVXQ2E_js.getMeFollowers; }
95
95
  });
96
96
  Object.defineProperty(exports, "getMeFollowings", {
97
97
  enumerable: true,
98
- get: function () { return chunkZOHFLO4B_js.getMeFollowings; }
98
+ get: function () { return chunkYBNVXQ2E_js.getMeFollowings; }
99
99
  });
100
100
  Object.defineProperty(exports, "getMeFollowingsTracks", {
101
101
  enumerable: true,
102
- get: function () { return chunkZOHFLO4B_js.getMeFollowingsTracks; }
102
+ get: function () { return chunkYBNVXQ2E_js.getMeFollowingsTracks; }
103
103
  });
104
104
  Object.defineProperty(exports, "getMeLikesPlaylists", {
105
105
  enumerable: true,
106
- get: function () { return chunkZOHFLO4B_js.getMeLikesPlaylists; }
106
+ get: function () { return chunkYBNVXQ2E_js.getMeLikesPlaylists; }
107
107
  });
108
108
  Object.defineProperty(exports, "getMeLikesTracks", {
109
109
  enumerable: true,
110
- get: function () { return chunkZOHFLO4B_js.getMeLikesTracks; }
110
+ get: function () { return chunkYBNVXQ2E_js.getMeLikesTracks; }
111
111
  });
112
112
  Object.defineProperty(exports, "getMePlaylists", {
113
113
  enumerable: true,
114
- get: function () { return chunkZOHFLO4B_js.getMePlaylists; }
114
+ get: function () { return chunkYBNVXQ2E_js.getMePlaylists; }
115
115
  });
116
116
  Object.defineProperty(exports, "getMeTracks", {
117
117
  enumerable: true,
118
- get: function () { return chunkZOHFLO4B_js.getMeTracks; }
118
+ get: function () { return chunkYBNVXQ2E_js.getMeTracks; }
119
119
  });
120
120
  Object.defineProperty(exports, "getPlaylist", {
121
121
  enumerable: true,
122
- get: function () { return chunkZOHFLO4B_js.getPlaylist; }
122
+ get: function () { return chunkYBNVXQ2E_js.getPlaylist; }
123
123
  });
124
124
  Object.defineProperty(exports, "getPlaylistReposts", {
125
125
  enumerable: true,
126
- get: function () { return chunkZOHFLO4B_js.getPlaylistReposts; }
126
+ get: function () { return chunkYBNVXQ2E_js.getPlaylistReposts; }
127
127
  });
128
128
  Object.defineProperty(exports, "getPlaylistTracks", {
129
129
  enumerable: true,
130
- get: function () { return chunkZOHFLO4B_js.getPlaylistTracks; }
130
+ get: function () { return chunkYBNVXQ2E_js.getPlaylistTracks; }
131
131
  });
132
132
  Object.defineProperty(exports, "getRelatedTracks", {
133
133
  enumerable: true,
134
- get: function () { return chunkZOHFLO4B_js.getRelatedTracks; }
134
+ get: function () { return chunkYBNVXQ2E_js.getRelatedTracks; }
135
135
  });
136
136
  Object.defineProperty(exports, "getSoundCloudWidgetUrl", {
137
137
  enumerable: true,
138
- get: function () { return chunkZOHFLO4B_js.getSoundCloudWidgetUrl; }
138
+ get: function () { return chunkYBNVXQ2E_js.getSoundCloudWidgetUrl; }
139
139
  });
140
140
  Object.defineProperty(exports, "getTrack", {
141
141
  enumerable: true,
142
- get: function () { return chunkZOHFLO4B_js.getTrack; }
142
+ get: function () { return chunkYBNVXQ2E_js.getTrack; }
143
143
  });
144
144
  Object.defineProperty(exports, "getTrackComments", {
145
145
  enumerable: true,
146
- get: function () { return chunkZOHFLO4B_js.getTrackComments; }
146
+ get: function () { return chunkYBNVXQ2E_js.getTrackComments; }
147
147
  });
148
148
  Object.defineProperty(exports, "getTrackLikes", {
149
149
  enumerable: true,
150
- get: function () { return chunkZOHFLO4B_js.getTrackLikes; }
150
+ get: function () { return chunkYBNVXQ2E_js.getTrackLikes; }
151
151
  });
152
152
  Object.defineProperty(exports, "getTrackReposts", {
153
153
  enumerable: true,
154
- get: function () { return chunkZOHFLO4B_js.getTrackReposts; }
154
+ get: function () { return chunkYBNVXQ2E_js.getTrackReposts; }
155
155
  });
156
156
  Object.defineProperty(exports, "getTrackStreams", {
157
157
  enumerable: true,
158
- get: function () { return chunkZOHFLO4B_js.getTrackStreams; }
158
+ get: function () { return chunkYBNVXQ2E_js.getTrackStreams; }
159
159
  });
160
160
  Object.defineProperty(exports, "getTracks", {
161
161
  enumerable: true,
162
- get: function () { return chunkZOHFLO4B_js.getTracks; }
162
+ get: function () { return chunkYBNVXQ2E_js.getTracks; }
163
163
  });
164
164
  Object.defineProperty(exports, "getUser", {
165
165
  enumerable: true,
166
- get: function () { return chunkZOHFLO4B_js.getUser; }
166
+ get: function () { return chunkYBNVXQ2E_js.getUser; }
167
167
  });
168
168
  Object.defineProperty(exports, "getUserLikesPlaylists", {
169
169
  enumerable: true,
170
- get: function () { return chunkZOHFLO4B_js.getUserLikesPlaylists; }
170
+ get: function () { return chunkYBNVXQ2E_js.getUserLikesPlaylists; }
171
171
  });
172
172
  Object.defineProperty(exports, "getUserLikesTracks", {
173
173
  enumerable: true,
174
- get: function () { return chunkZOHFLO4B_js.getUserLikesTracks; }
174
+ get: function () { return chunkYBNVXQ2E_js.getUserLikesTracks; }
175
175
  });
176
176
  Object.defineProperty(exports, "getUserPlaylists", {
177
177
  enumerable: true,
178
- get: function () { return chunkZOHFLO4B_js.getUserPlaylists; }
178
+ get: function () { return chunkYBNVXQ2E_js.getUserPlaylists; }
179
179
  });
180
180
  Object.defineProperty(exports, "getUserToken", {
181
181
  enumerable: true,
182
- get: function () { return chunkZOHFLO4B_js.getUserToken; }
182
+ get: function () { return chunkYBNVXQ2E_js.getUserToken; }
183
183
  });
184
184
  Object.defineProperty(exports, "getUserTracks", {
185
185
  enumerable: true,
186
- get: function () { return chunkZOHFLO4B_js.getUserTracks; }
186
+ get: function () { return chunkYBNVXQ2E_js.getUserTracks; }
187
187
  });
188
188
  Object.defineProperty(exports, "getUserWebProfiles", {
189
189
  enumerable: true,
190
- get: function () { return chunkZOHFLO4B_js.getUserWebProfiles; }
190
+ get: function () { return chunkYBNVXQ2E_js.getUserWebProfiles; }
191
191
  });
192
192
  Object.defineProperty(exports, "likePlaylist", {
193
193
  enumerable: true,
194
- get: function () { return chunkZOHFLO4B_js.likePlaylist; }
194
+ get: function () { return chunkYBNVXQ2E_js.likePlaylist; }
195
195
  });
196
196
  Object.defineProperty(exports, "likeTrack", {
197
197
  enumerable: true,
198
- get: function () { return chunkZOHFLO4B_js.likeTrack; }
198
+ get: function () { return chunkYBNVXQ2E_js.likeTrack; }
199
199
  });
200
200
  Object.defineProperty(exports, "paginate", {
201
201
  enumerable: true,
202
- get: function () { return chunkZOHFLO4B_js.paginate; }
202
+ get: function () { return chunkYBNVXQ2E_js.paginate; }
203
203
  });
204
204
  Object.defineProperty(exports, "paginateItems", {
205
205
  enumerable: true,
206
- get: function () { return chunkZOHFLO4B_js.paginateItems; }
206
+ get: function () { return chunkYBNVXQ2E_js.paginateItems; }
207
207
  });
208
208
  Object.defineProperty(exports, "refreshUserToken", {
209
209
  enumerable: true,
210
- get: function () { return chunkZOHFLO4B_js.refreshUserToken; }
210
+ get: function () { return chunkYBNVXQ2E_js.refreshUserToken; }
211
211
  });
212
212
  Object.defineProperty(exports, "repostPlaylist", {
213
213
  enumerable: true,
214
- get: function () { return chunkZOHFLO4B_js.repostPlaylist; }
214
+ get: function () { return chunkYBNVXQ2E_js.repostPlaylist; }
215
215
  });
216
216
  Object.defineProperty(exports, "repostTrack", {
217
217
  enumerable: true,
218
- get: function () { return chunkZOHFLO4B_js.repostTrack; }
218
+ get: function () { return chunkYBNVXQ2E_js.repostTrack; }
219
219
  });
220
220
  Object.defineProperty(exports, "resolveUrl", {
221
221
  enumerable: true,
222
- get: function () { return chunkZOHFLO4B_js.resolveUrl; }
222
+ get: function () { return chunkYBNVXQ2E_js.resolveUrl; }
223
223
  });
224
224
  Object.defineProperty(exports, "scFetch", {
225
225
  enumerable: true,
226
- get: function () { return chunkZOHFLO4B_js.scFetch; }
226
+ get: function () { return chunkYBNVXQ2E_js.scFetch; }
227
227
  });
228
228
  Object.defineProperty(exports, "scFetchUrl", {
229
229
  enumerable: true,
230
- get: function () { return chunkZOHFLO4B_js.scFetchUrl; }
230
+ get: function () { return chunkYBNVXQ2E_js.scFetchUrl; }
231
231
  });
232
232
  Object.defineProperty(exports, "searchPlaylists", {
233
233
  enumerable: true,
234
- get: function () { return chunkZOHFLO4B_js.searchPlaylists; }
234
+ get: function () { return chunkYBNVXQ2E_js.searchPlaylists; }
235
235
  });
236
236
  Object.defineProperty(exports, "searchTracks", {
237
237
  enumerable: true,
238
- get: function () { return chunkZOHFLO4B_js.searchTracks; }
238
+ get: function () { return chunkYBNVXQ2E_js.searchTracks; }
239
239
  });
240
240
  Object.defineProperty(exports, "searchUsers", {
241
241
  enumerable: true,
242
- get: function () { return chunkZOHFLO4B_js.searchUsers; }
242
+ get: function () { return chunkYBNVXQ2E_js.searchUsers; }
243
243
  });
244
244
  Object.defineProperty(exports, "signOut", {
245
245
  enumerable: true,
246
- get: function () { return chunkZOHFLO4B_js.signOut; }
246
+ get: function () { return chunkYBNVXQ2E_js.signOut; }
247
247
  });
248
248
  Object.defineProperty(exports, "unfollowUser", {
249
249
  enumerable: true,
250
- get: function () { return chunkZOHFLO4B_js.unfollowUser; }
250
+ get: function () { return chunkYBNVXQ2E_js.unfollowUser; }
251
251
  });
252
252
  Object.defineProperty(exports, "unlikePlaylist", {
253
253
  enumerable: true,
254
- get: function () { return chunkZOHFLO4B_js.unlikePlaylist; }
254
+ get: function () { return chunkYBNVXQ2E_js.unlikePlaylist; }
255
255
  });
256
256
  Object.defineProperty(exports, "unlikeTrack", {
257
257
  enumerable: true,
258
- get: function () { return chunkZOHFLO4B_js.unlikeTrack; }
258
+ get: function () { return chunkYBNVXQ2E_js.unlikeTrack; }
259
259
  });
260
260
  Object.defineProperty(exports, "unrepostPlaylist", {
261
261
  enumerable: true,
262
- get: function () { return chunkZOHFLO4B_js.unrepostPlaylist; }
262
+ get: function () { return chunkYBNVXQ2E_js.unrepostPlaylist; }
263
263
  });
264
264
  Object.defineProperty(exports, "unrepostTrack", {
265
265
  enumerable: true,
266
- get: function () { return chunkZOHFLO4B_js.unrepostTrack; }
266
+ get: function () { return chunkYBNVXQ2E_js.unrepostTrack; }
267
267
  });
268
268
  Object.defineProperty(exports, "updatePlaylist", {
269
269
  enumerable: true,
270
- get: function () { return chunkZOHFLO4B_js.updatePlaylist; }
270
+ get: function () { return chunkYBNVXQ2E_js.updatePlaylist; }
271
271
  });
272
272
  Object.defineProperty(exports, "updateTrack", {
273
273
  enumerable: true,
274
- get: function () { return chunkZOHFLO4B_js.updateTrack; }
274
+ get: function () { return chunkYBNVXQ2E_js.updateTrack; }
275
275
  });
276
276
  Object.defineProperty(exports, "SoundCloudError", {
277
277
  enumerable: true,
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { IMPLEMENTED_OPERATIONS, InFlightDeduper, RawClient, SoundCloudClient, createPlaylist, createTrackComment, deletePlaylist, deleteTrack, fetchAll, followUser, generateCodeChallenge, generateCodeVerifier, getAuthorizationUrl, getClientToken, getFollowers, getFollowings, getMe, getMeActivities, getMeActivitiesOwn, getMeActivitiesTracks, getMeConnections, getMeFollowers, getMeFollowings, getMeFollowingsTracks, getMeLikesPlaylists, getMeLikesTracks, getMePlaylists, getMeTracks, getPlaylist, getPlaylistReposts, getPlaylistTracks, getRelatedTracks, getSoundCloudWidgetUrl, getTrack, getTrackComments, getTrackLikes, getTrackReposts, getTrackStreams, getTracks, getUser, getUserLikesPlaylists, getUserLikesTracks, getUserPlaylists, getUserToken, getUserTracks, getUserWebProfiles, likePlaylist, likeTrack, paginate, paginateItems, refreshUserToken, repostPlaylist, repostTrack, resolveUrl, scFetch, scFetchUrl, searchPlaylists, searchTracks, searchUsers, signOut, unfollowUser, unlikePlaylist, unlikeTrack, unrepostPlaylist, unrepostTrack, updatePlaylist, updateTrack } from './chunk-QNL6UJL5.mjs';
1
+ export { IMPLEMENTED_OPERATIONS, InFlightDeduper, RawClient, SoundCloudClient, createPlaylist, createTrackComment, deletePlaylist, deleteTrack, fetchAll, followUser, generateCodeChallenge, generateCodeVerifier, getAuthorizationUrl, getClientToken, getFollowers, getFollowings, getMe, getMeActivities, getMeActivitiesOwn, getMeActivitiesTracks, getMeConnections, getMeFollowers, getMeFollowings, getMeFollowingsTracks, getMeLikesPlaylists, getMeLikesTracks, getMePlaylists, getMeTracks, getPlaylist, getPlaylistReposts, getPlaylistTracks, getRelatedTracks, getSoundCloudWidgetUrl, getTrack, getTrackComments, getTrackLikes, getTrackReposts, getTrackStreams, getTracks, getUser, getUserLikesPlaylists, getUserLikesTracks, getUserPlaylists, getUserToken, getUserTracks, getUserWebProfiles, likePlaylist, likeTrack, paginate, paginateItems, refreshUserToken, repostPlaylist, repostTrack, resolveUrl, scFetch, scFetchUrl, searchPlaylists, searchTracks, searchUsers, signOut, unfollowUser, unlikePlaylist, unlikeTrack, unrepostPlaylist, unrepostTrack, updatePlaylist, updateTrack } from './chunk-4FNI5QIN.mjs';
2
2
  export { SoundCloudError } from './chunk-QYYEWUIJ.mjs';
3
3
  //# sourceMappingURL=index.mjs.map
4
4
  //# sourceMappingURL=index.mjs.map
package/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # soundcloud-api-ts v1.13.2
1
+ # soundcloud-api-ts v1.14.0
2
2
 
3
3
  > A TypeScript client for the SoundCloud API. Zero dependencies, native fetch, full OAuth 2.1 + PKCE support via `secure.soundcloud.com`.
4
4
 
@@ -39,7 +39,7 @@ Paginated responses return `SoundCloudPaginatedResponse<T>` with `collection: T[
39
39
  refreshUserToken(refreshToken: string): Promise<SoundCloudToken>
40
40
  signOut(accessToken: string): Promise<void>
41
41
 
42
- > **Note (v1.13.2+)**: All token endpoints (`client_credentials`, `refresh_token`, `authorization_code`) send `client_id` and `client_secret` in the request body, not via `Authorization: Basic`. SoundCloud rejects Basic Auth on `/oauth/token` with 403/400 as of early 2026.
42
+ > **Note (v1.13.3+)**: SoundCloud's `/oauth/token` requirements differ **per grant type**: `client_credentials` requires `Authorization: Basic` (body credentials return `401 invalid_client`), while `refresh_token` and `authorization_code` require `client_id`/`client_secret` in the request body. `getClientToken` sends Basic Auth; `refreshUserToken`/`getUserToken` send body credentials. (v1.13.2 briefly used body credentials for all grants reversed for `client_credentials` in v1.13.3.)
43
43
 
44
44
  ### PKCE Helpers (standalone exports)
45
45
 
@@ -49,7 +49,7 @@ Paginated responses return `SoundCloudPaginatedResponse<T>` with `collection: T[
49
49
  ### Tracks (sc.tracks)
50
50
 
51
51
  getTrack(trackId: string | number): Promise<SoundCloudTrack>
52
- getTracks(ids: (string | number)[]): Promise<SoundCloudTrack[]> // batch fetch by IDs
52
+ getTracks(ids: (string | number)[]): Promise<SoundCloudTrack[]> // batch fetch by IDs; max 200 (throws above)
53
53
  getStreams(trackId: string | number): Promise<SoundCloudStreams>
54
54
  getComments(trackId: string | number, limit?: number): Promise<SoundCloudPaginatedResponse<SoundCloudComment>>
55
55
  createComment(trackId: string | number, body: string, timestamp?: number): Promise<SoundCloudComment>
@@ -202,7 +202,7 @@ const sc = new SoundCloudClient({
202
202
  });
203
203
  ```
204
204
 
205
- `SCRequestTelemetry`: `{ method, path, durationMs, status, retryCount, error? }` — fires after every request including pagination and retries.
205
+ `SCRequestTelemetry`: `{ method, path, durationMs, status, retryCount, error? }` — fires after every client-namespace request including pagination and retries. Not emitted for `sc.raw.*` or `auth.signOut`.
206
206
 
207
207
  ## Raw API
208
208
  ```ts
@@ -223,16 +223,16 @@ const sc = new SoundCloudClient({
223
223
  });
224
224
  ```
225
225
  `SoundCloudCache`: `{ get<T>(key): T|undefined; set<T>(key, value, {ttlMs}): void; delete(key): void }`
226
+ Applies to GETs made through the client namespaces. `sc.raw.*` and pagination `next_href` fetches are not deduped/cached. (Note: these options existed but were not wired up in v1.12.0–v1.13.4.)
226
227
 
227
228
  ## Fetch Injection & Runtime Portability
228
229
  ```ts
229
230
  const sc = new SoundCloudClient({
230
231
  clientId: '...', clientSecret: '...',
231
- fetch: customFetch, // custom fetch implementation
232
- AbortController: customAbort, // custom AbortController
232
+ fetch: customFetch, // custom fetch implementation (defaults to globalThis.fetch)
233
233
  });
234
234
  ```
235
- No Node-only APIs. Works in Cloudflare Workers, Bun, Deno, Edge runtimes.
235
+ No Node-only APIs. Works in Cloudflare Workers, Bun, Deno, Edge runtimes. There is no `AbortController` config option — pass a pre-wired `fetch` if you need cancellation/timeouts.
236
236
 
237
237
  ## Retry Hook
238
238
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "soundcloud-api-ts",
3
- "version": "1.13.3",
3
+ "version": "1.14.0",
4
4
  "description": "TypeScript-first SoundCloud API client for accessing tracks, users, playlists, and search endpoints. Zero dependencies, native fetch, full OAuth 2.1 + PKCE support.",
5
5
  "bin": {
6
6
  "sc-cli": "./dist/cli.js",
@@ -61,9 +61,15 @@
61
61
  "node"
62
62
  ],
63
63
  "license": "MIT",
64
+ "packageManager": "pnpm@10.23.0",
64
65
  "engines": {
65
66
  "node": ">=20"
66
67
  },
68
+ "pnpm": {
69
+ "onlyBuiltDependencies": [
70
+ "esbuild"
71
+ ]
72
+ },
67
73
  "devDependencies": {
68
74
  "@types/node": "^25.2.3",
69
75
  "@typescript-eslint/eslint-plugin": "^8.55.0",