Skip to content

Commit 4063e40

Browse files
committed
fix(base-client): support more flexible date formats
1 parent 5945105 commit 4063e40

File tree

7 files changed

+47
-17
lines changed

7 files changed

+47
-17
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export type TraktCalendarStartAndDay = {
2323
* Date (in UTC) from which to start the calendar.
2424
* Defaults to today.
2525
*/
26-
start_date?: string;
26+
start_date?: string | number | Date;
2727
/**
2828
* Number of days to display.
2929
* Defaults to 7.

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

+20-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { TraktApiTemplate } from '~/models/trakt/trakt-client.model';
1+
import type { TraktApiParams, TraktApiTemplate } from '~/models/trakt/trakt-client.model';
22
import type { TraktApiIds } from '~/models/trakt/trakt-id.model';
33
import type { RequireAtLeastOne } from '~/utils/typescript.utils';
44

@@ -75,7 +75,7 @@ export type StartDateParam = {
7575
* The start_date is only accurate to the hour, for caching purposes. Please drop the minutes and seconds from your timestamp to help optimize our cached data.
7676
* For example, use 2021-07-17T12:00:00Z and not 2021-07-17T12:23:34Z.
7777
*/
78-
start_date?: string;
78+
start_date?: string | number | Date;
7979
};
8080

8181
export const EntityType = {
@@ -90,12 +90,24 @@ export type Extended = typeof EntityType.Extended;
9090

9191
export type EntityTypes = (typeof EntityType)[keyof typeof EntityType];
9292

93-
export const validateStartDate: TraktApiTemplate<StartDateParam>['validate'] = param => {
94-
if (param.start_date) TraktApiValidators.date(param.start_date);
95-
return true;
93+
export const getDateValidate = <T extends TraktApiParams>(prop: keyof T, regex?: RegExp): TraktApiTemplate<T>['validate'] => {
94+
return param => {
95+
const _date = param[prop];
96+
if (_date === undefined) return true;
97+
if (typeof _date === 'string') return TraktApiValidators.date(_date, regex);
98+
return true;
99+
};
96100
};
97101

98-
export const transformStartDate: TraktApiTemplate<StartDateParam>['transform'] = param => {
99-
if (param.start_date) return { ...param, start_date: TraktApiTransforms.date.dropMinutes(param.start_date) };
100-
return param;
102+
export const getDateTransform = <T extends TraktApiParams>(prop: keyof T, short?: boolean): TraktApiTemplate<T>['transform'] => {
103+
return param => {
104+
let _date = param[prop] as string | number | Date;
105+
if (_date === undefined) return param;
106+
if (typeof _date !== 'string') _date = _date instanceof Date ? _date.toISOString() : new Date(_date).toISOString();
107+
if (short && _date.includes('T')) _date = _date.split('T').at(0)!;
108+
return { ...param, [prop]: TraktApiTransforms.date.dropMinutes(_date) };
109+
};
101110
};
111+
112+
export const validateStartDate: TraktApiTemplate<StartDateParam>['validate'] = getDateValidate('start_date');
113+
export const transformStartDate: TraktApiTemplate<StartDateParam>['transform'] = getDateTransform('start_date', true);

src/services/common/base-client.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,10 @@ export abstract class BaseClient<
346346
const fn: ClientEndpointCall = (param, init) => this._call(template, param, init);
347347

348348
const cachedFn: ClientEndpointCache = getCachedFunction(fn, {
349-
key: (param: unknown, init: unknown) => JSON.stringify({ template: template.config, param, init }),
349+
key: (param: unknown, init: unknown) => {
350+
const _param = template?.transform?.(param as RecursiveRecord) ?? param;
351+
return JSON.stringify({ template: template.config, param: _param, init });
352+
},
350353
cache: this._cache,
351354
retention: template.opts?.cache,
352355
evictionKey: `{"template":${JSON.stringify(template.config).replace(ExactMatchRegex, '\\$&')}`,

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

+16-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import type { TraktApiTemplate, TraktApiTemplateOptions } from '~/models/trakt/t
33

44
import { TraktApiExtended, TraktClientEndpoint } from '~/models/trakt/trakt-client.model';
55

6-
import { validateStartDate } from '~/models/trakt/trakt-entity.model';
6+
import { getDateTransform, getDateValidate } from '~/models/trakt/trakt-entity.model';
77
import { TraktApiCommonFilterValues } from '~/services/trakt-client/api/trakt-api.filters';
88

99
import { HttpMethod } from '~/utils/http.utils';
10+
import { DateISO8601Short } from '~/utils/regex.utils';
1011

1112
const opts: TraktApiTemplateOptions = {
1213
extended: [TraktApiExtended.Full],
@@ -19,7 +20,8 @@ const opts: TraktApiTemplateOptions = {
1920
},
2021
};
2122

22-
const validate: TraktApiTemplate<TraktCalendarQuery>['validate'] = validateStartDate;
23+
const validate: TraktApiTemplate<TraktCalendarQuery>['validate'] = getDateValidate('start_date', DateISO8601Short);
24+
const transform: TraktApiTemplate<TraktCalendarQuery>['transform'] = getDateTransform('start_date', true);
2325

2426
/**
2527
* By default, the calendar will return all shows or movies for the specified time period and can be global or user specific.
@@ -48,6 +50,7 @@ export const calendars = {
4850
url: '/calendars/my/shows/:start_date/:days',
4951
opts: { auth: true, ...opts },
5052
validate,
53+
transform,
5154
}),
5255
/**
5356
* Returns all new show premieres (series_premiere) airing during the time period specified.
@@ -63,6 +66,7 @@ export const calendars = {
6366
url: '/calendars/my/shows/new/:start_date/:days',
6467
opts: { auth: true, ...opts },
6568
validate,
69+
transform,
6670
}),
6771
/**
6872
* Returns all show premieres (mid_season_premiere, season_premiere, series_premiere) airing during the time period specified.
@@ -78,6 +82,7 @@ export const calendars = {
7882
url: '/calendars/my/shows/premieres/:start_date/:days',
7983
opts: { auth: true, ...opts },
8084
validate,
85+
transform,
8186
}),
8287
/**
8388
* Returns all show finales (mid_season_finale, season_finale, series_finale) airing during the time period specified.
@@ -93,6 +98,7 @@ export const calendars = {
9398
url: '/calendars/my/shows/finales/:start_date/:days',
9499
opts: { auth: true, ...opts },
95100
validate,
101+
transform,
96102
}),
97103
},
98104
/**
@@ -109,6 +115,7 @@ export const calendars = {
109115
url: '/calendars/my/movies/:start_date/:days',
110116
opts: { auth: true, ...opts },
111117
validate,
118+
transform,
112119
}),
113120
/**
114121
* Returns all movies with a DVD release date during the time period specified.
@@ -124,6 +131,7 @@ export const calendars = {
124131
url: '/calendars/my/dvd/:start_date/:days',
125132
opts: { auth: true, ...opts },
126133
validate,
134+
transform,
127135
}),
128136
},
129137
all: {
@@ -140,6 +148,7 @@ export const calendars = {
140148
url: '/calendars/all/shows/:start_date/:days',
141149
opts,
142150
validate,
151+
transform,
143152
}),
144153
/**
145154
* Returns all new show premieres (series_premiere) airing during the time period specified.
@@ -153,6 +162,7 @@ export const calendars = {
153162
url: '/calendars/all/shows/new/:start_date/:days',
154163
opts,
155164
validate,
165+
transform,
156166
}),
157167
/**
158168
* Returns all show premieres (mid_season_premiere, season_premiere, series_premiere) airing during the time period specified.
@@ -166,6 +176,7 @@ export const calendars = {
166176
url: '/calendars/all/shows/premieres/:start_date/:days',
167177
opts,
168178
validate,
179+
transform,
169180
}),
170181
/**
171182
* Returns all show finales (mid_season_finale, season_finale, series_finale) airing during the time period specified.
@@ -179,6 +190,7 @@ export const calendars = {
179190
url: '/calendars/all/finales/:start_date/:days',
180191
opts,
181192
validate,
193+
transform,
182194
}),
183195
/**
184196
* Returns all movies with a release date during the time period specified.
@@ -192,6 +204,7 @@ export const calendars = {
192204
url: '/calendars/all/movies/:start_date/:days',
193205
opts,
194206
validate,
207+
transform,
195208
}),
196209
},
197210
/**
@@ -206,6 +219,7 @@ export const calendars = {
206219
url: '/calendars/all/dvd/:start_date/:days',
207220
opts,
208221
validate,
222+
transform,
209223
}),
210224
},
211225
};

src/services/trakt-client/api/trakt-api.validators.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { DateISO8601Short } from '~/utils/regex.utils';
1+
import { DateISO8601 } from '~/utils/regex.utils';
22

33
export const TraktApiValidators = {
4-
date: (date: string, regex = DateISO8601Short) => {
4+
date: (date: string, regex = DateISO8601) => {
55
if (!regex.test(date)) {
6-
throw new Error(`Invalide 'start_date' format : ${date}`);
6+
throw new Error(`Invalide 'start_date' format, found '${date}', expected '${regex}'`);
77
}
88
return true;
99
},

src/stores/data/calendar.store.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,11 @@ export const useCalendarStore = defineStore('data.calendar', () => {
144144
const startDate = ['start', 'reload'].includes(mode) ? startCalendar.value : endCalendar.value;
145145
const endDate = DateUtils.next(days.value - 1, startDate);
146146
const start_date = startDate.toISOString().split('T')[0];
147+
const end_date = endDate.toISOString().split('T')[0];
147148

148149
if (mode === 'end') endCalendar.value = DateUtils.next(days.value, endCalendar.value);
149150

150-
console.info('Fetching calendar', { mode, start_date, endDate: endDate.toISOString().split('T')[0], days: days.value });
151+
console.info('Fetching calendar', { mode, start_date, end_date, days: days.value });
151152

152153
const timeout = setTimeout(() => {
153154
if (mode === 'reload') calendar.value = getEmptyWeeks(startDate, true);

src/utils/regex.utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ export const DecimalRange = /^(10|\d)\.\d-(10|\d)\.\d$/;
33
export const PercentageRange = /^(100|\d{0,2})-(100|\d{0,2})$/;
44
export const LargeRange = /^(100000|\d{0,5})-(100000|\d{0,5})$/;
55
export const VeryLargeRange = /^(300000|[1-2]?\d{0,5})-(300000|[1-2]?\d{0,5})$/;
6-
export const DateISO8601 = /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-]\d{2}:[0-5]\d)?$/;
6+
export const DateISO8601 = /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])(T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-]\d{2}:[0-5]\d)?)?$/;
77
export const DateISO8601Short = /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
88
export const ExactMatchRegex = /[/\-\\^$*+?.()|[\]{}]/g;

0 commit comments

Comments
 (0)