Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
Remove redundant type and simplify media service (#1173)
Browse files Browse the repository at this point in the history
  • Loading branch information
sarayourfriend authored Mar 23, 2022
1 parent 7aa2ab5 commit d1c5185
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 45 deletions.
2 changes: 1 addition & 1 deletion src/components/VAllResultsGrid/VAllResultsGrid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export default defineComponent({
})
/**
* @type { ComputedRef<import('../../store/types').MediaDetail[]> }
* @type { ComputedRef<import('../../store/types').Media[]> }
*/
const allMedia = computed(() => mediaStore.allMedia)
Expand Down
44 changes: 18 additions & 26 deletions src/data/media-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ import { decodeMediaData } from '~/utils/decode-media-data'
import { VersionedApiService } from '~/data/api-service'

import type { ApiQueryParams, MediaResult } from '~/store/types'
import type { DetailFromMediaType, MediaDetail } from '~/models/media'

import type { SupportedMediaType } from '~/constants/media'
import type { Media } from '~/models/media'

import type { AxiosResponse } from 'axios'

class MediaService<T extends SupportedMediaType> {
private readonly mediaType: T
class MediaService<T extends Media> {
private readonly mediaType: T['frontendMediaType']

constructor(mediaType: T) {
constructor(mediaType: T['frontendMediaType']) {
this.mediaType = mediaType
}

Expand All @@ -21,16 +19,14 @@ class MediaService<T extends SupportedMediaType> {
* media id as keys.
* @param data - search result data
*/
transformResults(
data: MediaResult<DetailFromMediaType<T>[]>
): MediaResult<Record<string, DetailFromMediaType<T>>> {
const mediaResults = <DetailFromMediaType<T>[]>data.results
transformResults(data: MediaResult<T[]>): MediaResult<Record<string, T>> {
const mediaResults = <T[]>data.results
return {
...data,
results: mediaResults.reduce((acc, item) => {
acc[item.id] = decodeMediaData(item, this.mediaType)
return acc
}, {} as Record<string, DetailFromMediaType<T>>),
}, {} as Record<string, T>),
}
}

Expand All @@ -40,10 +36,11 @@ class MediaService<T extends SupportedMediaType> {
*/
async search(
params: ApiQueryParams
): Promise<MediaResult<Record<string, MediaDetail>>> {
const res = await VersionedApiService.query<
MediaResult<DetailFromMediaType<T>[]>
>(this.mediaType, params as unknown as Record<string, string>)
): Promise<MediaResult<Record<string, Media>>> {
const res = await VersionedApiService.query<MediaResult<T[]>>(
this.mediaType,
params as unknown as Record<string, string>
)
return this.transformResults(res.data)
}

Expand All @@ -52,26 +49,21 @@ class MediaService<T extends SupportedMediaType> {
* SSR-called
* @param id - the media id to fetch
*/
async getMediaDetail(id: string): Promise<DetailFromMediaType<T>> {
async getMediaDetail(id: string): Promise<T> {
if (!id) {
throw new Error(
`MediaService.getMediaDetail() id parameter required to retrieve ${this.mediaType} details.`
)
}
const res = await VersionedApiService.get<DetailFromMediaType<T>>(
this.mediaType,
id
)
return decodeMediaData<T>(res.data, this.mediaType)
const res = await VersionedApiService.get<T>(this.mediaType, id)
return decodeMediaData(res.data, this.mediaType)
}

/**
* Retrieve related media
* @param params - object with id of the main media, for which to fetch related media
*/
async getRelatedMedia(params: {
id: string
}): Promise<MediaResult<DetailFromMediaType<T>[]>> {
async getRelatedMedia(params: { id: string }): Promise<MediaResult<T[]>> {
if (!params.id) {
throw new Error(
`MediaService.getRelatedMedia() id parameter required to retrieve related media.`
Expand All @@ -81,12 +73,12 @@ class MediaService<T extends SupportedMediaType> {
const res = (await VersionedApiService.get(
this.mediaType,
`${params.id}/related`
)) as AxiosResponse<MediaResult<DetailFromMediaType<T>[]>>
)) as AxiosResponse<MediaResult<T[]>>
return {
...res.data,
results: res.data.results.map((item) =>
decodeMediaData(item, this.mediaType)
) as DetailFromMediaType<T>[],
) as T[],
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions src/models/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,5 @@ export interface AudioDetail extends Media {
peaks?: number[]
}

export type MediaDetail = ImageDetail | AudioDetail

export type DetailFromMediaType<T extends SupportedMediaType> =
T extends 'image' ? ImageDetail : T extends 'audio' ? AudioDetail : never
2 changes: 1 addition & 1 deletion src/pages/search/search-page.types.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const propTypes = {
resultItems: {
type: /** @type {import('../../store/types').MediaDetail[]} */ (Object),
type: /** @type {import('../../store/types').Media[]} */ (Object),
required: true,
},
fetchState: {
Expand Down
4 changes: 2 additions & 2 deletions src/store/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type {
AudioDetail,
DetailFromMediaType,
ImageDetail,
MediaDetail,
Media,
} from '~/models/media'
import type { SupportedMediaType } from '~/constants/media'

Expand All @@ -11,7 +11,7 @@ import type { SupportedMediaType } from '~/constants/media'
* Properties use snake_case, unlike the camelCase in the store.
*/
export interface MediaResult<
T extends MediaDetail | MediaDetail[] | Record<string, MediaDetail>
T extends Media | Media[] | Record<string, Media>
> {
result_count: number
page_count: number
Expand Down
15 changes: 10 additions & 5 deletions src/stores/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@ import MediaService from '~/data/media-service'
import { hash, rand as prng } from '~/utils/prng'
import { useSearchStore } from '~/stores/search'
import type { MediaState } from '~/store/types'
import type { DetailFromMediaType, MediaDetail } from '~/models/media'
import type {
Media,
AudioDetail,
ImageDetail,
DetailFromMediaType,
} from '~/models/media'

export const mediaServices = {
[AUDIO]: new MediaService(AUDIO),
[IMAGE]: new MediaService(IMAGE),
}
[AUDIO]: new MediaService<AudioDetail>(AUDIO),
[IMAGE]: new MediaService<ImageDetail>(IMAGE),
} as const

export const createUseMediaStore = (services = mediaServices) =>
defineStore('media', () => {
Expand Down Expand Up @@ -70,7 +75,7 @@ export const createUseMediaStore = (services = mediaServices) =>
...items,
[type]: Object.values(state.results[type].items),
}),
{} as Record<SupportedMediaType, MediaDetail[]>
{} as Record<SupportedMediaType, Media[]>
)
})
/**
Expand Down
12 changes: 5 additions & 7 deletions src/utils/decode-media-data.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { title } from 'case'

import { decodeData as decodeString } from '~/utils/decode-data'
import type { SupportedMediaType } from '~/constants/media'
import { IMAGE } from '~/constants/media'
import type { DetailFromMediaType, Media, Tag } from '~/models/media'
import type { Media, Tag } from '~/models/media'

/**
* This interface is a subset of `Media` that types dictionaries sent by the API
Expand All @@ -21,10 +19,10 @@ interface ApiMedia extends Omit<Media, 'frontendMediaType' | 'title'> {
* @param mediaType - the type of the media
* @returns the given media object with the text fields decoded
*/
export const decodeMediaData = <T extends SupportedMediaType>(
export const decodeMediaData = <T extends Media>(
media: ApiMedia,
mediaType: SupportedMediaType = IMAGE
): DetailFromMediaType<T> =>
mediaType: T['frontendMediaType']
): T =>
({
...media,
frontendMediaType: mediaType,
Expand All @@ -35,4 +33,4 @@ export const decodeMediaData = <T extends SupportedMediaType>(
...tag,
name: decodeString(tag.name),
})),
} as DetailFromMediaType<T>)
} as T)
2 changes: 1 addition & 1 deletion test/unit/specs/utils/decode-image-data.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ describe('decodeImageData', () => {
frontendMediaType: IMAGE,
}

expect(decodeMediaData(data)).toEqual(expected)
expect(decodeMediaData(data, IMAGE)).toEqual(expected)
})
})

0 comments on commit d1c5185

Please sign in to comment.