Migrated read APIs to Nitro
This commit is contained in:
1 parent
eb4e9f0700
commit
ee5809a489
26 files changed
+558
No files matched your search
@@ -0,0 +1,95 @@
|
||||
import Fuse from "fuse.js"
|
||||
import { Album } from "../models/album"
|
||||
import { Artist } from "../models/artist"
|
||||
import { Track } from "../models/track"
|
||||
import {
|
||||
parseNumber,
|
||||
parseQueryString,
|
||||
validationResponse,
|
||||
} from "../utils/api-validation"
|
||||
import { requireAuthenticatedUser } from "../utils/auth"
|
||||
|
||||
const searchTypes = ["track", "album", "artist", "default"] as const
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
await requireAuthenticatedUser(event)
|
||||
|
||||
const query = getQuery(event)
|
||||
const q = parseQueryString(query.q)
|
||||
if ("error" in q) return validationResponse(event, q.error)
|
||||
|
||||
let type = "default"
|
||||
if (query.type !== undefined) {
|
||||
const parsedType = parseQueryString(query.type)
|
||||
if ("error" in parsedType) return validationResponse(event, parsedType.error)
|
||||
if (!searchTypes.includes(parsedType.value as (typeof searchTypes)[number])) {
|
||||
return validationResponse(
|
||||
event,
|
||||
`Invalid enum value. Expected 'track' | 'album' | 'artist' | 'default', received '${parsedType.value}'`,
|
||||
)
|
||||
}
|
||||
type = parsedType.value
|
||||
}
|
||||
|
||||
const parsedLimit = parseNumber(query.limit, 9, 1)
|
||||
if ("error" in parsedLimit) return validationResponse(event, parsedLimit.error)
|
||||
const limit = parsedLimit.value
|
||||
|
||||
let results: { tracks: any[]; albums: any[]; artists: any[] } = {
|
||||
tracks: [],
|
||||
albums: [],
|
||||
artists: [],
|
||||
}
|
||||
|
||||
if (type === "track" || type === "default") {
|
||||
const rawTracks = await Track.find({})
|
||||
.populate(["album", "artists"])
|
||||
.lean()
|
||||
|
||||
const fuse = new Fuse(rawTracks, {
|
||||
keys: ["name", "lyrics.text"],
|
||||
threshold: 0.3,
|
||||
distance: 100,
|
||||
ignoreLocation: true,
|
||||
})
|
||||
|
||||
results.tracks = fuse.search(q.value).slice(0, limit).map((result) => result.item)
|
||||
}
|
||||
|
||||
if (type === "album" || type === "default") {
|
||||
const rawAlbums = await Album.find({})
|
||||
.populate(["artists", "genre"])
|
||||
.lean()
|
||||
|
||||
const fuse = new Fuse(rawAlbums, {
|
||||
keys: ["name"],
|
||||
threshold: 0.3,
|
||||
distance: 100,
|
||||
ignoreLocation: true,
|
||||
})
|
||||
|
||||
results.albums = fuse.search(q.value).slice(0, limit).map((result) => result.item)
|
||||
}
|
||||
|
||||
if (type === "artist" || type === "default") {
|
||||
const rawArtists = await Artist.find({}).lean()
|
||||
|
||||
const fuse = new Fuse(rawArtists, {
|
||||
keys: ["name"],
|
||||
threshold: 0.3,
|
||||
distance: 100,
|
||||
ignoreLocation: true,
|
||||
})
|
||||
|
||||
results.artists = fuse.search(q.value).slice(0, limit).map((result) => result.item)
|
||||
}
|
||||
|
||||
// Keep the original API's split allocation, including when type selects one category.
|
||||
results = {
|
||||
tracks: results.tracks.slice(0, Math.ceil(limit / 3)),
|
||||
albums: results.albums.slice(0, Math.floor(limit / 3)),
|
||||
artists: results.artists.slice(0, Math.floor(limit / 3)),
|
||||
}
|
||||
|
||||
return results
|
||||
})
|
||||
Reference in new issue
Block a user