chore(api): update dependencies

This commit is contained in:
Julian Tölle 2020-05-02 17:17:20 +02:00
parent 05f230a7ce
commit d881a78757
37 changed files with 4804 additions and 2700 deletions

View file

@ -1,7 +1,7 @@
##################
## common
##################
FROM node:12-alpine as common
FROM node:14-alpine as common
LABEL org.label-schema.schema-version="1.0" \
org.label-schema.name="listory" \
stage="common"

7218
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"apps/**/*.ts\" \"libs/**/*.ts\"",
"format": "prettier --write \"src/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
@ -20,47 +20,47 @@
"test:e2e": "jest --config ./apps/listory/test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^6.7.2",
"@nestjs/config": "^0.1.0",
"@nestjs/core": "^6.7.2",
"@nestjs/jwt": "^6.1.1",
"@nestjs/passport": "^6.1.1",
"@nestjs/platform-express": "^6.7.2",
"@nestjs/schedule": "^0.2.0",
"@nestjs/swagger": "^4.2.3",
"@nestjs/typeorm": "^6.2.0",
"@nestjs/common": "^7.0.9",
"@nestjs/config": "^0.4.0",
"@nestjs/core": "^7.0.9",
"@nestjs/jwt": "^7.0.0",
"@nestjs/passport": "^7.0.0",
"@nestjs/platform-express": "^7.0.9",
"@nestjs/schedule": "^0.3.1",
"@nestjs/swagger": "^4.5.3",
"@nestjs/typeorm": "^7.0.0",
"class-transformer": "^0.2.3",
"class-validator": "^0.11.0",
"class-validator": "^0.12.2",
"passport": "^0.4.1",
"passport-jwt": "^4.0.0",
"passport-spotify": "^1.1.0",
"pg": "^7.17.1",
"pg": "^8.0.3",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.0",
"rxjs": "^6.5.3",
"swagger-ui-express": "^4.1.3",
"typeorm": "^0.2.22"
"rimraf": "^3.0.2",
"rxjs": "^6.5.5",
"swagger-ui-express": "^4.1.4",
"typeorm": "^0.2.24"
},
"devDependencies": {
"@nestjs/cli": "^6.9.0",
"@nestjs/schematics": "^6.7.0",
"@nestjs/testing": "^6.7.1",
"@types/express": "^4.17.1",
"@types/jest": "^24.0.18",
"@types/node": "^12.7.5",
"@nestjs/cli": "^7.1.4",
"@nestjs/schematics": "^7.0.0",
"@nestjs/testing": "^7.0.9",
"@types/express": "^4.17.6",
"@types/jest": "^25.2.1",
"@types/node": "^13.13.4",
"@types/passport-jwt": "^3.0.3",
"@types/supertest": "^2.0.8",
"jest": "^24.9.0",
"prettier": "^1.18.2",
"@types/supertest": "^2.0.9",
"jest": "^25.5.4",
"prettier": "^2.0.5",
"supertest": "^4.0.2",
"ts-jest": "^24.1.0",
"ts-loader": "^6.1.1",
"ts-node": "^8.4.1",
"ts-jest": "^25.4.0",
"ts-loader": "^7.0.2",
"ts-node": "^8.9.1",
"tsconfig-paths": "^3.9.0",
"tslint": "^5.20.0",
"tslint": "^6.1.2",
"tslint-config-prettier": "^1.18.0",
"tslint-plugin-prettier": "^2.1.0",
"typescript": "^3.6.3"
"tslint-plugin-prettier": "^2.3.0",
"typescript": "^3.8.3"
},
"jest": {
"moduleFileExtensions": [

View file

@ -17,7 +17,7 @@ import { UsersModule } from "./users/users.module";
UsersModule,
SourcesModule,
MusicLibraryModule,
ListensModule
]
ListensModule,
],
})
export class AppModule {}

View file

@ -31,7 +31,7 @@ export class AuthController {
maxAge: 15 * 60 * 1000,
// Must be readable by SPA
httpOnly: false
httpOnly: false,
});
// Redirect User to SPA

View file

@ -14,14 +14,14 @@ import { SpotifyStrategy } from "./spotify.strategy";
JwtModule.registerAsync({
useFactory: (config: ConfigService) => ({
secret: config.get<string>("JWT_SECRET"),
signOptions: { expiresIn: config.get<string>("JWT_EXPIRATION_TIME") }
signOptions: { expiresIn: config.get<string>("JWT_EXPIRATION_TIME") },
}),
inject: [ConfigService]
inject: [ConfigService],
}),
UsersModule
UsersModule,
],
providers: [AuthService, SpotifyStrategy, JwtStrategy],
exports: [PassportModule],
controllers: [AuthController]
controllers: [AuthController],
})
export class AuthModule {}

View file

@ -6,7 +6,7 @@ describe("AuthService", () => {
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AuthService]
providers: [AuthService],
}).compile();
service = module.get<AuthService>(AuthService);

View file

@ -14,7 +14,7 @@ export class AuthService {
async spotifyLogin({
accessToken,
refreshToken,
profile
profile,
}: LoginDto): Promise<User> {
const user = await this.usersService.createOrUpdate({
displayName: profile.displayName,
@ -22,8 +22,8 @@ export class AuthService {
spotify: {
id: profile.id,
accessToken,
refreshToken
}
refreshToken,
},
});
return user;
@ -33,7 +33,7 @@ export class AuthService {
const payload = {
sub: user.id,
name: user.displayName,
picture: user.photo
picture: user.photo,
};
const token = await this.jwtService.signAsync(payload);

View file

@ -1,3 +1,8 @@
import { createParamDecorator } from "@nestjs/common";
import { createParamDecorator, ExecutionContext } from "@nestjs/common";
export const ReqUser = createParamDecorator((data, req) => req.user);
export const ReqUser = createParamDecorator<void>(
(_: void, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return request.user;
}
);

View file

@ -7,13 +7,13 @@ import { AuthService } from "./auth.service";
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
private readonly config: ConfigService,
private readonly authService: AuthService
private readonly authService: AuthService,
config: ConfigService
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: config.get<string>("JWT_SECRET")
secretOrKey: config.get<string>("JWT_SECRET"),
});
}

View file

@ -13,13 +13,14 @@ export class SpotifyStrategy extends PassportStrategy(Strategy) {
super({
clientID: config.get<string>("SPOTIFY_CLIENT_ID"),
clientSecret: config.get<string>("SPOTIFY_CLIENT_SECRET"),
callbackURL: `${config.get<string>("BASE_DOMAIN") ||
"http://localhost:3000"}/api/v1/auth/spotify/callback`,
callbackURL: `${
config.get<string>("BASE_DOMAIN") || "http://localhost:3000"
}/api/v1/auth/spotify/callback`,
scope: [
"user-read-private",
"user-read-email",
"user-read-recently-played"
]
"user-read-recently-played",
],
});
}
@ -27,7 +28,7 @@ export class SpotifyStrategy extends PassportStrategy(Strategy) {
return await this.authService.spotifyLogin({
accessToken,
refreshToken,
profile
profile,
});
}
}

View file

@ -19,7 +19,7 @@ export const DatabaseModule = TypeOrmModule.forRootAsync({
// Migrations
// migrationsRun: true,
// migrations: [join(__dirname, "migrations", "*.{ts,js}")],
synchronize: true
synchronize: true,
}),
inject: [ConfigService]
inject: [ConfigService],
});

View file

@ -3,7 +3,7 @@ import {
Entity,
Index,
ManyToOne,
PrimaryGeneratedColumn
PrimaryGeneratedColumn,
} from "typeorm";
import { Track } from "../music-library/track.entity";
import { User } from "../users/user.entity";
@ -14,10 +14,10 @@ export class Listen {
@PrimaryGeneratedColumn("uuid")
id: string;
@ManyToOne(type => Track)
@ManyToOne((type) => Track)
track: Track;
@ManyToOne(type => User)
@ManyToOne((type) => User)
user: User;
@Column({ type: "timestamp" })

View file

@ -6,6 +6,6 @@ import { ListenRepository } from "./listen.repository";
@Module({
imports: [TypeOrmModule.forFeature([ListenRepository])],
providers: [ListensService],
exports: [ListensService]
exports: [ListensService],
})
export class ListensModule {}

View file

@ -6,7 +6,7 @@ describe("ListensService", () => {
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ListensService]
providers: [ListensService],
}).compile();
service = module.get<ListensService>(ListensService);

View file

@ -10,7 +10,7 @@ export class ListensService {
async createListen({
user,
track,
playedAt
playedAt,
}: CreateListenDto): Promise<Listen> {
const listen = this.listenRepository.create();
@ -23,7 +23,7 @@ export class ListensService {
} catch (err) {
if (err.code === "23505") {
return this.listenRepository.findOne({
where: { user, track, playedAt }
where: { user, track, playedAt },
});
}

View file

@ -4,7 +4,7 @@ import {
Column,
ManyToMany,
JoinTable,
OneToMany
OneToMany,
} from "typeorm";
import { SpotifyLibraryDetails } from "src/sources/spotify/spotify-library-details.entity";
import { Artist } from "./artist.entity";
@ -18,19 +18,13 @@ export class Album {
@Column()
name: string;
@ManyToMany(
type => Artist,
artist => artist.albums
)
@ManyToMany((type) => Artist, (artist) => artist.albums)
@JoinTable()
artists: Artist[];
@OneToMany(
type => Track,
track => track.album
)
@OneToMany((type) => Track, (track) => track.album)
tracks: Track[];
@Column(type => SpotifyLibraryDetails)
@Column((type) => SpotifyLibraryDetails)
spotify: SpotifyLibraryDetails;
}

View file

@ -10,12 +10,9 @@ export class Artist {
@Column()
name: string;
@ManyToMany(
type => Album,
album => album.artists
)
@ManyToMany((type) => Album, (album) => album.artists)
albums: Album[];
@Column(type => SpotifyLibraryDetails)
@Column((type) => SpotifyLibraryDetails)
spotify: SpotifyLibraryDetails;
}

View file

@ -10,10 +10,10 @@ import { TrackRepository } from "./track.repository";
TypeOrmModule.forFeature([
AlbumRepository,
ArtistRepository,
TrackRepository
])
TrackRepository,
]),
],
providers: [MusicLibraryService],
exports: [MusicLibraryService]
exports: [MusicLibraryService],
})
export class MusicLibraryModule {}

View file

@ -6,7 +6,7 @@ describe("MusicLibraryService", () => {
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MusicLibraryService]
providers: [MusicLibraryService],
}).compile();
service = module.get<MusicLibraryService>(MusicLibraryService);

View file

@ -22,7 +22,7 @@ export class MusicLibraryService {
async findArtist(query: FindArtistDto): Promise<Artist | undefined> {
return this.artistRepository.findOne({
where: { spotify: { id: query.spotify.id } }
where: { spotify: { id: query.spotify.id } },
});
}
@ -41,7 +41,7 @@ export class MusicLibraryService {
async findAlbum(query: FindAlbumDto): Promise<Album | undefined> {
return this.albumRepository.findOne({
where: { spotify: { id: query.spotify.id } }
where: { spotify: { id: query.spotify.id } },
});
}
@ -59,7 +59,7 @@ export class MusicLibraryService {
async findTrack(query: FindTrackDto): Promise<Track | undefined> {
return this.trackRepository.findOne({
where: { spotify: { id: query.spotify.id } }
where: { spotify: { id: query.spotify.id } },
});
}

View file

@ -5,7 +5,7 @@ import {
JoinTable,
ManyToMany,
ManyToOne,
PrimaryGeneratedColumn
PrimaryGeneratedColumn,
} from "typeorm";
import { Album } from "./album.entity";
import { Artist } from "./artist.entity";
@ -18,16 +18,13 @@ export class Track {
@Column()
name: string;
@ManyToOne(
type => Album,
album => album.tracks
)
@ManyToOne((type) => Album, (album) => album.tracks)
album: Album;
@ManyToMany(type => Artist)
@ManyToMany((type) => Artist)
@JoinTable()
artists: Artist[];
@Column(type => SpotifyLibraryDetails)
@Column((type) => SpotifyLibraryDetails)
spotify?: SpotifyLibraryDetails;
}

View file

@ -2,6 +2,6 @@ import { Module } from "@nestjs/common";
import { SpotifyModule } from "./spotify/spotify.module";
@Module({
imports: [SpotifyModule]
imports: [SpotifyModule],
})
export class SourcesModule {}

View file

@ -6,11 +6,11 @@ import { SpotifyApiService } from "./spotify-api.service";
HttpModule.registerAsync({
useFactory: () => ({
timeout: 5000,
baseURL: "https://api.spotify.com/"
})
})
baseURL: "https://api.spotify.com/",
}),
}),
],
providers: [SpotifyApiService],
exports: [SpotifyApiService]
exports: [SpotifyApiService],
})
export class SpotifyApiModule {}

View file

@ -1,7 +1,7 @@
import { Test, TestingModule } from '@nestjs/testing';
import { SpotifyApiService } from './spotify-api.service';
import { Test, TestingModule } from "@nestjs/testing";
import { SpotifyApiService } from "./spotify-api.service";
describe('SpotifyApiService', () => {
describe("SpotifyApiService", () => {
let service: SpotifyApiService;
beforeEach(async () => {
@ -12,7 +12,7 @@ describe('SpotifyApiService', () => {
service = module.get<SpotifyApiService>(SpotifyApiService);
});
it('should be defined', () => {
it("should be defined", () => {
expect(service).toBeDefined();
});
});

View file

@ -12,12 +12,12 @@ export class SpotifyApiService {
async getRecentlyPlayedTracks({
accessToken,
lastRefreshTime
lastRefreshTime,
}: SpotifyConnection): Promise<PlayHistoryObject[]> {
console.log("SpotifyApiService#getRecentlyPlayedTracks");
const parameters: { limit: number; after?: number } = {
limit: 50
limit: 50,
};
if (lastRefreshTime) {
@ -33,7 +33,7 @@ export class SpotifyApiService {
const history = await this.httpService
.get<PagingObject<PlayHistoryObject>>(`v1/me/player/recently-played`, {
headers: { Authorization: `Bearer ${accessToken}` },
params: parameters
params: parameters,
})
.toPromise();
@ -47,7 +47,7 @@ export class SpotifyApiService {
console.log("SpotifyApiService#getArtist");
const artist = await this.httpService
.get<ArtistObject>(`v1/artists/${spotifyID}`, {
headers: { Authorization: `Bearer ${accessToken}` }
headers: { Authorization: `Bearer ${accessToken}` },
})
.toPromise();
@ -59,7 +59,7 @@ export class SpotifyApiService {
const album = await this.httpService
.get<AlbumObject>(`v1/albums/${spotifyID}`, {
headers: { Authorization: `Bearer ${accessToken}` }
headers: { Authorization: `Bearer ${accessToken}` },
})
.toPromise();
@ -72,7 +72,7 @@ export class SpotifyApiService {
const track = await this.httpService
.get<TrackObject>(`v1/tracks/${spotifyID}`, {
headers: { Authorization: `Bearer ${accessToken}` }
headers: { Authorization: `Bearer ${accessToken}` },
})
.toPromise();

View file

@ -6,11 +6,11 @@ import { SpotifyAuthService } from "./spotify-auth.service";
HttpModule.registerAsync({
useFactory: () => ({
timeout: 5000,
baseURL: "https://accounts.spotify.com/"
})
})
baseURL: "https://accounts.spotify.com/",
}),
}),
],
providers: [SpotifyAuthService],
exports: [SpotifyAuthService]
exports: [SpotifyAuthService],
})
export class SpotifyAuthModule {}

View file

@ -23,8 +23,8 @@ export class SpotifyAuthService {
{
auth: {
username: this.clientID,
password: this.clientSecret
}
password: this.clientSecret,
},
}
)
.toPromise();
@ -40,8 +40,8 @@ export class SpotifyAuthService {
{
auth: {
username: this.clientID,
password: this.clientSecret
}
password: this.clientSecret,
},
}
)
.toPromise();

View file

@ -12,8 +12,8 @@ import { SpotifyAuthModule } from "./spotify-auth/spotify-auth.module";
ListensModule,
MusicLibraryModule,
SpotifyApiModule,
SpotifyAuthModule
SpotifyAuthModule,
],
providers: [SpotifyService]
providers: [SpotifyService],
})
export class SpotifyModule {}

View file

@ -6,7 +6,7 @@ describe("SpotifyService", () => {
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [SpotifyService]
providers: [SpotifyService],
}).compile();
service = module.get<SpotifyService>(SpotifyService);

View file

@ -51,7 +51,7 @@ export class SpotifyService {
);
await this.usersService.updateSpotifyConnection(user, {
...user.spotify,
accessToken
accessToken,
});
await this.processUser(user, false);
}
@ -62,13 +62,13 @@ export class SpotifyService {
}
await Promise.all(
playHistory.map(async history => {
playHistory.map(async (history) => {
const track = await this.importTrack(history.track.id);
this.listensService.createListen({
user,
track,
playedAt: new Date(history.played_at)
playedAt: new Date(history.played_at),
});
console.log(
@ -79,19 +79,19 @@ export class SpotifyService {
const newestPlayTime = new Date(
playHistory
.map(history => history.played_at)
.map((history) => history.played_at)
.sort()
.pop()
);
console.log("newestPlayTime", {
newestPlayTime,
times: playHistory.map(history => history.played_at).sort()
times: playHistory.map((history) => history.played_at).sort(),
});
this.usersService.updateSpotifyConnection(user, {
...user.spotify,
lastRefreshTime: newestPlayTime
lastRefreshTime: newestPlayTime,
});
}
@ -100,7 +100,7 @@ export class SpotifyService {
retryOnExpiredToken: boolean = true
): Promise<Track> {
const track = await this.musicLibraryService.findTrack({
spotify: { id: spotifyID }
spotify: { id: spotifyID },
});
if (track) {
return track;
@ -129,7 +129,7 @@ export class SpotifyService {
spotifyTrack.artists.map(({ id: artistID }) =>
this.importArtist(artistID)
)
)
),
]);
return this.musicLibraryService.createTrack({
@ -140,8 +140,8 @@ export class SpotifyService {
id: spotifyTrack.id,
uri: spotifyTrack.uri,
type: spotifyTrack.type,
href: spotifyTrack.href
}
href: spotifyTrack.href,
},
});
}
@ -150,7 +150,7 @@ export class SpotifyService {
retryOnExpiredToken: boolean = true
): Promise<Album> {
const album = await this.musicLibraryService.findAlbum({
spotify: { id: spotifyID }
spotify: { id: spotifyID },
});
if (album) {
return album;
@ -186,8 +186,8 @@ export class SpotifyService {
id: spotifyAlbum.id,
uri: spotifyAlbum.uri,
type: spotifyAlbum.type,
href: spotifyAlbum.href
}
href: spotifyAlbum.href,
},
});
}
@ -196,7 +196,7 @@ export class SpotifyService {
retryOnExpiredToken: boolean = true
): Promise<Artist> {
const artist = await this.musicLibraryService.findArtist({
spotify: { id: spotifyID }
spotify: { id: spotifyID },
});
if (artist) {
return artist;
@ -225,8 +225,8 @@ export class SpotifyService {
id: spotifyArtist.id,
uri: spotifyArtist.uri,
type: spotifyArtist.type,
href: spotifyArtist.href
}
href: spotifyArtist.href,
},
});
}

View file

@ -12,6 +12,6 @@ export class User {
@Column({ nullable: true })
photo?: string;
@Column(type => SpotifyConnection)
@Column((type) => SpotifyConnection)
spotify: SpotifyConnection;
}

View file

@ -1,7 +1,7 @@
import { Test, TestingModule } from '@nestjs/testing';
import { UsersController } from './users.controller';
import { Test, TestingModule } from "@nestjs/testing";
import { UsersController } from "./users.controller";
describe('Users Controller', () => {
describe("Users Controller", () => {
let controller: UsersController;
beforeEach(async () => {
@ -12,7 +12,7 @@ describe('Users Controller', () => {
controller = module.get<UsersController>(UsersController);
});
it('should be defined', () => {
it("should be defined", () => {
expect(controller).toBeDefined();
});
});

View file

@ -11,7 +11,7 @@ export class UsersController {
return {
id: user.id,
displayName: user.displayName,
photo: user.photo
photo: user.photo,
};
}
}

View file

@ -2,12 +2,12 @@ import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { UserRepository } from "./user.repository";
import { UsersService } from "./users.service";
import { UsersController } from './users.controller';
import { UsersController } from "./users.controller";
@Module({
imports: [TypeOrmModule.forFeature([UserRepository])],
providers: [UsersService],
exports: [UsersService],
controllers: [UsersController]
controllers: [UsersController],
})
export class UsersModule {}

View file

@ -6,7 +6,7 @@ describe("UsersService", () => {
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UsersService]
providers: [UsersService],
}).compile();
service = module.get<UsersService>(UsersService);

View file

@ -24,14 +24,14 @@ export class UsersService {
async createOrUpdate(data: CreateOrUpdateDto): Promise<User> {
let user = await this.userRepository.findOne({
where: { spotify: { id: data.spotify.id } }
where: { spotify: { id: data.spotify.id } },
});
if (!user) {
user = this.userRepository.create({
spotify: {
id: data.spotify.id
}
id: data.spotify.id,
},
});
}