Skip to content

Commit

Permalink
refactor: adapters and types
Browse files Browse the repository at this point in the history
  • Loading branch information
Mnigos committed Jan 29, 2024
1 parent 63c8688 commit b827112
Show file tree
Hide file tree
Showing 54 changed files with 457 additions and 569 deletions.
9 changes: 5 additions & 4 deletions src/common/adapters/adapters.module.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import { Module } from '@nestjs/common'
import { Global, Module } from '@nestjs/common'

import { ArtistsAdapter } from './artists.adapter'
import { AudioFeaturesAdapter } from './audio-features.adapter'
import { DevicesAdapter } from './devices.adapter'
import { GenresAdapter } from './genres.adapter'
import { PaginatedAdapter } from './paginated.adapter'
import { PageAdapter } from './page.adapter'
import { TracksAdapter } from './tracks.adapter'
import { PlaybackStateAdapter } from './playback-state.adapter'
import { ProfileAdapter } from './profile.adapter'
import { SecretDataAdapter } from './secret-data.adapter'
import { AdaptersService } from './adapters.service'

@Global()
@Module({
imports: [AdaptersService],
providers: [
ArtistsAdapter,
TracksAdapter,
AudioFeaturesAdapter,
DevicesAdapter,
GenresAdapter,
PaginatedAdapter,
PageAdapter,
PlaybackStateAdapter,
ProfileAdapter,
SecretDataAdapter,
AdaptersService,
],
exports: [AdaptersService],
})
Expand Down
13 changes: 9 additions & 4 deletions src/common/adapters/adapters.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@ import { Injectable } from '@nestjs/common'
import { AudioFeaturesAdapter } from './audio-features.adapter'
import { DevicesAdapter } from './devices.adapter'
import { GenresAdapter } from './genres.adapter'
import { PaginatedAdapter } from './paginated.adapter'
import { PageAdapter } from './page.adapter'
import { TracksAdapter } from './tracks.adapter'
import { PlaybackStateAdapter } from './playback-state.adapter'
import { ProfileAdapter } from './profile.adapter'
import { ArtistsAdapter } from './artists.adapter'
import { SecretDataAdapter } from './secret-data.adapter'

@Injectable()
export class AdaptersService {
constructor(
readonly artists: AdaptersService,
readonly artists: ArtistsAdapter,
readonly tracks: TracksAdapter,
readonly audioFeatures: AudioFeaturesAdapter,
readonly devices: DevicesAdapter,
readonly genres: GenresAdapter,
readonly paginated: PaginatedAdapter,
readonly playbackState: PlaybackStateAdapter
readonly page: PageAdapter,
readonly playbackState: PlaybackStateAdapter,
readonly profile: ProfileAdapter,
readonly secretData: SecretDataAdapter
) {}
}
32 changes: 15 additions & 17 deletions src/common/adapters/artists.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { Test } from '@nestjs/testing'

import { ArtistsAdapter } from './artists.adapter'
import { PaginatedAdapter } from './paginated.adapter'
import { PageAdapter } from './page.adapter'

import {
artistMock,
spotifyArtistMock,
spotifyResponseWithOffsetMockFactory,
spotifyTrackArtistMock,
trackArtistMock,
sdkArtistMock,
pageMockFactory,
sdkSimplifiedArtistMock,
simplifiedArtistMock,
} from '@common/mocks'

describe('ArtistsAdapter', () => {
let artistsAdapter: ArtistsAdapter

beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [ArtistsAdapter, PaginatedAdapter],
providers: [ArtistsAdapter, PageAdapter],
}).compile()

artistsAdapter = module.get(ArtistsAdapter)
Expand All @@ -27,30 +27,28 @@ describe('ArtistsAdapter', () => {
})

test('should adapt a single artist', () => {
expect(artistsAdapter.adapt(spotifyArtistMock)).toEqual(artistMock)
expect(artistsAdapter.adapt(sdkArtistMock)).toEqual(artistMock)
})

test('should adapt a single simplified artist', () => {
expect(artistsAdapter.adapt(spotifyTrackArtistMock)).toEqual(
trackArtistMock
expect(artistsAdapter.adapt(sdkSimplifiedArtistMock)).toEqual(
simplifiedArtistMock
)
})

test('should adapt an array of artists', () => {
expect(artistsAdapter.adapt([spotifyArtistMock])).toEqual([artistMock])
expect(artistsAdapter.adapt([sdkArtistMock])).toEqual([artistMock])
})

test('should adapt an array of simplified artists', () => {
expect(artistsAdapter.adapt([spotifyTrackArtistMock])).toEqual([
trackArtistMock,
expect(artistsAdapter.adapt([sdkSimplifiedArtistMock])).toEqual([
simplifiedArtistMock,
])
})

test('should adapt a paginated list of artists', () => {
expect(
artistsAdapter.adapt(
spotifyResponseWithOffsetMockFactory([spotifyArtistMock])
)
).toEqual(spotifyResponseWithOffsetMockFactory([artistMock]))
expect(artistsAdapter.adapt(pageMockFactory([sdkArtistMock]))).toEqual(
pageMockFactory([artistMock])
)
})
})
73 changes: 34 additions & 39 deletions src/common/adapters/artists.adapter.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,62 @@
import { Injectable } from '@nestjs/common'
import {
Page,
SimplifiedArtist,
Artist as SpotifyArtist,
} from '@spotify/web-api-ts-sdk'
import { Page } from '@spotify/web-api-ts-sdk'

import { PaginatedAdapter } from './paginated.adapter'
import { PageAdapter } from './page.adapter'

import { Artist, TrackArtist } from '@common/types/spotify'
import {
Artist,
SdkArtist,
SdkSimplifiedArtist,
SimplifiedArtist,
} from '@common/types/spotify'

@Injectable()
export class ArtistsAdapter {
constructor(private readonly paginatedAdapter: PaginatedAdapter) {}
constructor(private readonly pageAdapter: PageAdapter) {}

public adapt(data: SpotifyArtist[]): Artist[]
public adapt(data: SimplifiedArtist[]): TrackArtist[]
public adapt(data: SpotifyArtist): Artist
public adapt(data: SimplifiedArtist): TrackArtist
public adapt(data: Page<SpotifyArtist>): Page<Artist>
public adapt(data: SdkArtist[]): Artist[]
public adapt(data: SdkSimplifiedArtist[]): SimplifiedArtist[]
public adapt(data: SdkArtist): Artist
public adapt(data: SdkSimplifiedArtist): SimplifiedArtist
public adapt(data: Page<SdkArtist>): Page<Artist>

adapt(
data:
| SpotifyArtist
| SimplifiedArtist
| (SpotifyArtist | SimplifiedArtist)[]
| Page<SpotifyArtist>
| SdkArtist
| SdkSimplifiedArtist
| (SdkArtist | SdkSimplifiedArtist)[]
| Page<SdkArtist>
) {
if (Array.isArray(data)) return this.adaptArtists(data)

if ('offset' in data) return this.adaptPaginatedArtists(data)
if ('offset' in data) return this.adaptArtistsPage(data)

return this.adaptArtist(data)
}

adaptArtist({
adaptArtist = ({
name,
id,
external_urls: { spotify: href },
...rest
}: SpotifyArtist | SimplifiedArtist): Artist | TrackArtist {
console.log(href)

return {
id,
name,
href,
...('genres' in rest && {
genres: rest.genres,
images: rest.images,
popularity: rest.popularity,
}),
}
}
}: SdkArtist | SdkSimplifiedArtist): Artist | SimplifiedArtist => ({
id,
name,
href,
...('genres' in rest && {
genres: rest.genres,
images: rest.images,
popularity: rest.popularity,
}),
})

adaptArtists(
artists: (SpotifyArtist | SimplifiedArtist)[]
): (Artist | TrackArtist)[] {
artists: (SdkArtist | SdkSimplifiedArtist)[]
): (Artist | SimplifiedArtist)[] {
return artists.map(artist => this.adaptArtist(artist))
}

adaptPaginatedArtists(data: Page<SpotifyArtist>) {
return this.paginatedAdapter.adapt(data, artists =>
this.adaptArtists(artists)
)
adaptArtistsPage(data: Page<SdkArtist>) {
return this.pageAdapter.adapt(data, artists => this.adaptArtists(artists))
}
}
6 changes: 3 additions & 3 deletions src/common/adapters/audio-features.adapter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Test } from '@nestjs/testing'

import { AudioFeaturesAdapter } from './audio-features.adapter'

import { audioFeaturesMock, spotifyAudioFeaturesMock } from '@common/mocks'
import { audioFeaturesMock, sdkAudioFeaturesMock } from '@common/mocks'

describe('AudioFeaturesAdapter', () => {
let audioFeaturesAdapter: AudioFeaturesAdapter
Expand All @@ -20,13 +20,13 @@ describe('AudioFeaturesAdapter', () => {
})

test('should adapt a single audio feature', () => {
expect(audioFeaturesAdapter.adapt(spotifyAudioFeaturesMock)).toEqual(
expect(audioFeaturesAdapter.adapt(sdkAudioFeaturesMock)).toEqual(
audioFeaturesMock
)
})

test('should adapt an array of audio features', () => {
expect(audioFeaturesAdapter.adapt([spotifyAudioFeaturesMock])).toEqual([
expect(audioFeaturesAdapter.adapt([sdkAudioFeaturesMock])).toEqual([
audioFeaturesMock,
])
})
Expand Down
11 changes: 5 additions & 6 deletions src/common/adapters/audio-features.adapter.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { Injectable } from '@nestjs/common'
import { AudioFeatures as SpotifyAudioFeatures } from '@spotify/web-api-ts-sdk'

import { AudioFeatures } from '@common/types/spotify'
import { AudioFeatures, SdkAudioFeatures } from '@common/types/spotify'

@Injectable()
export class AudioFeaturesAdapter {
public adapt(data: SpotifyAudioFeatures[]): AudioFeatures[]
public adapt(data: SpotifyAudioFeatures): AudioFeatures
public adapt(data: SdkAudioFeatures[]): AudioFeatures[]
public adapt(data: SdkAudioFeatures): AudioFeatures

adapt(data: SpotifyAudioFeatures | SpotifyAudioFeatures[]) {
adapt(data: SdkAudioFeatures | SdkAudioFeatures[]) {
if (Array.isArray(data))
return data.map(audioFeatures => this.adaptAudioFeatures(audioFeatures))

Expand All @@ -29,7 +28,7 @@ export class AudioFeaturesAdapter {
mode,
key,
valence,
}: SpotifyAudioFeatures): AudioFeatures => ({
}: SdkAudioFeatures): AudioFeatures => ({
id,
trackHref: track_href,
danceability,
Expand Down
6 changes: 3 additions & 3 deletions src/common/adapters/devices.adapter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Test } from '@nestjs/testing'

import { DevicesAdapter } from './devices.adapter'

import { deviceMock, spotifyDeviceMock } from '@common/mocks'
import { deviceMock, sdkDeviceMock } from '@common/mocks'

describe('DevicesAdapter', () => {
let devicesAdapter: DevicesAdapter
Expand All @@ -20,10 +20,10 @@ describe('DevicesAdapter', () => {
})

test('should adapt a single device', () => {
expect(devicesAdapter.adapt(spotifyDeviceMock)).toEqual(deviceMock)
expect(devicesAdapter.adapt(sdkDeviceMock)).toEqual(deviceMock)
})

test('should adapt an array of devices', () => {
expect(devicesAdapter.adapt([spotifyDeviceMock])).toEqual([deviceMock])
expect(devicesAdapter.adapt([sdkDeviceMock])).toEqual([deviceMock])
})
})
11 changes: 5 additions & 6 deletions src/common/adapters/devices.adapter.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { Injectable } from '@nestjs/common'
import { Device as SpotifyDevice } from '@spotify/web-api-ts-sdk'

import { Device } from '@common/types/spotify'
import { Device, SdkDevice } from '@common/types/spotify'

@Injectable()
export class DevicesAdapter {
public adapt(data: SpotifyDevice[]): Device[]
public adapt(data: SpotifyDevice): Device
public adapt(data: SdkDevice[]): Device[]
public adapt(data: SdkDevice): Device

adapt(data: SpotifyDevice | SpotifyDevice[]) {
adapt(data: SdkDevice | SdkDevice[]) {
if (Array.isArray(data)) return data.map(device => this.adaptDevice(device))

return this.adaptDevice(data)
Expand All @@ -22,7 +21,7 @@ export class DevicesAdapter {
is_private_session: isPrivateSession,
is_restricted: isRestricted,
volume_percent: volumePercent,
}: SpotifyDevice): Device => ({
}: SdkDevice): Device => ({
id,
name,
type,
Expand Down
6 changes: 3 additions & 3 deletions src/common/adapters/genres.adapter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Test } from '@nestjs/testing'

import { GenresAdapter } from './genres.adapter'

import { spotifyArtistMock, topGenresMock } from '@common/mocks'
import { sdkArtistMock, topGenresMock } from '@common/mocks'

describe('GenresAdapter', () => {
let genresAdapter: GenresAdapter
Expand All @@ -20,10 +20,10 @@ describe('GenresAdapter', () => {
})

test('should adapt a single artist', () => {
expect(genresAdapter.adapt([spotifyArtistMock])).toEqual(topGenresMock)
expect(genresAdapter.adapt([sdkArtistMock])).toEqual(topGenresMock)
})

test('should adapt an array of artists', () => {
expect(genresAdapter.adapt([spotifyArtistMock])).toEqual(topGenresMock)
expect(genresAdapter.adapt([sdkArtistMock])).toEqual(topGenresMock)
})
})
5 changes: 2 additions & 3 deletions src/common/adapters/genres.adapter.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { Injectable } from '@nestjs/common'
import { Artist as SpotifyArtist } from '@spotify/web-api-ts-sdk'

import { getMostFrequentItems } from '../utils'

import { Genres } from '@common/types/spotify'
import { Genres, SdkArtist } from '@common/types/spotify'

@Injectable()
export class GenresAdapter {
adapt(artists: SpotifyArtist[], limit = 20): Genres {
adapt(artists: SdkArtist[], limit = 20): Genres {
return {
genres: getMostFrequentItems(
artists.flatMap(({ genres }) => genres),
Expand Down
10 changes: 10 additions & 0 deletions src/common/adapters/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
export * from './adapters.module'
export * from './adapters.service'

export * from './artists.adapter'
export * from './audio-features.adapter'
export * from './devices.adapter'
export * from './genres.adapter'
export * from './page.adapter'
export * from './tracks.adapter'
export * from './playback-state.adapter'
export * from './profile.adapter'
export * from './secret-data.adapter'
Loading

0 comments on commit b827112

Please sign in to comment.