import { defineRelations } from "drizzle-orm"; import { boolean, index, integer, pgEnum, pgTable, primaryKey, text, timestamp, uniqueIndex, uuid, varchar, } from "drizzle-orm/pg-core"; import { user } from "./auth-schema"; export * from "./auth-schema"; export const platform = pgEnum("enum_platform", ["spotify", "apple"]); export const artist = pgTable("artist", { id: uuid().defaultRandom().primaryKey().notNull(), platform_id: text().notNull(), platform: platform().notNull(), name: text().notNull(), type: text(), popularity: integer(), }); export const genre = pgTable("genre", { id: uuid().defaultRandom().primaryKey().notNull(), name: text().notNull().unique(), }); export const artistGenre = pgTable( "artist_genre", { artistId: uuid() .references(() => artist.id) .notNull(), genreId: uuid() .references(() => genre.id) .notNull(), }, (artistGenres) => [ primaryKey({ columns: [artistGenres.artistId, artistGenres.genreId], }), ], ); export const platformImage = pgTable( "platform_image", { id: uuid().defaultRandom().primaryKey().notNull(), platform: platform().notNull(), url: text(), height: integer(), width: integer(), }, (platformImage) => [ uniqueIndex().on(platformImage.platform, platformImage.url), index().on(platformImage.url), ], ); export const artistImage = pgTable( "artist_image", { artistId: uuid() .references(() => artist.id) .notNull(), imageId: uuid() .references(() => platformImage.id) .notNull(), }, (artistImages) => [ primaryKey({ columns: [artistImages.artistId, artistImages.imageId], }), ], ); export const album = pgTable("album", { id: uuid().defaultRandom().primaryKey().notNull(), type: text(), name: text(), platform: platform(), platform_id: text(), popularity: integer(), release_date: timestamp(), label: text(), }); export const albumImage = pgTable( "album_image", { albumId: uuid() .references(() => album.id) .notNull(), imageId: uuid() .references(() => platformImage.id) .notNull(), }, (albumImage) => [ primaryKey({ columns: [albumImage.albumId, albumImage.imageId], }), ], ); export const albumArtist = pgTable( "album_artist", { albumId: uuid() .references(() => album.id) .notNull(), artistId: uuid() .references(() => artist.id) .notNull(), }, (albumArtist) => [ primaryKey({ columns: [albumArtist.albumId, albumArtist.artistId], }), ], ); export const albumGenre = pgTable( "album_genre", { albumId: uuid() .references(() => album.id) .notNull(), genreId: uuid() .references(() => genre.id) .notNull(), }, (albumGenre) => [ primaryKey({ columns: [albumGenre.albumId, albumGenre.genreId], }), ], ); export const track = pgTable( "track", { id: uuid().defaultRandom().primaryKey().notNull(), albumId: uuid() .references(() => album.id) .notNull(), name: text(), platform: platform(), platform_id: text(), popularity: integer(), duration: integer(), explicit: boolean(), disc_number: integer(), track_number: integer(), }, (track) => [index().on(track.albumId)], ); export const trackArtist = pgTable( "track_artist", { trackId: uuid() .references(() => track.id) .notNull(), artistId: uuid() .references(() => artist.id) .notNull(), }, (trackArtist) => [ primaryKey({ columns: [trackArtist.trackId, trackArtist.artistId], }), index("track_artist_track_id_idx").on(trackArtist.trackId), index("track_artist_artist_id_idx").on(trackArtist.artistId), ], ); export const topTimeline = pgEnum("top_timeline", [ "short_term", "medium_term", "long_term", ]); export const topTrack = pgTable( "top_track", { trackId: uuid() .references(() => track.id) .notNull(), position: integer().notNull(), userId: text() .references(() => user.id) .notNull(), timeline: topTimeline().notNull(), }, (topTrack) => [ primaryKey({ columns: [topTrack.trackId, topTrack.userId, topTrack.timeline], }), index().on(topTrack.userId), ], ); export const topArtist = pgTable( "top_artist", { artistId: uuid() .references(() => artist.id) .notNull(), position: integer().notNull(), userId: text() .references(() => user.id) .notNull(), timeline: topTimeline().notNull(), }, (topArtist) => [ primaryKey({ columns: [topArtist.artistId, topArtist.userId, topArtist.timeline], }), index().on(topArtist.userId), ], ); export const savedAlbum = pgTable( "saved_album", { albumId: uuid() .references(() => album.id) .notNull(), userId: text() .references(() => user.id) .notNull(), saved_at: timestamp("saved_at").defaultNow().notNull(), }, (savedAlbum) => [ primaryKey({ columns: [savedAlbum.albumId, savedAlbum.userId], }), index().on(savedAlbum.userId), ], ); export const savedTrack = pgTable( "saved_track", { trackId: uuid() .references(() => track.id) .notNull(), userId: text() .references(() => user.id) .notNull(), saved_at: timestamp("saved_at").defaultNow().notNull(), }, (savedTrack) => [ primaryKey({ columns: [savedTrack.trackId, savedTrack.userId], }), index().on(savedTrack.userId), ], ); export const followedArtist = pgTable( "followed_artist", { artistId: uuid() .references(() => artist.id) .notNull(), userId: text() .references(() => user.id) .notNull(), }, (followedArtist) => [ primaryKey({ columns: [followedArtist.artistId, followedArtist.userId], }), index().on(followedArtist.userId), ], ); export const playbackHistory = pgTable( "playback_history", { id: uuid().defaultRandom().primaryKey().notNull(), trackId: uuid() .references(() => track.id) .notNull(), userId: text() .references(() => user.id) .notNull(), played_at: timestamp("played_at").defaultNow().notNull(), }, (playbackHistory) => [index().on(playbackHistory.userId)], ); export const relations = defineRelations( { album, albumImage, albumArtist, albumGenre, artist, artistGenre, artistImage, followedArtist, genre, platformImage, playbackHistory, savedAlbum, savedTrack, topArtist, topTrack, track, trackArtist, user, }, (r) => ({ artist: { artistGenres: r.many.artistGenre(), artistImages: r.many.artistImage(), trackArtists: r.many.trackArtist(), albumArtists: r.many.albumArtist(), topArtists: r.many.topArtist(), followedArtists: r.many.followedArtist(), genres: r.many.genre({ from: r.artist.id.through(r.artistGenre.artistId), to: r.genre.id.through(r.artistGenre.genreId), }), images: r.many.platformImage({ from: r.artist.id.through(r.artistImage.artistId), to: r.platformImage.id.through(r.artistImage.imageId), }), albums: r.many.album({ from: r.artist.id.through(r.albumArtist.artistId), to: r.album.id.through(r.albumArtist.albumId), }), tracks: r.many.track({ from: r.artist.id.through(r.trackArtist.artistId), to: r.track.id.through(r.trackArtist.trackId), }), }, genre: { artistGenres: r.many.artistGenre(), albumGenres: r.many.albumGenre(), artists: r.many.artist({ from: r.genre.id.through(r.artistGenre.genreId), to: r.artist.id.through(r.artistGenre.artistId), }), albums: r.many.album({ from: r.genre.id.through(r.albumGenre.genreId), to: r.album.id.through(r.albumGenre.albumId), }), }, artistGenre: { artist: r.one.artist({ from: r.artistGenre.artistId, to: r.artist.id, }), genre: r.one.genre({ from: r.artistGenre.genreId, to: r.genre.id, }), }, platformImage: { artistImages: r.many.artistImage(), albumImages: r.many.albumImage(), artists: r.many.artist({ from: r.platformImage.id.through(r.artistImage.imageId), to: r.artist.id.through(r.artistImage.artistId), }), albums: r.many.album({ from: r.platformImage.id.through(r.albumImage.imageId), to: r.album.id.through(r.albumImage.albumId), }), }, artistImage: { artist: r.one.artist({ from: r.artistImage.artistId, to: r.artist.id, }), image: r.one.platformImage({ from: r.artistImage.imageId, to: r.platformImage.id, }), }, album: { tracks: r.many.track(), albumImages: r.many.albumImage(), albumArtists: r.many.albumArtist(), albumGenres: r.many.albumGenre(), savedAlbums: r.many.savedAlbum(), images: r.many.platformImage({ from: r.album.id.through(r.albumImage.albumId), to: r.platformImage.id.through(r.albumImage.imageId), }), artists: r.many.artist({ from: r.album.id.through(r.albumArtist.albumId), to: r.artist.id.through(r.albumArtist.artistId), }), genres: r.many.genre({ from: r.album.id.through(r.albumGenre.albumId), to: r.genre.id.through(r.albumGenre.genreId), }), }, albumImage: { album: r.one.album({ from: r.albumImage.albumId, to: r.album.id, }), image: r.one.platformImage({ from: r.albumImage.imageId, to: r.platformImage.id, }), }, albumArtist: { album: r.one.album({ from: r.albumArtist.albumId, to: r.album.id, }), artist: r.one.artist({ from: r.albumArtist.artistId, to: r.artist.id, }), }, albumGenre: { album: r.one.album({ from: r.albumGenre.albumId, to: r.album.id, }), genre: r.one.genre({ from: r.albumGenre.genreId, to: r.genre.id, }), }, track: { album: r.one.album({ from: r.track.albumId, to: r.album.id, }), trackArtists: r.many.trackArtist(), topTracks: r.many.topTrack(), savedTracks: r.many.savedTrack(), playbackHistory: r.many.playbackHistory(), artists: r.many.artist({ from: r.track.id.through(r.trackArtist.trackId), to: r.artist.id.through(r.trackArtist.artistId), }), }, trackArtist: { track: r.one.track({ from: r.trackArtist.trackId, to: r.track.id, }), artist: r.one.artist({ from: r.trackArtist.artistId, to: r.artist.id, }), }, topTrack: { track: r.one.track({ from: r.topTrack.trackId, to: r.track.id, }), user: r.one.user({ from: r.topTrack.userId, to: r.user.id, }), }, topArtist: { artist: r.one.artist({ from: r.topArtist.artistId, to: r.artist.id, }), user: r.one.user({ from: r.topArtist.userId, to: r.user.id, }), }, savedAlbum: { album: r.one.album({ from: r.savedAlbum.albumId, to: r.album.id, }), user: r.one.user({ from: r.savedAlbum.userId, to: r.user.id, }), }, savedTrack: { track: r.one.track({ from: r.savedTrack.trackId, to: r.track.id, }), user: r.one.user({ from: r.savedTrack.userId, to: r.user.id, }), }, followedArtist: { artist: r.one.artist({ from: r.followedArtist.artistId, to: r.artist.id, }), user: r.one.user({ from: r.followedArtist.userId, to: r.user.id, }), }, playbackHistory: { track: r.one.track({ from: r.playbackHistory.trackId, to: r.track.id, }), user: r.one.user({ from: r.playbackHistory.userId, to: r.user.id, }), }, }), );