soundcloud-api-ts 1.9.3 → 1.10.1

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 CHANGED
@@ -55,7 +55,7 @@ Unlike legacy JavaScript SoundCloud SDKs and community wrappers that require sep
55
55
 
56
56
  > **Why does auth method matter?** `soundcloud.ts` and `soundcloud-fetch` use SoundCloud's undocumented internal `api-v2` and require you to scrape your client ID from browser dev tools. This can break anytime SoundCloud changes their frontend, and may violate the [API Terms of Use](https://developers.soundcloud.com/docs/api/terms-of-use) which state *"you must register your app"* and *"any attempt to circumvent this and obtain a new client ID and Security Code is strictly prohibited."*
57
57
  >
58
- > `soundcloud-api-ts` uses the **official documented API** (`api.soundcloud.com`) with registered app credentials, OAuth 2.1 as specified by SoundCloud, PKCE for public clients, and automatic token refresh.
58
+ > `soundcloud-api-ts` uses the **official documented API** (`api.soundcloud.com`) with registered app credentials, OAuth 2.1 via `secure.soundcloud.com` as specified by SoundCloud, PKCE for public clients, and automatic token refresh.
59
59
 
60
60
  **Coming from `soundcloud.ts`?** See the [Migration Guide](docs/MIGRATING.md) — most changes are find-and-replace.
61
61
 
@@ -427,7 +427,7 @@ const sc = new SoundCloudClient({
427
427
 
428
428
  This package is built on SoundCloud's **official documented API** (`api.soundcloud.com`) and follows the [API Terms of Use](https://developers.soundcloud.com/docs/api/terms-of-use):
429
429
 
430
- - ✅ Uses registered app credentials (client ID + client secret) via OAuth 2.1
430
+ - ✅ Uses registered app credentials (client ID + client secret) via OAuth 2.1 on `secure.soundcloud.com`
431
431
  - ✅ No undocumented or internal API endpoints (`api-v2`)
432
432
  - ✅ No client ID scraping or credential circumvention
433
433
  - ✅ No content downloading, ripping, or stream capture
@@ -55,5 +55,5 @@ var SoundCloudError = class extends Error {
55
55
  };
56
56
 
57
57
  exports.SoundCloudError = SoundCloudError;
58
- //# sourceMappingURL=chunk-NBKG62HR.js.map
59
- //# sourceMappingURL=chunk-NBKG62HR.js.map
58
+ //# sourceMappingURL=chunk-MLVA534Z.js.map
59
+ //# sourceMappingURL=chunk-MLVA534Z.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts"],"names":[],"mappings":";AA6DO,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA;AAAA,EAEhC,MAAA;AAAA;AAAA,EAEA,UAAA;AAAA;AAAA,EAEA,SAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,WAAA,CAAY,MAAA,EAAgB,UAAA,EAAoB,IAAA,EAA4B;AAE1E,IAAA,MAAM,MACJ,IAAA,EAAM,OAAA,IACN,IAAA,EAAM,iBAAA,IACN,MAAM,UAAA,IACN,IAAA,EAAM,MAAA,GAAS,CAAC,GAAG,aAAA,IACnB,IAAA,EAAM,SACN,CAAA,EAAG,MAAM,IAAI,UAAU,CAAA,CAAA;AAEzB,IAAA,KAAA,CAAM,GAAG,CAAA;AACT,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,SAAA,GAAY,MAAM,UAAA,IAAc,MAAA;AACrC,IAAA,IAAA,CAAK,QAAA,GAAW,MAAM,IAAA,IAAQ,MAAA;AAC9B,IAAA,IAAA,CAAK,SACH,IAAA,EAAM,MAAA,EACF,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,aAAa,CAAA,CAC3B,MAAA,CAAO,CAAC,CAAA,KAAmB,CAAC,CAAC,CAAC,KAAK,EAAC;AACzC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,cAAA,GAA0B;AAC5B,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,WAAA,GAAuB;AACzB,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,UAAA,GAAsB;AACxB,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,aAAA,GAAyB;AAC3B,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,aAAA,GAAyB;AAC3B,IAAA,OAAO,IAAA,CAAK,MAAA,IAAU,GAAA,IAAO,IAAA,CAAK,MAAA,GAAS,GAAA;AAAA,EAC7C;AACF","file":"chunk-CYDTNVV3.mjs","sourcesContent":["/**\n * Shape of error response bodies returned by the SoundCloud API.\n *\n * The API returns varying combinations of these fields depending on the endpoint\n * and error type. All fields are optional.\n *\n * @example\n * ```json\n * {\n * \"code\": 401,\n * \"message\": \"invalid_client\",\n * \"link\": \"https://developers.soundcloud.com/docs/api/explorer/open-api\",\n * \"status\": \"401 - Unauthorized\",\n * \"errors\": [{\"error_message\": \"invalid_client\"}],\n * \"error\": null,\n * \"error_code\": \"invalid_client\"\n * }\n * ```\n *\n * @see https://developers.soundcloud.com/docs/api/explorer/open-api\n */\nexport interface SoundCloudErrorBody {\n /** HTTP status code echoed in the response body */\n code?: number;\n /** Error message from SoundCloud (e.g. \"invalid_client\", \"404 - Not Found\") */\n message?: string;\n /** Human-readable status string (e.g. \"401 - Unauthorized\") */\n status?: string;\n /** Link to SoundCloud API documentation */\n link?: string;\n /** Array of individual error detail objects */\n errors?: Array<{ error_message?: string }>;\n /** Generic error field — typically null in SoundCloud responses */\n error?: string | null;\n /** Machine-readable error code (e.g. \"invalid_client\") */\n error_code?: string;\n /** OAuth error description, present in `/oauth2/token` error responses */\n error_description?: string;\n}\n\n/**\n * Error class thrown when a SoundCloud API request fails.\n *\n * Provides structured access to HTTP status, error codes, and convenience\n * getters for common error categories.\n *\n * @example\n * ```ts\n * import { SoundCloudError } from 'soundcloud-api-ts';\n *\n * try {\n * await sc.tracks.getTrack(999999999);\n * } catch (err) {\n * if (err instanceof SoundCloudError) {\n * if (err.isNotFound) console.log('Track not found');\n * if (err.isRateLimited) console.log('Rate limited, retry later');\n * console.log(err.status, err.message);\n * }\n * }\n * ```\n */\nexport class SoundCloudError extends Error {\n /** HTTP status code of the failed response (e.g. 401, 404, 429) */\n readonly status: number;\n /** HTTP status text of the failed response (e.g. \"Unauthorized\", \"Not Found\") */\n readonly statusText: string;\n /** Machine-readable error code from SoundCloud (e.g. \"invalid_client\"), if present */\n readonly errorCode?: string;\n /** Link to SoundCloud API documentation, if included in the error response */\n readonly docsLink?: string;\n /** Individual error messages extracted from the response body's `errors` array */\n readonly errors: string[];\n /** The full parsed error response body, if available */\n readonly body?: SoundCloudErrorBody;\n\n /**\n * Creates a new SoundCloudError.\n *\n * @param status - HTTP status code\n * @param statusText - HTTP status text\n * @param body - Parsed JSON error response body from SoundCloud, if available\n */\n constructor(status: number, statusText: string, body?: SoundCloudErrorBody) {\n // Build the most useful message we can from SC's response\n const msg =\n body?.message ||\n body?.error_description ||\n body?.error_code ||\n body?.errors?.[0]?.error_message ||\n body?.error ||\n `${status} ${statusText}`;\n\n super(msg);\n this.name = \"SoundCloudError\";\n this.status = status;\n this.statusText = statusText;\n this.errorCode = body?.error_code ?? undefined;\n this.docsLink = body?.link ?? undefined;\n this.errors =\n body?.errors\n ?.map((e) => e.error_message)\n .filter((m): m is string => !!m) ?? [];\n this.body = body;\n }\n\n /** True if status is 401 Unauthorized (invalid or expired token) */\n get isUnauthorized(): boolean {\n return this.status === 401;\n }\n\n /** True if status is 403 Forbidden (insufficient permissions) */\n get isForbidden(): boolean {\n return this.status === 403;\n }\n\n /** True if status is 404 Not Found (resource does not exist) */\n get isNotFound(): boolean {\n return this.status === 404;\n }\n\n /** True if status is 429 Too Many Requests (rate limit exceeded) */\n get isRateLimited(): boolean {\n return this.status === 429;\n }\n\n /** True if status is 5xx (SoundCloud server error) */\n get isServerError(): boolean {\n return this.status >= 500 && this.status < 600;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts"],"names":[],"mappings":";;;AA6DO,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA;AAAA,EAEhC,MAAA;AAAA;AAAA,EAEA,UAAA;AAAA;AAAA,EAEA,SAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,WAAA,CAAY,MAAA,EAAgB,UAAA,EAAoB,IAAA,EAA4B;AAE1E,IAAA,MAAM,MACJ,IAAA,EAAM,OAAA,IACN,IAAA,EAAM,iBAAA,IACN,MAAM,UAAA,IACN,IAAA,EAAM,MAAA,GAAS,CAAC,GAAG,aAAA,IACnB,IAAA,EAAM,SACN,CAAA,EAAG,MAAM,IAAI,UAAU,CAAA,CAAA;AAEzB,IAAA,KAAA,CAAM,GAAG,CAAA;AACT,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,SAAA,GAAY,MAAM,UAAA,IAAc,MAAA;AACrC,IAAA,IAAA,CAAK,QAAA,GAAW,MAAM,IAAA,IAAQ,MAAA;AAC9B,IAAA,IAAA,CAAK,SACH,IAAA,EAAM,MAAA,EACF,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,aAAa,CAAA,CAC3B,MAAA,CAAO,CAAC,CAAA,KAAmB,CAAC,CAAC,CAAC,KAAK,EAAC;AACzC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,cAAA,GAA0B;AAC5B,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,WAAA,GAAuB;AACzB,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,UAAA,GAAsB;AACxB,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,aAAA,GAAyB;AAC3B,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,aAAA,GAAyB;AAC3B,IAAA,OAAO,IAAA,CAAK,MAAA,IAAU,GAAA,IAAO,IAAA,CAAK,MAAA,GAAS,GAAA;AAAA,EAC7C;AACF","file":"chunk-MLVA534Z.js","sourcesContent":["/**\n * Shape of error response bodies returned by the SoundCloud API.\n *\n * The API returns varying combinations of these fields depending on the endpoint\n * and error type. All fields are optional.\n *\n * @example\n * ```json\n * {\n * \"code\": 401,\n * \"message\": \"invalid_client\",\n * \"link\": \"https://developers.soundcloud.com/docs/api/explorer/open-api\",\n * \"status\": \"401 - Unauthorized\",\n * \"errors\": [{\"error_message\": \"invalid_client\"}],\n * \"error\": null,\n * \"error_code\": \"invalid_client\"\n * }\n * ```\n *\n * @see https://developers.soundcloud.com/docs/api/explorer/open-api\n */\nexport interface SoundCloudErrorBody {\n /** HTTP status code echoed in the response body */\n code?: number;\n /** Error message from SoundCloud (e.g. \"invalid_client\", \"404 - Not Found\") */\n message?: string;\n /** Human-readable status string (e.g. \"401 - Unauthorized\") */\n status?: string;\n /** Link to SoundCloud API documentation */\n link?: string;\n /** Array of individual error detail objects */\n errors?: Array<{ error_message?: string }>;\n /** Generic error field — typically null in SoundCloud responses */\n error?: string | null;\n /** Machine-readable error code (e.g. \"invalid_client\") */\n error_code?: string;\n /** OAuth error description, present in `/oauth/token` error responses */\n error_description?: string;\n}\n\n/**\n * Error class thrown when a SoundCloud API request fails.\n *\n * Provides structured access to HTTP status, error codes, and convenience\n * getters for common error categories.\n *\n * @example\n * ```ts\n * import { SoundCloudError } from 'soundcloud-api-ts';\n *\n * try {\n * await sc.tracks.getTrack(999999999);\n * } catch (err) {\n * if (err instanceof SoundCloudError) {\n * if (err.isNotFound) console.log('Track not found');\n * if (err.isRateLimited) console.log('Rate limited, retry later');\n * console.log(err.status, err.message);\n * }\n * }\n * ```\n */\nexport class SoundCloudError extends Error {\n /** HTTP status code of the failed response (e.g. 401, 404, 429) */\n readonly status: number;\n /** HTTP status text of the failed response (e.g. \"Unauthorized\", \"Not Found\") */\n readonly statusText: string;\n /** Machine-readable error code from SoundCloud (e.g. \"invalid_client\"), if present */\n readonly errorCode?: string;\n /** Link to SoundCloud API documentation, if included in the error response */\n readonly docsLink?: string;\n /** Individual error messages extracted from the response body's `errors` array */\n readonly errors: string[];\n /** The full parsed error response body, if available */\n readonly body?: SoundCloudErrorBody;\n\n /**\n * Creates a new SoundCloudError.\n *\n * @param status - HTTP status code\n * @param statusText - HTTP status text\n * @param body - Parsed JSON error response body from SoundCloud, if available\n */\n constructor(status: number, statusText: string, body?: SoundCloudErrorBody) {\n // Build the most useful message we can from SC's response\n const msg =\n body?.message ||\n body?.error_description ||\n body?.error_code ||\n body?.errors?.[0]?.error_message ||\n body?.error ||\n `${status} ${statusText}`;\n\n super(msg);\n this.name = \"SoundCloudError\";\n this.status = status;\n this.statusText = statusText;\n this.errorCode = body?.error_code ?? undefined;\n this.docsLink = body?.link ?? undefined;\n this.errors =\n body?.errors\n ?.map((e) => e.error_message)\n .filter((m): m is string => !!m) ?? [];\n this.body = body;\n }\n\n /** True if status is 401 Unauthorized (invalid or expired token) */\n get isUnauthorized(): boolean {\n return this.status === 401;\n }\n\n /** True if status is 403 Forbidden (insufficient permissions) */\n get isForbidden(): boolean {\n return this.status === 403;\n }\n\n /** True if status is 404 Not Found (resource does not exist) */\n get isNotFound(): boolean {\n return this.status === 404;\n }\n\n /** True if status is 429 Too Many Requests (rate limit exceeded) */\n get isRateLimited(): boolean {\n return this.status === 429;\n }\n\n /** True if status is 5xx (SoundCloud server error) */\n get isServerError(): boolean {\n return this.status >= 500 && this.status < 600;\n }\n}\n"]}
@@ -53,5 +53,5 @@ var SoundCloudError = class extends Error {
53
53
  };
54
54
 
55
55
  export { SoundCloudError };
56
- //# sourceMappingURL=chunk-CYDTNVV3.mjs.map
57
- //# sourceMappingURL=chunk-CYDTNVV3.mjs.map
56
+ //# sourceMappingURL=chunk-QYYEWUIJ.mjs.map
57
+ //# sourceMappingURL=chunk-QYYEWUIJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts"],"names":[],"mappings":";AA6DO,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA;AAAA,EAEhC,MAAA;AAAA;AAAA,EAEA,UAAA;AAAA;AAAA,EAEA,SAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,WAAA,CAAY,MAAA,EAAgB,UAAA,EAAoB,IAAA,EAA4B;AAE1E,IAAA,MAAM,MACJ,IAAA,EAAM,OAAA,IACN,IAAA,EAAM,iBAAA,IACN,MAAM,UAAA,IACN,IAAA,EAAM,MAAA,GAAS,CAAC,GAAG,aAAA,IACnB,IAAA,EAAM,SACN,CAAA,EAAG,MAAM,IAAI,UAAU,CAAA,CAAA;AAEzB,IAAA,KAAA,CAAM,GAAG,CAAA;AACT,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,SAAA,GAAY,MAAM,UAAA,IAAc,MAAA;AACrC,IAAA,IAAA,CAAK,QAAA,GAAW,MAAM,IAAA,IAAQ,MAAA;AAC9B,IAAA,IAAA,CAAK,SACH,IAAA,EAAM,MAAA,EACF,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,aAAa,CAAA,CAC3B,MAAA,CAAO,CAAC,CAAA,KAAmB,CAAC,CAAC,CAAC,KAAK,EAAC;AACzC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,cAAA,GAA0B;AAC5B,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,WAAA,GAAuB;AACzB,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,UAAA,GAAsB;AACxB,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,aAAA,GAAyB;AAC3B,IAAA,OAAO,KAAK,MAAA,KAAW,GAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,aAAA,GAAyB;AAC3B,IAAA,OAAO,IAAA,CAAK,MAAA,IAAU,GAAA,IAAO,IAAA,CAAK,MAAA,GAAS,GAAA;AAAA,EAC7C;AACF","file":"chunk-QYYEWUIJ.mjs","sourcesContent":["/**\n * Shape of error response bodies returned by the SoundCloud API.\n *\n * The API returns varying combinations of these fields depending on the endpoint\n * and error type. All fields are optional.\n *\n * @example\n * ```json\n * {\n * \"code\": 401,\n * \"message\": \"invalid_client\",\n * \"link\": \"https://developers.soundcloud.com/docs/api/explorer/open-api\",\n * \"status\": \"401 - Unauthorized\",\n * \"errors\": [{\"error_message\": \"invalid_client\"}],\n * \"error\": null,\n * \"error_code\": \"invalid_client\"\n * }\n * ```\n *\n * @see https://developers.soundcloud.com/docs/api/explorer/open-api\n */\nexport interface SoundCloudErrorBody {\n /** HTTP status code echoed in the response body */\n code?: number;\n /** Error message from SoundCloud (e.g. \"invalid_client\", \"404 - Not Found\") */\n message?: string;\n /** Human-readable status string (e.g. \"401 - Unauthorized\") */\n status?: string;\n /** Link to SoundCloud API documentation */\n link?: string;\n /** Array of individual error detail objects */\n errors?: Array<{ error_message?: string }>;\n /** Generic error field — typically null in SoundCloud responses */\n error?: string | null;\n /** Machine-readable error code (e.g. \"invalid_client\") */\n error_code?: string;\n /** OAuth error description, present in `/oauth/token` error responses */\n error_description?: string;\n}\n\n/**\n * Error class thrown when a SoundCloud API request fails.\n *\n * Provides structured access to HTTP status, error codes, and convenience\n * getters for common error categories.\n *\n * @example\n * ```ts\n * import { SoundCloudError } from 'soundcloud-api-ts';\n *\n * try {\n * await sc.tracks.getTrack(999999999);\n * } catch (err) {\n * if (err instanceof SoundCloudError) {\n * if (err.isNotFound) console.log('Track not found');\n * if (err.isRateLimited) console.log('Rate limited, retry later');\n * console.log(err.status, err.message);\n * }\n * }\n * ```\n */\nexport class SoundCloudError extends Error {\n /** HTTP status code of the failed response (e.g. 401, 404, 429) */\n readonly status: number;\n /** HTTP status text of the failed response (e.g. \"Unauthorized\", \"Not Found\") */\n readonly statusText: string;\n /** Machine-readable error code from SoundCloud (e.g. \"invalid_client\"), if present */\n readonly errorCode?: string;\n /** Link to SoundCloud API documentation, if included in the error response */\n readonly docsLink?: string;\n /** Individual error messages extracted from the response body's `errors` array */\n readonly errors: string[];\n /** The full parsed error response body, if available */\n readonly body?: SoundCloudErrorBody;\n\n /**\n * Creates a new SoundCloudError.\n *\n * @param status - HTTP status code\n * @param statusText - HTTP status text\n * @param body - Parsed JSON error response body from SoundCloud, if available\n */\n constructor(status: number, statusText: string, body?: SoundCloudErrorBody) {\n // Build the most useful message we can from SC's response\n const msg =\n body?.message ||\n body?.error_description ||\n body?.error_code ||\n body?.errors?.[0]?.error_message ||\n body?.error ||\n `${status} ${statusText}`;\n\n super(msg);\n this.name = \"SoundCloudError\";\n this.status = status;\n this.statusText = statusText;\n this.errorCode = body?.error_code ?? undefined;\n this.docsLink = body?.link ?? undefined;\n this.errors =\n body?.errors\n ?.map((e) => e.error_message)\n .filter((m): m is string => !!m) ?? [];\n this.body = body;\n }\n\n /** True if status is 401 Unauthorized (invalid or expired token) */\n get isUnauthorized(): boolean {\n return this.status === 401;\n }\n\n /** True if status is 403 Forbidden (insufficient permissions) */\n get isForbidden(): boolean {\n return this.status === 403;\n }\n\n /** True if status is 404 Not Found (resource does not exist) */\n get isNotFound(): boolean {\n return this.status === 404;\n }\n\n /** True if status is 429 Too Many Requests (rate limit exceeded) */\n get isRateLimited(): boolean {\n return this.status === 429;\n }\n\n /** True if status is 5xx (SoundCloud server error) */\n get isServerError(): boolean {\n return this.status >= 500 && this.status < 600;\n }\n}\n"]}
@@ -1,7 +1,8 @@
1
- import { SoundCloudError } from './chunk-CYDTNVV3.mjs';
1
+ import { SoundCloudError } from './chunk-QYYEWUIJ.mjs';
2
2
 
3
3
  // src/client/http.ts
4
4
  var BASE_URL = "https://api.soundcloud.com";
5
+ var AUTH_BASE_URL = "https://secure.soundcloud.com";
5
6
  var DEFAULT_RETRY = { maxRetries: 3, retryBaseDelay: 1e3 };
6
7
  function delay(ms) {
7
8
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -30,7 +31,8 @@ async function parseErrorBody(response) {
30
31
  async function scFetch(options, refreshCtx) {
31
32
  const retryConfig = refreshCtx?.retry ?? DEFAULT_RETRY;
32
33
  const execute = async (tokenOverride) => {
33
- const url = `${BASE_URL}${options.path}`;
34
+ const isAuthPath = options.path.startsWith("/oauth");
35
+ const url = `${isAuthPath ? AUTH_BASE_URL : BASE_URL}${options.path}`;
34
36
  const headers = {
35
37
  Accept: "application/json"
36
38
  };
@@ -336,7 +338,7 @@ var SoundCloudClient = class _SoundCloudClient {
336
338
  params.set("code_challenge", options.codeChallenge);
337
339
  params.set("code_challenge_method", "S256");
338
340
  }
339
- return `https://api.soundcloud.com/connect?${params}`;
341
+ return `https://secure.soundcloud.com/authorize?${params}`;
340
342
  }
341
343
  /**
342
344
  * Exchange client credentials for an access token (machine-to-machine auth).
@@ -354,7 +356,7 @@ var SoundCloudClient = class _SoundCloudClient {
354
356
  */
355
357
  async getClientToken() {
356
358
  return scFetch({
357
- path: "/oauth2/token",
359
+ path: "/oauth/token",
358
360
  method: "POST",
359
361
  body: new URLSearchParams({
360
362
  grant_type: "client_credentials",
@@ -389,7 +391,7 @@ var SoundCloudClient = class _SoundCloudClient {
389
391
  };
390
392
  if (codeVerifier) params.code_verifier = codeVerifier;
391
393
  return scFetch({
392
- path: "/oauth2/token",
394
+ path: "/oauth/token",
393
395
  method: "POST",
394
396
  body: new URLSearchParams(params)
395
397
  });
@@ -411,7 +413,7 @@ var SoundCloudClient = class _SoundCloudClient {
411
413
  */
412
414
  async refreshUserToken(refreshToken) {
413
415
  return scFetch({
414
- path: "/oauth2/token",
416
+ path: "/oauth/token",
415
417
  method: "POST",
416
418
  body: new URLSearchParams({
417
419
  grant_type: "refresh_token",
@@ -1391,7 +1393,7 @@ var SoundCloudClient = class _SoundCloudClient {
1391
1393
  // src/auth/getClientToken.ts
1392
1394
  var getClientToken = (clientId, clientSecret) => {
1393
1395
  return scFetch({
1394
- path: "/oauth2/token",
1396
+ path: "/oauth/token",
1395
1397
  method: "POST",
1396
1398
  body: new URLSearchParams({
1397
1399
  grant_type: "client_credentials",
@@ -1412,7 +1414,7 @@ var getUserToken = (clientId, clientSecret, redirectUri, code, codeVerifier) =>
1412
1414
  };
1413
1415
  if (codeVerifier) params.code_verifier = codeVerifier;
1414
1416
  return scFetch({
1415
- path: "/oauth2/token",
1417
+ path: "/oauth/token",
1416
1418
  method: "POST",
1417
1419
  body: new URLSearchParams(params)
1418
1420
  });
@@ -1421,7 +1423,7 @@ var getUserToken = (clientId, clientSecret, redirectUri, code, codeVerifier) =>
1421
1423
  // src/auth/refreshUserToken.ts
1422
1424
  var refreshUserToken = (clientId, clientSecret, redirectUri, refreshToken) => {
1423
1425
  return scFetch({
1424
- path: "/oauth2/token",
1426
+ path: "/oauth/token",
1425
1427
  method: "POST",
1426
1428
  body: new URLSearchParams({
1427
1429
  grant_type: "refresh_token",
@@ -1455,7 +1457,7 @@ function getAuthorizationUrl(clientId, redirectUri, options) {
1455
1457
  params.set("code_challenge", options.codeChallenge);
1456
1458
  params.set("code_challenge_method", "S256");
1457
1459
  }
1458
- return `https://api.soundcloud.com/connect?${params}`;
1460
+ return `https://secure.soundcloud.com/authorize?${params}`;
1459
1461
  }
1460
1462
 
1461
1463
  // src/auth/pkce.ts
@@ -1679,5 +1681,5 @@ var unrepostPlaylist = async (token, playlistId) => {
1679
1681
  var getSoundCloudWidgetUrl = (trackId) => `https%3A//api.soundcloud.com/tracks/${trackId}&show_teaser=false&color=%2300a99d&inverse=false&show_user=false&sharing=false&buying=false&liking=false&show_artwork=false&show_name=false`;
1680
1682
 
1681
1683
  export { SoundCloudClient, createPlaylist, createTrackComment, deletePlaylist, deleteTrack, fetchAll, followUser, generateCodeChallenge, generateCodeVerifier, getAuthorizationUrl, getClientToken, getFollowers, getFollowings, getMe, getMeActivities, getMeActivitiesOwn, getMeActivitiesTracks, getMeFollowers, getMeFollowings, getMeFollowingsTracks, getMeLikesPlaylists, getMeLikesTracks, getMePlaylists, getMeTracks, getPlaylist, getPlaylistReposts, getPlaylistTracks, getRelatedTracks, getSoundCloudWidgetUrl, getTrack, getTrackComments, getTrackLikes, getTrackReposts, getTrackStreams, 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 };
1682
- //# sourceMappingURL=chunk-G6S6GM75.mjs.map
1683
- //# sourceMappingURL=chunk-G6S6GM75.mjs.map
1684
+ //# sourceMappingURL=chunk-RETVFKZM.mjs.map
1685
+ //# sourceMappingURL=chunk-RETVFKZM.mjs.map