From 560c2072840517979f349618607a1367e17766a7 Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Wed, 30 Oct 2024 10:24:23 -0400 Subject: [PATCH] add ts types, change spotify link to link and account tokens --- src/jukebox/dto/add-jukebox-link.dto.ts | 7 +- src/jukebox/dto/create-jukebox.dto.ts | 2 +- src/jukebox/dto/jukebox.dto.ts | 52 +++++---- src/jukebox/dto/update-jukebox.dto.ts | 10 +- src/jukebox/entities/jukebox.entity.ts | 37 +++++-- src/jukebox/jukebox.controller.ts | 49 ++++++--- src/jukebox/jukebox.module.ts | 4 +- src/jukebox/jukebox.service.ts | 103 +++++++++++------- src/jukebox/tests/jukebox.controller.spec.ts | 12 +- src/jukebox/tests/jukebox.service.spec.ts | 12 +- src/network/network.service.ts | 4 +- ...ify-link.dto.ts => spotify-account.dto.ts} | 29 +++-- ...nk.entity.ts => spotify-account.entity.ts} | 10 +- src/spotify/spotify.module.ts | 4 +- src/spotify/spotify.service.ts | 18 +-- src/spotify/tests/spotify.controller.spec.ts | 6 +- src/spotify/tests/spotify.service.spec.ts | 8 +- src/types/jukebox.d.ts | 15 +++ src/types/spotify-auth.d.ts | 9 ++ src/types/{index.d.ts => user.d.ts} | 4 +- src/utils/mock/mockUser.ts | 4 +- 21 files changed, 255 insertions(+), 144 deletions(-) rename src/spotify/dto/{spotify-link.dto.ts => spotify-account.dto.ts} (54%) rename src/spotify/entities/{spotify-link.entity.ts => spotify-account.entity.ts} (65%) create mode 100644 src/types/jukebox.d.ts create mode 100644 src/types/spotify-auth.d.ts rename src/types/{index.d.ts => user.d.ts} (58%) diff --git a/src/jukebox/dto/add-jukebox-link.dto.ts b/src/jukebox/dto/add-jukebox-link.dto.ts index 14cc4a4..3d99b31 100644 --- a/src/jukebox/dto/add-jukebox-link.dto.ts +++ b/src/jukebox/dto/add-jukebox-link.dto.ts @@ -1,8 +1,11 @@ import { ApiProperty } from '@nestjs/swagger' import { IsEmail } from 'class-validator' -export class AddJukeboxLinkDto { +export class AddJukeboxLinkDto implements Partial { + @ApiProperty() + type: JukeboxLinkType + @ApiProperty() @IsEmail() - spotifyEmail: string + email: string } diff --git a/src/jukebox/dto/create-jukebox.dto.ts b/src/jukebox/dto/create-jukebox.dto.ts index f37c817..c9e1920 100644 --- a/src/jukebox/dto/create-jukebox.dto.ts +++ b/src/jukebox/dto/create-jukebox.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger' import { IsNumber, IsString } from 'class-validator' -export class CreateJukeboxDto { +export class CreateJukeboxDto implements Partial { @ApiProperty() @IsString() name: string diff --git a/src/jukebox/dto/jukebox.dto.ts b/src/jukebox/dto/jukebox.dto.ts index d89c4a6..f45f277 100644 --- a/src/jukebox/dto/jukebox.dto.ts +++ b/src/jukebox/dto/jukebox.dto.ts @@ -1,41 +1,53 @@ import { ApiProperty } from '@nestjs/swagger' import { Expose } from 'class-transformer' import { BaseDto } from 'src/config/dtos' -import { SpotifyLinkDto, SpotifyLinkNestedDto } from 'src/spotify/dto/spotify-link.dto' -import { Jukebox } from '../entities/jukebox.entity' -export class JukeboxDto extends BaseDto { +export class JukeboxLinkDto implements IJukeboxLink { @Expose() @ApiProperty() id: number @Expose() @ApiProperty() - name: string + type: JukeboxLinkType @Expose() @ApiProperty() - club_id: number + email: string + + @Expose() + @ApiProperty() + active: boolean +} +export class JukeboxDto extends BaseDto implements IJukebox { @Expose() @ApiProperty() - spotify_links: SpotifyLinkNestedDto[] + id: number + + @Expose() + @ApiProperty() + name: string + + @Expose() + @ApiProperty() + club_id: number @Expose() @ApiProperty() - active_spotify_link?: SpotifyLinkDto + links: JukeboxLinkDto[] - static serialize(entity: Jukebox): JukeboxDto { - return { - ...super.serialize(entity), - name: entity.name, - club_id: entity.club_id, - spotify_links: - entity.spotify_link_assignments?.map((assignment) => ({ - spotify_email: assignment.spotify_link.spotify_email, - })) ?? [], - active_spotify_link: entity.spotify_link_assignments?.find((assignment) => assignment.active) - ?.spotify_link, - } - } + // static serialize(entity: Jukebox): JukeboxDto { + // return { + // ...super.serialize(entity), + // name: entity.name, + // club_id: entity.club_id, + // links: + // entity.spotify_link_assignments?.map((assignment) => ({ + // type: 'spotify', + // email: assignment.spotify_link.spotify_email, + // active: assignment.active, + // })) ?? [], + // } + // } } diff --git a/src/jukebox/dto/update-jukebox.dto.ts b/src/jukebox/dto/update-jukebox.dto.ts index c836a66..c42ebf3 100644 --- a/src/jukebox/dto/update-jukebox.dto.ts +++ b/src/jukebox/dto/update-jukebox.dto.ts @@ -1,14 +1,8 @@ -import { ApiProperty, PartialType } from '@nestjs/swagger' -import { SpotifyLinkNestedDto } from 'src/spotify/dto/spotify-link.dto' -import { CreateJukeboxDto } from './create-jukebox.dto' +import { ApiProperty } from '@nestjs/swagger' import { IsOptional } from 'class-validator' -export class UpdateJukeboxDto { +export class UpdateJukeboxDto implements Partial { @IsOptional() @ApiProperty() name?: string - - @IsOptional() - @ApiProperty() - active_spotify_link?: SpotifyLinkNestedDto } diff --git a/src/jukebox/entities/jukebox.entity.ts b/src/jukebox/entities/jukebox.entity.ts index 381150a..cf2801a 100644 --- a/src/jukebox/entities/jukebox.entity.ts +++ b/src/jukebox/entities/jukebox.entity.ts @@ -1,5 +1,5 @@ import { BaseEntity } from 'src/config/entities' -import { SpotifyLink } from 'src/spotify/entities/spotify-link.entity' +import { SpotifyAccount } from 'src/spotify/entities/spotify-account.entity' import { Column, Entity, @@ -9,6 +9,7 @@ import { PrimaryColumn, PrimaryGeneratedColumn, } from 'typeorm' +import { JukeboxDto, JukeboxLinkDto } from '../dto/jukebox.dto' @Entity('jukebox') export class Jukebox extends BaseEntity { @@ -21,26 +22,46 @@ export class Jukebox extends BaseEntity { @Column() club_id: number - @OneToMany(() => JukeboxSpotifyLinkAssignment, (assignment) => assignment.jukebox) - spotify_link_assignments: JukeboxSpotifyLinkAssignment[] + @OneToMany(() => JukeboxLinkAssignment, (assignment) => assignment.jukebox) + link_assignments: JukeboxLinkAssignment[] + + serialize(): JukeboxDto { + return { + id: this.id, + name: this.name, + club_id: this.club_id, + links: this.link_assignments?.map((assignment) => assignment.serialize()) ?? [], + created_at: this.created_at, + updated_at: this.updated_at, + } + } } -@Entity('jukebox_spotify_link_assignment') -export class JukeboxSpotifyLinkAssignment extends BaseEntity { +@Entity('jukebox_link_assignment') +export class JukeboxLinkAssignment extends BaseEntity { @PrimaryColumn({ name: 'jukebox_id' }) jukebox_id: number - @ManyToOne(() => Jukebox, (jukebox) => jukebox.spotify_link_assignments) + @ManyToOne(() => Jukebox, (jukebox) => jukebox.link_assignments) @JoinColumn({ name: 'jukebox_id' }) jukebox: Jukebox @PrimaryColumn({ name: 'spotify_link_id' }) spotify_link_id: number - @ManyToOne(() => SpotifyLink, (link) => link.jukebox_assignments) + @ManyToOne(() => SpotifyAccount, (link) => link.jukebox_assignments) @JoinColumn({ name: 'spotify_link_id' }) - spotify_link: SpotifyLink + spotify_link: SpotifyAccount @Column({ default: false }) active: boolean + + serialize(): JukeboxLinkDto { + return { + id: this.id, + type: 'spotify', + email: this.spotify_link.spotify_email, + active: this.active, + } + } } diff --git a/src/jukebox/jukebox.controller.ts b/src/jukebox/jukebox.controller.ts index 476d8ae..8ce2361 100644 --- a/src/jukebox/jukebox.controller.ts +++ b/src/jukebox/jukebox.controller.ts @@ -10,11 +10,10 @@ import { } from '@nestjs/common' import { ApiTags } from '@nestjs/swagger' import { CurrentUser } from '../auth/current-user.decorator' -import { SpotifyLinkDto } from '../spotify/dto/spotify-link.dto' import { SpotifyService } from '../spotify/spotify.service' import { AddJukeboxLinkDto } from './dto/add-jukebox-link.dto' import { CreateJukeboxDto } from './dto/create-jukebox.dto' -import { JukeboxDto } from './dto/jukebox.dto' +import { JukeboxDto, JukeboxLinkDto } from './dto/jukebox.dto' import { UpdateJukeboxDto } from './dto/update-jukebox.dto' import { JukeboxService } from './jukebox.service' @@ -29,19 +28,19 @@ export class JukeboxController { @Post('jukeboxes/') async create(@Body() createJukeboxDto: CreateJukeboxDto): Promise { const jbx = await this.jukeboxService.create(createJukeboxDto) - return JukeboxDto.serialize(jbx) + return jbx.serialize() } @Get('jukeboxes/') async findAll(): Promise { const jbxs = await this.jukeboxService.findAll() - return jbxs.map((jbx) => JukeboxDto.serialize(jbx)) + return jbxs.map((jbx) => jbx.serialize()) } @Get('jukeboxes/:id/') async findOne(@Param('id') id: number): Promise { const jbx = await this.jukeboxService.findOne(id) - return JukeboxDto.serialize(jbx) + return jbx.serialize() } @Patch('jukeboxes/:id/') @@ -50,44 +49,62 @@ export class JukeboxController { @Body() updateJukeboxDto: UpdateJukeboxDto, ): Promise { const jbx = await this.jukeboxService.update(id, updateJukeboxDto) - return JukeboxDto.serialize(jbx) + return jbx.serialize() } @Delete('jukeboxes/:id/') async remove(@Param('id') id: number): Promise { const jbx = await this.jukeboxService.remove(id) - return JukeboxDto.serialize(jbx) + return jbx.serialize() } @Get('/:jukebox_id/links/') - getJukeboxLinks(@Param('jukebox_id') jukeboxId: number): Promise { - return this.jukeboxService.getJukeboxSpotifyLinks(jukeboxId) + getJukeboxLinks(@Param('jukebox_id') jukeboxId: number): Promise { + return this.jukeboxService.getJukeboxLinks(jukeboxId) } @Post('/:jukebox_id/links/') async addLinkToJukebox( @CurrentUser() user: IUser, @Param('jukebox_id') jukeboxId: number, - @Body() spotifyLink: AddJukeboxLinkDto, - ): Promise { - const link = await this.spotifyService.findOneUserLink(user.id, spotifyLink.spotifyEmail) + @Body() jukeboxLink: AddJukeboxLinkDto, + ): Promise { + const link = await this.spotifyService.findOneUserLink(user.id, jukeboxLink.email) if (!link) { throw new NotFoundException( - `Spotify link with email ${spotifyLink.spotifyEmail} not found for current user.`, + `Spotify link with email ${jukeboxLink.email} not found for current user.`, ) } - await this.jukeboxService.addSpotifyLinkToJukebox(jukeboxId, link) + return await this.jukeboxService.addLinkToJukebox(jukeboxId, link) + } + @Delete('/:jukebox_id/links/:id/') + async deleteJukeboxLink(@Param('jukebox_id') jukeboxId: number, @Param('id') linkId: number) { + const link = await this.jukeboxService.removeJukeboxLink(jukeboxId, linkId) return link } @Get('/:jukebox_id/active-link/') - async refreshActiveJukeboxLink(@Param('jukebox_id') jukeboxId: number) { + async getActiveJukeboxLink(@Param('jukebox_id') jukeboxId: number) { const link = await this.jukeboxService.getJukeboxActiveSpotifyLink(jukeboxId) - const refreshed = await this.spotifyService.refreshSpotifyLink(link) + if (!link) { + return + } + const refreshed = await this.spotifyService.refreshSpotifyLink(link) return refreshed } + + @Post('/:jukebox_id/active-link/') + async setActiveJukeboxLink( + @Param('jukebox_id') jukeboxId: number, + @Body() jukeboxLink: AddJukeboxLinkDto, + ) { + const link = await this.jukeboxService.findJukeboxLink(jukeboxId, jukeboxLink) + const activeLink = await this.jukeboxService.setActiveLink(jukeboxId, link.id) + + return await this.spotifyService.refreshSpotifyLink(activeLink.spotify_link) + } } diff --git a/src/jukebox/jukebox.module.ts b/src/jukebox/jukebox.module.ts index 0fe2001..f96d16a 100644 --- a/src/jukebox/jukebox.module.ts +++ b/src/jukebox/jukebox.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common' import { TypeOrmModule } from '@nestjs/typeorm' import { SpotifyModule } from '../spotify/spotify.module' -import { Jukebox, JukeboxSpotifyLinkAssignment } from './entities/jukebox.entity' +import { Jukebox, JukeboxLinkAssignment } from './entities/jukebox.entity' import { JukeboxController } from './jukebox.controller' import { JukeboxService } from './jukebox.service' @@ -10,7 +10,7 @@ import { JukeboxService } from './jukebox.service' providers: [JukeboxService], imports: [ // MongooseModule.forFeature([{ name: Jukebox.name, schema: JukeboxSchema }]), - TypeOrmModule.forFeature([Jukebox, JukeboxSpotifyLinkAssignment]), + TypeOrmModule.forFeature([Jukebox, JukeboxLinkAssignment]), SpotifyModule, ], exports: [JukeboxService], diff --git a/src/jukebox/jukebox.service.ts b/src/jukebox/jukebox.service.ts index 6083732..721faf3 100644 --- a/src/jukebox/jukebox.service.ts +++ b/src/jukebox/jukebox.service.ts @@ -1,17 +1,19 @@ import { Injectable, NotFoundException } from '@nestjs/common' import { InjectRepository } from '@nestjs/typeorm' -import { Repository } from 'typeorm' -import { SpotifyLink } from '../spotify/entities/spotify-link.entity' +import { Not, Repository } from 'typeorm' +import { SpotifyAccount } from '../spotify/entities/spotify-account.entity' +import { AddJukeboxLinkDto } from './dto/add-jukebox-link.dto' import { CreateJukeboxDto } from './dto/create-jukebox.dto' +import { JukeboxLinkDto } from './dto/jukebox.dto' import { UpdateJukeboxDto } from './dto/update-jukebox.dto' -import { Jukebox, JukeboxSpotifyLinkAssignment } from './entities/jukebox.entity' +import { Jukebox, JukeboxLinkAssignment } from './entities/jukebox.entity' @Injectable() export class JukeboxService { constructor( @InjectRepository(Jukebox) private repo: Repository, - @InjectRepository(JukeboxSpotifyLinkAssignment) - private assignmentRepo: Repository, + @InjectRepository(JukeboxLinkAssignment) + private assignmentRepo: Repository, ) {} create(createJukeboxDto: CreateJukeboxDto) { @@ -21,14 +23,14 @@ export class JukeboxService { findAll() { return this.repo.find({ - relations: ['spotify_link_assignments', 'spotify_link_assignments.spotify_link'], + relations: ['link_assignments', 'link_assignments.spotify_link'], }) } async findOne(id: number) { const jukebox = await this.repo.findOne({ where: { id }, - relations: ['spotify_link_assignments', 'spotify_link_assignments.spotify_link'], + relations: ['link_assignments', 'link_assignments.spotify_link'], }) if (!jukebox) { throw new NotFoundException('Jukebox not found') @@ -39,7 +41,6 @@ export class JukeboxService { async update(id: number, updateJukeboxDto: UpdateJukeboxDto) { const jukebox = await this.findOne(id) - const spotifyEmail = updateJukeboxDto.active_spotify_link.spotify_email if (!jukebox) { throw new NotFoundException(`Jukebox with id ${id} not found`) @@ -49,28 +50,6 @@ export class JukeboxService { jukebox.name = updateJukeboxDto.name } - if ('active_spotify_link' in updateJukeboxDto) { - const assignment = jukebox.spotify_link_assignments.find( - (a) => a.spotify_link.spotify_email === spotifyEmail, - ) - - if (!assignment) { - throw new NotFoundException( - `Unable to find a linked Spotify account with email ${spotifyEmail}`, - ) - } - - const deactivateAssignments = jukebox.spotify_link_assignments.filter((a) => a.active) - - for (const dAssignment of deactivateAssignments) { - dAssignment.active = false - await this.assignmentRepo.save(dAssignment) - } - - assignment.active = true - this.assignmentRepo.save(assignment) - } - this.repo.save(jukebox) return jukebox @@ -88,27 +67,77 @@ export class JukeboxService { return jukebox } - async getJukeboxSpotifyLinks(jukeboxId: number) { + async getJukeboxLinks(jukeboxId: number): Promise { const jukebox = await this.findOne(jukeboxId) - return jukebox.spotify_link_assignments.map((assignments) => assignments.spotify_link) + return jukebox.link_assignments.map((assignment) => assignment.serialize()) + } + + async findJukeboxLink(jukeboxId: number, jukeboxLink: AddJukeboxLinkDto) { + const link = await this.assignmentRepo.findOne({ + where: { + jukebox_id: jukeboxId, + spotify_link: { spotify_email: jukeboxLink.email }, + }, + }) + + if (!link) { + throw new NotFoundException(`Jukebox link not found with email ${jukeboxLink.email}.`) + } + + return link } - async addSpotifyLinkToJukebox(jukeboxId: number, spotifyLink: SpotifyLink) { + async removeJukeboxLink(jukeboxId: number, linkId: number) { + const link = await this.assignmentRepo.findOne({ where: { jukebox_id: jukeboxId, id: linkId } }) + if (!link) { + throw new NotFoundException(`Jukebox link not found with id ${linkId}.`) + } + + await this.assignmentRepo.delete({ jukebox_id: jukeboxId, id: linkId }) + + return link + } + + async setActiveLink(jukeboxId: number, linkId: number) { + await this.assignmentRepo.update( + { jukebox_id: jukeboxId, active: true, id: Not(linkId) }, + { active: false }, + ) + const assignment = await this.assignmentRepo.findOne({ + where: { jukebox_id: jukeboxId, id: linkId }, + relations: ['spotify_link'], + }) + + if (!assignment) { + throw new NotFoundException('Spotify assignment not found.') + } + + assignment.active = true + await assignment.save() + + return assignment + } + + async addLinkToJukebox(jukeboxId: number, spotifyLink: SpotifyAccount): Promise { const jukebox = await this.findOne(jukeboxId) const assignment = this.assignmentRepo.create({ jukebox_id: jukebox.id, + jukebox: jukebox, spotify_link_id: spotifyLink.id, + spotify_link: spotifyLink, }) - await this.assignmentRepo.save(assignment) - return jukebox + const record = await this.assignmentRepo.save(assignment) + await this.setActiveLink(jukebox.id, record.id) + + return assignment.serialize() } - async getJukeboxActiveSpotifyLink(jukeboxId: number): Promise { + async getJukeboxActiveSpotifyLink(jukeboxId: number): Promise { const jukebox = await this.findOne(jukeboxId) - const assignment = jukebox.spotify_link_assignments.find((lnk) => lnk.active) + const assignment = jukebox.link_assignments.find((lnk) => lnk.active) if (!assignment) { return diff --git a/src/jukebox/tests/jukebox.controller.spec.ts b/src/jukebox/tests/jukebox.controller.spec.ts index 4156d07..c81b589 100644 --- a/src/jukebox/tests/jukebox.controller.spec.ts +++ b/src/jukebox/tests/jukebox.controller.spec.ts @@ -2,12 +2,12 @@ import type { TestingModule } from '@nestjs/testing' import { Test } from '@nestjs/testing' import { getRepositoryToken } from '@nestjs/typeorm' import { NetworkModule } from 'src/network/network.module' -import { SpotifyLink } from 'src/spotify/entities/spotify-link.entity' +import { SpotifyAccount } from 'src/spotify/entities/spotify-account.entity' import { SpotifyService } from 'src/spotify/spotify.service' import type { MockType } from 'src/utils' import { AxiosProvider } from 'src/utils/providers/axios.provider' import type { Repository } from 'typeorm' -import { Jukebox, JukeboxSpotifyLinkAssignment } from '../entities/jukebox.entity' +import { Jukebox, JukeboxLinkAssignment } from '../entities/jukebox.entity' import { JukeboxController } from '../jukebox.controller' import { JukeboxService } from '../jukebox.service' @@ -16,10 +16,10 @@ describe('JukeboxController', () => { beforeEach(async () => { const mockRepo: () => MockType> = jest.fn(() => ({})) - const mockAssignmentRepo: () => MockType> = jest.fn( + const mockAssignmentRepo: () => MockType> = jest.fn( () => ({}), ) - const mockSpotifyLinkRepo: () => MockType> = jest.fn(() => ({})) + const mockSpotifyLinkRepo: () => MockType> = jest.fn(() => ({})) const module: TestingModule = await Test.createTestingModule({ imports: [NetworkModule], @@ -33,11 +33,11 @@ describe('JukeboxController', () => { useFactory: mockRepo, }, { - provide: getRepositoryToken(JukeboxSpotifyLinkAssignment), + provide: getRepositoryToken(JukeboxLinkAssignment), useFactory: mockAssignmentRepo, }, { - provide: getRepositoryToken(SpotifyLink), + provide: getRepositoryToken(SpotifyAccount), useFactory: mockSpotifyLinkRepo, }, ], diff --git a/src/jukebox/tests/jukebox.service.spec.ts b/src/jukebox/tests/jukebox.service.spec.ts index 047964e..eb77ff8 100644 --- a/src/jukebox/tests/jukebox.service.spec.ts +++ b/src/jukebox/tests/jukebox.service.spec.ts @@ -1,10 +1,10 @@ import type { TestingModule } from '@nestjs/testing' import { Test } from '@nestjs/testing' import { getRepositoryToken } from '@nestjs/typeorm' -import { SpotifyLink } from 'src/spotify/entities/spotify-link.entity' +import { SpotifyAccount } from 'src/spotify/entities/spotify-account.entity' import type { MockType } from 'src/utils' import type { Repository } from 'typeorm' -import { Jukebox, JukeboxSpotifyLinkAssignment } from '../entities/jukebox.entity' +import { Jukebox, JukeboxLinkAssignment } from '../entities/jukebox.entity' import { JukeboxService } from '../jukebox.service' describe('JukeboxService', () => { @@ -12,10 +12,10 @@ describe('JukeboxService', () => { beforeEach(async () => { const mockRepo: () => MockType> = jest.fn(() => ({})) - const mockAssignmentRepo: () => MockType> = jest.fn( + const mockAssignmentRepo: () => MockType> = jest.fn( () => ({}), ) - const mockSpotifyLinkRepo: () => MockType> = jest.fn(() => ({})) + const mockSpotifyLinkRepo: () => MockType> = jest.fn(() => ({})) const module: TestingModule = await Test.createTestingModule({ providers: [ @@ -25,11 +25,11 @@ describe('JukeboxService', () => { useFactory: mockRepo, }, { - provide: getRepositoryToken(JukeboxSpotifyLinkAssignment), + provide: getRepositoryToken(JukeboxLinkAssignment), useFactory: mockAssignmentRepo, }, { - provide: getRepositoryToken(SpotifyLink), + provide: getRepositoryToken(SpotifyAccount), useFactory: mockSpotifyLinkRepo, }, ], diff --git a/src/network/network.service.ts b/src/network/network.service.ts index 694d36a..bb9f56a 100644 --- a/src/network/network.service.ts +++ b/src/network/network.service.ts @@ -57,8 +57,8 @@ export class NetworkService { return { id: +res.data.id, email: res.data.email ?? '', - firstName: res.data.first_name, - lastName: res.data.last_name, + first_name: res.data.first_name, + last_name: res.data.last_name, } } } diff --git a/src/spotify/dto/spotify-link.dto.ts b/src/spotify/dto/spotify-account.dto.ts similarity index 54% rename from src/spotify/dto/spotify-link.dto.ts rename to src/spotify/dto/spotify-account.dto.ts index ce5932e..6aa3492 100644 --- a/src/spotify/dto/spotify-link.dto.ts +++ b/src/spotify/dto/spotify-account.dto.ts @@ -1,20 +1,23 @@ -import { ApiProperty, PartialType } from '@nestjs/swagger' +import { ApiProperty } from '@nestjs/swagger' import { Expose } from 'class-transformer' import { BaseDto } from 'src/config/dtos' import { SpotifyTokensDto } from './spotify-tokens.dto' -export class CreateSpotifyLinkDto { +export class CreateSpotifyAccountDto { user_id: number spotify_email: string tokens: SpotifyTokensDto } -export class UpdateSpotifyLinkDto { +export class UpdateSpotifyAccountDto { access_token: string expires_in: number } -export class SpotifyLinkDto extends BaseDto { +export class SpotifyAccountDto extends BaseDto implements ISpotifyAccount { + @Expose() + id: number + @Expose() @ApiProperty() access_token: string @@ -37,8 +40,16 @@ export class SpotifyLinkDto extends BaseDto { token_type: string } -export class SpotifyLinkNestedDto { - @Expose() - @ApiProperty() - spotify_email: string -} +// export class SpotifyLinkNestedDto implements IJukeboxLink { +// @Expose() +// @ApiProperty() +// type: JukeboxLinkType + +// @Expose() +// @ApiProperty() +// email: string + +// @Expose() +// @ApiProperty() +// active: boolean +// } diff --git a/src/spotify/entities/spotify-link.entity.ts b/src/spotify/entities/spotify-account.entity.ts similarity index 65% rename from src/spotify/entities/spotify-link.entity.ts rename to src/spotify/entities/spotify-account.entity.ts index dc5afce..5977969 100644 --- a/src/spotify/entities/spotify-link.entity.ts +++ b/src/spotify/entities/spotify-account.entity.ts @@ -1,9 +1,9 @@ import { BaseEntity } from 'src/config/entities' -import { JukeboxSpotifyLinkAssignment } from 'src/jukebox/entities/jukebox.entity' +import { JukeboxLinkAssignment } from 'src/jukebox/entities/jukebox.entity' import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm' @Entity('spotify_link') -export class SpotifyLink extends BaseEntity { +export class SpotifyAccount extends BaseEntity { @PrimaryGeneratedColumn() id: number @@ -28,8 +28,8 @@ export class SpotifyLink extends BaseEntity { @Column() token_type: string - @OneToMany(() => JukeboxSpotifyLinkAssignment, (assignment) => assignment.spotify_link) - jukebox_assignments: JukeboxSpotifyLinkAssignment[] + @OneToMany(() => JukeboxLinkAssignment, (assignment) => assignment.spotify_link) + jukebox_assignments: JukeboxLinkAssignment[] isExpired() { return this.expires_at.getTime() <= Date.now() @@ -40,6 +40,6 @@ export class SpotifyLink extends BaseEntity { } } -export const isSpotifyLink = (obj: any): obj is SpotifyLink => { +export const isSpotifyLink = (obj: any): obj is SpotifyAccount => { return Object.keys(obj).includes('id') } diff --git a/src/spotify/spotify.module.ts b/src/spotify/spotify.module.ts index 75c773c..45f93af 100644 --- a/src/spotify/spotify.module.ts +++ b/src/spotify/spotify.module.ts @@ -3,12 +3,12 @@ import { TypeOrmModule } from '@nestjs/typeorm' import { NetworkModule } from 'src/network/network.module' import { NetworkService } from '../network/network.service' import { AxiosProvider } from '../utils/providers/axios.provider' -import { SpotifyLink } from './entities/spotify-link.entity' +import { SpotifyAccount } from './entities/spotify-account.entity' import { SpotifyController } from './spotify.controller' import { SpotifyService } from './spotify.service' @Module({ - imports: [NetworkModule, TypeOrmModule.forFeature([SpotifyLink])], + imports: [NetworkModule, TypeOrmModule.forFeature([SpotifyAccount])], controllers: [SpotifyController], providers: [SpotifyService, AxiosProvider, NetworkService], // imports: [MongooseModule.forFeature([{ name: SpotifyLink.name, schema: SpotifyLinkSchema }])], diff --git a/src/spotify/spotify.service.ts b/src/spotify/spotify.service.ts index 4d4a39b..1ef7590 100644 --- a/src/spotify/spotify.service.ts +++ b/src/spotify/spotify.service.ts @@ -10,14 +10,14 @@ import { SPOTIFY_SCOPES, } from 'src/config' import { Repository } from 'typeorm' -import { CreateSpotifyLinkDto, UpdateSpotifyLinkDto } from './dto/spotify-link.dto' +import { CreateSpotifyAccountDto, UpdateSpotifyAccountDto } from './dto/spotify-account.dto' import { SpotifyTokensDto } from './dto/spotify-tokens.dto' -import { isSpotifyLink, SpotifyLink } from './entities/spotify-link.entity' +import { isSpotifyLink, SpotifyAccount } from './entities/spotify-account.entity' @Injectable() export class SpotifyService { constructor( - @InjectRepository(SpotifyLink) private repo: Repository, + @InjectRepository(SpotifyAccount) private repo: Repository, protected axios: Axios, ) {} @@ -102,12 +102,12 @@ export class SpotifyService { } public async refreshSpotifyLink( - link: { spotify_email: string } | SpotifyLink, - ): Promise { - let spotifyLink: SpotifyLink + link: { spotify_email: string } | SpotifyAccount, + ): Promise { + let spotifyLink: SpotifyAccount if (!isSpotifyLink(link)) { - spotifyLink = (await this.findLinkFromEmail(link.spotify_email)) as SpotifyLink + spotifyLink = (await this.findLinkFromEmail(link.spotify_email)) as SpotifyAccount } else { spotifyLink = link } @@ -143,7 +143,7 @@ export class SpotifyService { return spotifyLink } - private async createLink(createSpotifyLinkDto: CreateSpotifyLinkDto) { + private async createLink(createSpotifyLinkDto: CreateSpotifyAccountDto) { const { user_id: userId, spotify_email: spotifyEmail, tokens } = createSpotifyLinkDto const link = this.repo.create({ user_id: userId, spotify_email: spotifyEmail, ...tokens }) @@ -153,7 +153,7 @@ export class SpotifyService { return link } - private async updateLink(id: number, updateSpotifyLInkDto: UpdateSpotifyLinkDto) { + private async updateLink(id: number, updateSpotifyLInkDto: UpdateSpotifyAccountDto) { const link = await this.repo.findOneBy({ id }) Object.assign(link, updateSpotifyLInkDto) diff --git a/src/spotify/tests/spotify.controller.spec.ts b/src/spotify/tests/spotify.controller.spec.ts index 47ce323..f6d3608 100644 --- a/src/spotify/tests/spotify.controller.spec.ts +++ b/src/spotify/tests/spotify.controller.spec.ts @@ -5,7 +5,7 @@ import Axios from 'axios' import { NetworkModule } from 'src/network/network.module' import type { MockType } from 'src/utils' import type { Repository } from 'typeorm' -import { SpotifyLink } from '../entities/spotify-link.entity' +import { SpotifyAccount } from '../entities/spotify-account.entity' import { SpotifyController } from '../spotify.controller' import { SpotifyService } from '../spotify.service' @@ -13,7 +13,7 @@ describe('SpotifyController', () => { let controller: SpotifyController beforeEach(async () => { - const mockSpotifyLinkRepo: () => MockType> = jest.fn(() => ({})) + const mockSpotifyLinkRepo: () => MockType> = jest.fn(() => ({})) const module: TestingModule = await Test.createTestingModule({ imports: [NetworkModule], controllers: [SpotifyController], @@ -24,7 +24,7 @@ describe('SpotifyController', () => { useValue: Axios.create(), }, { - provide: getRepositoryToken(SpotifyLink), + provide: getRepositoryToken(SpotifyAccount), useFactory: mockSpotifyLinkRepo, }, ], diff --git a/src/spotify/tests/spotify.service.spec.ts b/src/spotify/tests/spotify.service.spec.ts index d2951d0..b16834a 100644 --- a/src/spotify/tests/spotify.service.spec.ts +++ b/src/spotify/tests/spotify.service.spec.ts @@ -6,24 +6,24 @@ import Axios from 'axios' import { Model } from 'mongoose' import type { MockType } from 'src/utils' import type { Repository } from 'typeorm' -import { SpotifyLink } from '../entities/spotify-link.entity' +import { SpotifyAccount } from '../entities/spotify-account.entity' import { SpotifyService } from '../spotify.service' describe('SpotifyService', () => { let service: SpotifyService beforeEach(async () => { - const mockSpotifyLinkRepo: () => MockType> = jest.fn(() => ({})) + const mockSpotifyLinkRepo: () => MockType> = jest.fn(() => ({})) const module: TestingModule = await Test.createTestingModule({ providers: [ SpotifyService, - { provide: getModelToken(SpotifyLink.name), useValue: Model }, + { provide: getModelToken(SpotifyAccount.name), useValue: Model }, { provide: Axios.Axios, useValue: Axios.create(), }, { - provide: getRepositoryToken(SpotifyLink), + provide: getRepositoryToken(SpotifyAccount), useFactory: mockSpotifyLinkRepo, }, ], diff --git a/src/types/jukebox.d.ts b/src/types/jukebox.d.ts new file mode 100644 index 0000000..2c1b729 --- /dev/null +++ b/src/types/jukebox.d.ts @@ -0,0 +1,15 @@ +declare interface IJukebox { + id: number + name: string + club_id: number + links: IJukeboxLink[] +} + +declare type JukeboxLinkType = 'spotify' + +declare interface IJukeboxLink { + id: number + type: JukeboxLinkType + email: string + active: boolean +} diff --git a/src/types/spotify-auth.d.ts b/src/types/spotify-auth.d.ts new file mode 100644 index 0000000..7aab3ff --- /dev/null +++ b/src/types/spotify-auth.d.ts @@ -0,0 +1,9 @@ +declare interface ISpotifyAccount { + id: number + access_token: string + user_id: number + spotify_email: string + expires_in: number + expires_at: Date + token_type: string +} diff --git a/src/types/index.d.ts b/src/types/user.d.ts similarity index 58% rename from src/types/index.d.ts rename to src/types/user.d.ts index f54847d..8451e28 100644 --- a/src/types/index.d.ts +++ b/src/types/user.d.ts @@ -1,6 +1,6 @@ declare interface IUser { id: number email: string - firstName: string - lastName: string + first_name: string + last_name: string } diff --git a/src/utils/mock/mockUser.ts b/src/utils/mock/mockUser.ts index 157b27b..a23ab74 100644 --- a/src/utils/mock/mockUser.ts +++ b/src/utils/mock/mockUser.ts @@ -1,6 +1,6 @@ export const mockUser: IUser = { id: 0, email: 'user@example.com', - firstName: 'John', - lastName: 'Doe', + first_name: 'John', + last_name: 'Doe', }