Skip to content

fix: return correct types instead of casting with as #116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/SpotifyApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ export class SpotifyApi {
this.authenticationStrategy.setConfiguration(this.sdkConfig);
}

public async makeRequest<TReturnType>(method: "GET" | "POST" | "PUT" | "DELETE", url: string, body: any = undefined, contentType: string | undefined = undefined): Promise<TReturnType> {
public async makeRequest<TReturnType>(method: "GET" | "POST" | "PUT" | "DELETE", url: string, body: any = undefined, contentType: string | undefined = undefined): Promise<TReturnType|null> {
try {
const accessToken = await this.authenticationStrategy.getOrCreateAccessToken();
if (isEmptyAccessToken(accessToken)) {
console.warn("No access token found, authenticating now.");
return null as TReturnType;
return null;
}

const token = accessToken?.access_token;
Expand All @@ -99,7 +99,7 @@ export class SpotifyApi {
this.sdkConfig.afterRequest(fullUrl, opts, result);

if (result.status === 204) {
return null as TReturnType;
return null;
}

await this.sdkConfig.responseValidator.validateResponse(result);
Expand All @@ -109,7 +109,7 @@ export class SpotifyApi {
if (!handled) {
throw error;
}
return null as TReturnType;
return null;
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/auth/ClientCredentialsStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ export default class ClientCredentialsStrategy implements IAuthStrategy {
}

private async getTokenFromApi(): Promise<AccessToken> {
const options = {
const options: Record<string,string> = {
grant_type: 'client_credentials',
scope: this.scopes.join(' ')
} as any;
};

const bodyAsString = Object.keys(options).map(key => key + '=' + options[key]).join('&');
const hasBuffer = typeof Buffer !== 'undefined';
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/AlbumsEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default class AlbumsEndpoints extends EndpointsBase {
const params = this.paramsFor({ ids: idOrIds, market });
// TODO: only returns top 20, validate here
const response = await this.getRequest<Albums>(`albums${params}`);
return response.albums;
return response?.albums;
}

public tracks(albumId: string, market?: Market, limit?: MaxInt<50>, offset?: number) {
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/ArtistsEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default class ArtistsEndpoints extends EndpointsBase {

const params = this.paramsFor({ ids: idOrIds });
const response = await this.getRequest<Artists>(`artists${params}`);
return response.artists;
return response?.artists;
}

public albums(
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/AudiobooksEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default class AudiobooksEndpoints extends EndpointsBase {

const params = this.paramsFor({ ids: idOrIds, market });
const response = await this.getRequest<Audiobooks>(`audiobooks${params}`);
return response.audiobooks;
return response?.audiobooks;
}

public getAudiobookChapters(id: string, market?: Market, limit?: MaxInt<50>, offset?: number) {
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/ChaptersEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ export default class ChaptersEndpoints extends EndpointsBase {
// TODO: Only returns top 50, validate / pre-check here
const params = this.paramsFor({ ids: idOrIds, market });
const response = await this.getRequest<Chapters>(`chapters${params}`);
return response.chapters;
return response?.chapters;
}
}
8 changes: 4 additions & 4 deletions src/endpoints/EndpointsBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ export default class EndpointsBase {
constructor(protected api: SpotifyApi) {
}

protected async getRequest<TReturnType>(url: string): Promise<TReturnType> {
protected async getRequest<TReturnType>(url: string): Promise<TReturnType|null> {
return await this.api.makeRequest<TReturnType>("GET", url);
}

protected async postRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType: string | undefined = undefined): Promise<TReturnType> {
protected async postRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType: string | undefined = undefined): Promise<TReturnType|null> {
return await this.api.makeRequest<TReturnType>("POST", url, body, contentType);
}

protected async putRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType: string | undefined = undefined): Promise<TReturnType> {
protected async putRequest<TReturnType, TBody = unknown>(url: string, body?: TBody, contentType: string | undefined = undefined): Promise<TReturnType|null> {
return await this.api.makeRequest<TReturnType>("PUT", url, body, contentType);
}

protected async deleteRequest<TReturnType, TBody = unknown>(url: string, body?: TBody): Promise<TReturnType> {
protected async deleteRequest<TReturnType, TBody = unknown>(url: string, body?: TBody): Promise<TReturnType|null> {
return await this.api.makeRequest<TReturnType>("DELETE", url, body);
}

Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/EpisodesEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ export default class EpisodesEndpoints extends EndpointsBase {

const params = this.paramsFor({ ids: idOrIds, market });
const response = await this.getRequest<Episodes>(`episodes${params}`);
return response.episodes;
return response?.episodes;
}
}
2 changes: 1 addition & 1 deletion src/endpoints/SearchEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ItemTypes, Market, MaxInt, SearchResults } from '../types.js';
import EndpointsBase from './EndpointsBase.js';

export interface SearchExecutionFunction {
<const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T>>;
<const T extends readonly ItemTypes[]>(q: string, type: T, market?: Market, limit?: MaxInt<50>, offset?: number, include_external?: string): Promise<SearchResults<T>|null>;
}

export default class SearchEndpoints extends EndpointsBase {
Expand Down
2 changes: 1 addition & 1 deletion src/endpoints/ShowsEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default class ShowsEndpoints extends EndpointsBase {
// TODO: only returns 50, validate here
const params = this.paramsFor({ ids: idOrIds, market });
const response = await this.getRequest<Shows>(`shows${params}`);
return response.shows;
return response?.shows;
}

public episodes(id: string, market?: Market, limit?: MaxInt<50>, offset?: number) {
Expand Down
4 changes: 2 additions & 2 deletions src/endpoints/TracksEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default class TracksEndpoints extends EndpointsBase {
const params = this.paramsFor({ ids: idOrIds, market });
// TODO: only returns top 20, validate here
const response = await this.getRequest<Tracks>(`tracks${params}`);
return response.tracks;
return response?.tracks;
}

public audioFeatures(id: string): Promise<AudioFeatures>
Expand All @@ -25,7 +25,7 @@ export default class TracksEndpoints extends EndpointsBase {
}
const params = this.paramsFor({ ids: idOrIds });
const response = await this.getRequest<AudioFeaturesCollection>(`audio-features${params}`);
return response.audio_features;
return response?.audio_features;
}

public audioAnalysis(id: string) {
Expand Down
4 changes: 2 additions & 2 deletions src/serialization/DefaultResponseDeserializer.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { IResponseDeserializer } from "../types.js";

export default class DefaultResponseDeserializer implements IResponseDeserializer {
public async deserialize<TReturnType>(response: Response): Promise<TReturnType> {
public async deserialize<TReturnType>(response: Response): Promise<TReturnType|null> {
const text = await response.text();

if (text.length > 0) {
const json = JSON.parse(text);
return json as TReturnType;
}

return null as TReturnType;
return null;
}
}
6 changes: 5 additions & 1 deletion src/test/FakeAuthStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class FakeAuthStrategy implements IAuthStrategy {

constructor(
protected accessToken: string = FakeAuthStrategy.FAKE_AUTH_TOKEN,
protected refreshToken: string = FakeAuthStrategy.FAKE_AUTH_TOKEN,
) {
this.cache = new InMemoryCachingStrategy();
}
Expand All @@ -24,7 +25,10 @@ export class FakeAuthStrategy implements IAuthStrategy {
return {
access_token: this.accessToken,
expires: Date.now() + 3600 * 1000,
} as AccessToken;
token_type: "Bearer",
refresh_token: this.refreshToken,
expires_in: 3600,
} satisfies AccessToken;
},
);

Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export interface IValidateResponses {
}

export interface IResponseDeserializer {
deserialize<TReturnType>(response: Response): Promise<TReturnType>;
deserialize<TReturnType>(response: Response): Promise<TReturnType|null>;
}

export interface ICachingStrategy {
Expand Down