Skip to content

Commit b41a01a

Browse files
committed
fix(base-client): adds type inference to param & body
1 parent 288566a commit b41a01a

13 files changed

+44
-33
lines changed

src/models/tmdb/tmdb-client.model.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export type TmdbPaginatedData<T = unknown, C = unknown> = {
6767
export type TmdbApiResponse<T = unknown> = ResponseOrTypedResponse<T>;
6868

6969
export type TmdbApiQuery<T = unknown> = BaseQuery<BaseRequest, T>;
70-
export type TmdbApiTemplateOptions = BaseTemplateOptions & {
70+
export type TmdbApiTemplateOptions<T extends string | number | symbol = string> = BaseTemplateOptions<T, boolean> & {
7171
/** If the method requires user authentication */
7272
auth?: 'session' | 'token' | false;
7373
/** If the method is authorized for a guest session id */
@@ -76,7 +76,7 @@ export type TmdbApiTemplateOptions = BaseTemplateOptions & {
7676
version: number | string;
7777
};
7878

79-
export type TmdbApiTemplate<Parameter extends TmdbApiParam = TmdbApiParam> = BaseTemplate<Parameter, TmdbApiTemplateOptions>;
79+
export type TmdbApiTemplate<Parameter extends TmdbApiParam = TmdbApiParam> = BaseTemplate<Parameter, TmdbApiTemplateOptions<keyof Parameter>>;
8080

8181
export interface TmdbClientEndpoint<Parameter extends TmdbApiParam = Record<string, never>, Response = unknown> {
8282
(param?: Parameter, init?: BodyInit): Promise<TmdbApiResponse<Response>>;
@@ -87,7 +87,7 @@ export class TmdbClientEndpoint<
8787
Parameter extends TmdbApiParam = Record<string, never>,
8888
Response = unknown,
8989
Cache extends boolean = true,
90-
> extends ClientEndpoint<Parameter, Response, Cache, TmdbApiTemplateOptions> {}
90+
> extends ClientEndpoint<Parameter, Response, Cache, TmdbApiTemplateOptions<keyof Parameter>> {}
9191

9292
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- this is a recursive type
9393
export type ITmdbApi<Parameter extends TmdbApiParam = any, Response = unknown, Cache extends boolean = boolean> = {

src/models/trakt/trakt-client.model.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export type TraktApiExtends = (typeof TraktApiExtended)[keyof typeof TraktApiExt
7676
/**
7777
* Represents options that can be used in a Trakt API template.
7878
*/
79-
export type TraktApiTemplateOptions = BaseTemplateOptions & {
79+
export type TraktApiTemplateOptions<T extends string | number | symbol = string> = BaseTemplateOptions<T, boolean | 'vip'> & {
8080
/** If the method supports or requires vip status */
8181
vip?: boolean | 'enhanced';
8282
/** If the method supports or requires authentication */
@@ -93,7 +93,7 @@ export type TraktApiTemplateOptions = BaseTemplateOptions & {
9393

9494
export type TraktApiInit = BaseInit;
9595

96-
export type TraktApiTemplate<Parameter extends TraktApiParams = TraktApiParams> = BaseTemplate<Parameter, TraktApiTemplateOptions>;
96+
export type TraktApiTemplate<Parameter extends TraktApiParams = TraktApiParams> = BaseTemplate<Parameter, TraktApiTemplateOptions<keyof Parameter>>;
9797

9898
export interface TraktClientEndpoint<Parameter extends TraktApiParams = Record<string, never>, Response = unknown> {
9999
(param?: Parameter, init?: TraktApiInit): Promise<TraktApiResponse<Response>>;
@@ -104,7 +104,7 @@ export class TraktClientEndpoint<
104104
Parameter extends TraktApiParams = Record<string, never>,
105105
Response = unknown,
106106
Cache extends boolean = true,
107-
> extends ClientEndpoint<Parameter, Response, Cache, TraktApiTemplateOptions> {}
107+
> extends ClientEndpoint<Parameter, Response, Cache, TraktApiTemplateOptions<keyof Parameter>> {}
108108

109109
export type TraktApiRequest = BaseRequest;
110110

src/models/tvdb/tvdb-client.model.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@ export type TvdbApiQuery<T = unknown> = BaseQuery<BaseRequest, T>;
6666
/**
6767
* Represents options that can be used in a tvdb API template.
6868
*/
69-
export type TvdbApiTemplateOptions = BaseTemplateOptions & {
69+
export type TvdbApiTemplateOptions<T extends string | number | symbol = string> = BaseTemplateOptions<T, boolean> & {
7070
/** If the method requires authentication */
7171
auth?: boolean;
7272
};
7373

74-
export type TvdbApiTemplate<Parameter extends TvdbApiParam = TvdbApiParam> = BaseTemplate<Parameter, TvdbApiTemplateOptions>;
74+
export type TvdbApiTemplate<Parameter extends TvdbApiParam = TvdbApiParam> = BaseTemplate<Parameter, TvdbApiTemplateOptions<keyof Parameter>>;
7575

7676
export interface TvdbClientEndpoint<Parameter extends TvdbApiParam = Record<string, never>, Response = unknown> {
7777
(param?: Parameter, init?: BodyInit): Promise<TvdbApiResponse<Response>>;
@@ -82,7 +82,7 @@ export class TvdbClientEndpoint<
8282
Parameter extends TvdbApiParam = Record<string, never>,
8383
Response = unknown,
8484
Cache extends boolean = true,
85-
> extends ClientEndpoint<Parameter, Response, Cache, TvdbApiTemplateOptions> {}
85+
> extends ClientEndpoint<Parameter, Response, Cache, TvdbApiTemplateOptions<keyof Parameter>> {}
8686

8787
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- this is a recursive type
8888
export type ITvdbApi<Parameter extends TvdbApiParam = any, Response = unknown, Cache extends boolean = boolean> = {

src/services/common/base-client.test.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { HttpMethod } from '../../utils/http.utils';
66

77
import {
88
BaseApiHeaders,
9+
type BaseBody,
910
BaseClient,
1011
BaseHeaderContentType,
1112
type BaseOptions,
@@ -61,7 +62,7 @@ const api = {
6162
},
6263
},
6364
}),
64-
endpointWithBody: new ClientEndpoint({
65+
endpointWithBody: new ClientEndpoint<RecursiveRecord>({
6566
method: HttpMethod.POST,
6667
url: '/endpoint-with-body',
6768
body: {
@@ -136,7 +137,7 @@ class TestableBaseClient extends BaseClient implements IEndpoints {
136137
}
137138

138139
// eslint-disable-next-line class-methods-use-this -- abstract method
139-
_parseBody<T extends RecursiveRecord = RecursiveRecord>(body: Record<string, string | boolean>, params: T): BodyInit {
140+
_parseBody<T extends RecursiveRecord = RecursiveRecord>(body: BaseBody<string | keyof T>, params: T): BodyInit {
140141
return parseBody(body, params);
141142
}
142143

src/services/common/base-client.ts

+15-7
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ export type BaseOptions<S extends RecursiveRecord = RecursiveRecord, R extends R
3939
cacheStore?: CacheStore<R>;
4040
};
4141

42-
export type BaseTemplateOptions = {
42+
export type BaseTemplateOptions<
43+
T extends string | number | symbol = string | number | symbol,
44+
V extends boolean | symbol | string = boolean | symbol | string,
45+
> = {
4346
/**
4447
* Enables caching of requests (defaults to true).
4548
* If a number is provided, it will be used as the retention time in milliseconds.
@@ -48,20 +51,25 @@ export type BaseTemplateOptions = {
4851
/** Boolean record or required (truthy) or optional parameters (falsy) */
4952
parameters?: {
5053
/** Boolean record or required (truthy) or optional path parameters (falsy) */
51-
path?: Record<string, boolean | 'vip'>;
54+
path?: Partial<Record<T, V>>;
5255
/** Boolean record or required (truthy) or optional query parameters (falsy) */
53-
query?: Record<string, boolean | 'vip'>;
56+
query?: Partial<Record<T, V>>;
5457
};
5558
};
5659

5760
export type BaseInit = Omit<Partial<BaseRequest['init']>, 'method'>;
5861

62+
export type BaseBody<
63+
T extends string | number | symbol = string | number | symbol,
64+
V extends boolean | symbol | string = boolean | symbol | string,
65+
> = Partial<Record<T, V>>;
66+
5967
export type BaseTemplate<P extends RecursiveRecord = RecursiveRecord, O extends BaseTemplateOptions = BaseTemplateOptions> = {
6068
method: HttpMethods;
6169
url: string;
6270
opts?: O;
6371
/** Boolean record or required (truthy) or optional fields (falsy) */
64-
body?: Record<string, boolean>;
72+
body?: BaseBody<string | keyof P>;
6573
/** Partial fetch request init */
6674
init?: BaseInit;
6775
/** Validate the parameters before performing request */
@@ -101,7 +109,7 @@ export class ClientEndpoint<
101109
method: HttpMethods;
102110
url: string;
103111
opts: Option;
104-
body?: Record<string, boolean>;
112+
body?: BaseBody<string | keyof Parameter>;
105113
init?: BaseInit;
106114
validate?: (param: Parameter) => boolean;
107115
cached: Cache extends true ? Omit<this, 'cached'> & ClientEndpointCache<Parameter, Response> : never;
@@ -381,7 +389,7 @@ export abstract class BaseClient<
381389
* @protected
382390
* @abstract
383391
*/
384-
protected abstract _parseBody<T extends RecursiveRecord = RecursiveRecord>(body: Record<string, string | boolean>, params: T): BodyInit;
392+
protected abstract _parseBody<T extends RecursiveRecord = RecursiveRecord>(body: BaseBody<string | keyof T>, params: T): BodyInit;
385393

386394
/**
387395
* Parses the response from the API before returning from the call.
@@ -406,7 +414,7 @@ export abstract class BaseClient<
406414
*
407415
* @returns {BodyInit} The parsed request body.
408416
*/
409-
export const parseBody = <T extends RecursiveRecord = RecursiveRecord>(template: Record<string, string | boolean> = {}, params: T): BodyInit => {
417+
export const parseBody = <T extends RecursiveRecord = RecursiveRecord>(template: BaseBody<string | keyof T> = {}, params: T): BodyInit => {
410418
const _body: Record<string, string> = {};
411419

412420
Object.entries(params).forEach(([key, value]) => {

src/services/tmdb-client/clients/base-tmdb-client.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type {
1313
} from '~/models/tmdb/tmdb-client.model';
1414

1515
import { TraktApiHeaders } from '~/models/trakt/trakt-client.model';
16-
import { BaseApiHeaders, BaseClient, BaseHeaderContentType, parseBody, parseUrl } from '~/services/common/base-client';
16+
import { BaseApiHeaders, type BaseBody, BaseClient, BaseHeaderContentType, parseBody, parseUrl } from '~/services/common/base-client';
1717
import { tmdbApi } from '~/services/tmdb-client/api/tmdb-api.endpoint';
1818

1919
/**
@@ -138,7 +138,7 @@ export class BaseTmdbClient
138138
* @returns {BodyInit} The parsed request body.
139139
*/
140140
// eslint-disable-next-line class-methods-use-this -- implemented from abstract class
141-
protected _parseBody<T extends TmdbApiParam = TmdbApiParam>(template: Record<string, string | boolean>, params: T): BodyInit {
141+
protected _parseBody<T extends TmdbApiParam = TmdbApiParam>(template: BaseBody<string | keyof T>, params: T): BodyInit {
142142
return parseBody(template, params);
143143
}
144144

src/services/trakt-client/api/endpoints/scrobble.endpoint.ts

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export const scrobble = {
3131

3232
movie: false,
3333
episode: false,
34+
show: false,
3435
},
3536
}),
3637
/**
@@ -53,6 +54,7 @@ export const scrobble = {
5354

5455
movie: false,
5556
episode: false,
57+
show: false,
5658
},
5759
}),
5860
/**
@@ -90,6 +92,7 @@ export const scrobble = {
9092

9193
movie: false,
9294
episode: false,
95+
show: false,
9396
},
9497
}),
9598
};

src/services/trakt-client/api/endpoints/users.endpoint.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ export const users = {
351351
pagination: true,
352352
parameters: {
353353
path: {
354-
username: true,
354+
id: true,
355355
type: false,
356356
},
357357
},
@@ -392,7 +392,7 @@ export const users = {
392392
extended: [TraktApiExtended.Full, TraktApiExtended.Metadata],
393393
parameters: {
394394
path: {
395-
username: true,
395+
id: true,
396396
type: true,
397397
},
398398
},

src/services/trakt-client/clients/base-trakt-client.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { CancellableFetch } from '../../../utils/fetch.utils';
88

99
import { HttpMethod } from '../../../utils/http.utils';
1010

11-
import { BaseHeaderContentType } from '../../common/base-client';
11+
import { type BaseBody, BaseHeaderContentType } from '../../common/base-client';
1212

1313
import { BaseTraktClient, parseResponse } from './base-trakt-client';
1414

@@ -25,7 +25,7 @@ class TestableTraktClient extends BaseTraktClient {
2525
return this._call<P>(template, params, init);
2626
}
2727

28-
publicParseBody<T extends TraktApiParams = TraktApiParams>(template: Record<string, string | boolean>, params: T): BodyInit {
28+
publicParseBody<T extends TraktApiParams = TraktApiParams>(template: BaseBody<string | keyof T>, params: T): BodyInit {
2929
return this._parseBody(template, params);
3030
}
3131

src/services/trakt-client/clients/base-trakt-client.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type { Primitive } from '~/utils/typescript.utils';
1313

1414
import { TraktApiHeaders } from '~/models/trakt/trakt-client.model';
1515

16-
import { BaseClient, BaseHeaderContentType, parseBody, parseUrl } from '~/services/common/base-client';
16+
import { type BaseBody, BaseClient, BaseHeaderContentType, parseBody, parseUrl } from '~/services/common/base-client';
1717
import { traktApi } from '~/services/trakt-client/api/trakt-api.endpoints';
1818
import { isFilter, TraktApiFilterValidator } from '~/services/trakt-client/api/trakt-api.filters';
1919

@@ -222,7 +222,7 @@ export class BaseTraktClient
222222
* @returns {BodyInit} The parsed request body.
223223
*/
224224
// eslint-disable-next-line class-methods-use-this -- implemented from abstract class
225-
protected _parseBody<T extends TraktApiParams = TraktApiParams>(template: Record<string, string | boolean>, params: T): BodyInit {
225+
protected _parseBody<T extends TraktApiParams = TraktApiParams>(template: BaseBody<string | keyof T>, params: T): BodyInit {
226226
return parseBody(template, params);
227227
}
228228

src/services/trakt-client/clients/trakt-client.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -291,11 +291,11 @@ export class TraktClient extends BaseTraktClient {
291291
*
292292
* @throws Error Throws an error if no refresh token is found.
293293
*/
294-
refreshToken() {
295-
if (!this.auth.refresh_token) {
294+
refreshToken(refresh_token = this.auth.refresh_token) {
295+
if (!refresh_token) {
296296
throw new Error('No refresh token found.');
297297
}
298-
return this._exchange({ refresh_token: this.auth.refresh_token });
298+
return this._exchange({ refresh_token });
299299
}
300300

301301
/**
@@ -321,7 +321,7 @@ export class TraktClient extends BaseTraktClient {
321321
* @returns A promise resolving to the imported Trakt authentication information.
322322
*/
323323
async importAuthentication(auth: TraktClientAuthentication = {}): Promise<TraktClientAuthentication> {
324-
if (auth.expires !== undefined && auth.expires < Date.now()) return this.refreshToken();
324+
if (auth.expires !== undefined && auth.expires < Date.now()) return this.refreshToken(auth.refresh_token);
325325

326326
this.updateAuth(auth);
327327
return this.auth;

src/services/tvdb-client/clients/base-tvdb-client.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type {
1111
} from '~/models/tvdb/tvdb-client.model';
1212

1313
import { TraktApiHeaders } from '~/models/trakt/trakt-client.model';
14-
import { BaseApiHeaders, BaseClient, BaseHeaderContentType, parseBody, parseUrl } from '~/services/common/base-client';
14+
import { BaseApiHeaders, type BaseBody, BaseClient, BaseHeaderContentType, parseBody, parseUrl } from '~/services/common/base-client';
1515
import { tvdbApi } from '~/services/tvdb-client/api/tvdb-api.endpoint';
1616

1717
/**
@@ -103,7 +103,7 @@ export class BaseTvdbClient
103103
* @returns {BodyInit} The parsed request body.
104104
*/
105105
// eslint-disable-next-line class-methods-use-this -- implemented from abstract class
106-
protected _parseBody<T extends TvdbApiParam = TvdbApiParam>(template: Record<string, string | boolean>, params: T): BodyInit {
106+
protected _parseBody<T extends TvdbApiParam = TvdbApiParam>(template: BaseBody<string | keyof T>, params: T): BodyInit {
107107
return parseBody(template, params);
108108
}
109109

tsconfig.vitest.json

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"compilerOptions": {
66
"strict": true,
77
"composite": true,
8-
"lib": [],
98
"types": ["node", "jsdom", "vitest/globals"]
109
}
1110
}

0 commit comments

Comments
 (0)