@remcostoeten/fync
Version:
A unified TypeScript library for easy access to popular APIs (GitHub, Spotify, GitLab, etc.)
99 lines • 3.79 kB
JavaScript
export const SPOTIFY_SCOPES = {
PLAYLIST_READ_PRIVATE: "playlist-read-private",
PLAYLIST_READ_COLLABORATIVE: "playlist-read-collaborative",
PLAYLIST_MODIFY_PUBLIC: "playlist-modify-public",
PLAYLIST_MODIFY_PRIVATE: "playlist-modify-private",
USER_READ_PRIVATE: "user-read-private",
USER_READ_EMAIL: "user-read-email",
USER_READ_PLAYBACK_STATE: "user-read-playback-state",
USER_MODIFY_PLAYBACK_STATE: "user-modify-playback-state",
USER_READ_CURRENTLY_PLAYING: "user-read-currently-playing",
USER_READ_RECENTLY_PLAYED: "user-read-recently-played",
USER_TOP_READ: "user-top-read",
USER_LIBRARY_READ: "user-library-read",
USER_LIBRARY_MODIFY: "user-library-modify",
USER_FOLLOW_READ: "user-follow-read",
USER_FOLLOW_MODIFY: "user-follow-modify",
STREAMING: "streaming",
};
export function createSpotifyAuth(config) {
const baseUrl = config.baseUrl || "https://accounts.spotify.com";
const userAgent = config.userAgent || "Fync Spotify Client";
function getAuthorizationUrl(scopes, state) {
const params = new URLSearchParams({
response_type: "code",
client_id: config.clientId,
scope: scopes.join(" "),
redirect_uri: config.redirectUri || "",
...(state && { state }),
});
return `${baseUrl}/authorize?${params.toString()}`;
}
async function exchangeCodeForToken(code, _state) {
const params = new URLSearchParams({
grant_type: "authorization_code",
code,
redirect_uri: config.redirectUri || "",
client_id: config.clientId,
client_secret: config.clientSecret,
});
const response = await fetch(`${baseUrl}/api/token`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": userAgent,
},
body: params.toString(),
});
if (!response.ok) {
const error = (await response.json());
throw new Error(`Spotify OAuth error: ${error.error_description || error.error}`);
}
const data = (await response.json());
return {
...data,
created_at: Math.floor(Date.now() / 1000),
};
}
async function refreshAccessToken(refreshToken) {
const params = new URLSearchParams({
grant_type: "refresh_token",
refresh_token: refreshToken,
client_id: config.clientId,
client_secret: config.clientSecret,
});
const response = await fetch(`${baseUrl}/api/token`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": userAgent,
},
body: params.toString(),
});
if (!response.ok) {
const error = (await response.json());
throw new Error(`Spotify token refresh error: ${error.error_description || error.error}`);
}
const data = (await response.json());
return {
...data,
created_at: Math.floor(Date.now() / 1000),
};
}
return {
getAuthorizationUrl,
exchangeCodeForToken,
refreshAccessToken,
};
}
export function isTokenExpired(token, bufferSeconds = 300) {
if (!token.created_at)
return true;
const expiresAt = token.created_at + token.expires_in;
const now = Math.floor(Date.now() / 1000);
return now >= expiresAt - bufferSeconds;
}
export function shouldRefreshToken(token, bufferSeconds = 300) {
return isTokenExpired(token, bufferSeconds) && !!token.refresh_token;
}
//# sourceMappingURL=index.js.map