{"version":3,"sources":["../src/errors/NotFound.ts","../src/errors/RequestError.ts","../src/utils.ts","../src/lyrics.ts"],"sourcesContent":["export class NotFoundError extends Error {\n  constructor() {\n    super(\"Track was not found\");\n  }\n}\nexport class NoResultError extends Error {\n  constructor() {\n    super(\"No result was found\");\n  }\n}\n","export class RequestError extends Error {\n  constructor(error?: string) {\n    super(\"Request error \" + error);\n  }\n}\n","import { LyricLine, ParsedLyrics } from \"./types/Utils\";\n\n/**\n * Parses song lyrics into a structured format by removing metadata tags and separating lines.\n *\n * Example Input:\n * ```\n * [00:27.93] Listen to the wind blow\n * [00:30.88] Watch the sun rise\n * ```\n *\n * Example Output:\n * {\n *   synced: [{ text: \"Listen to the wind blow\", startTime: 27930 }, { text: \"Watch the sun rise\", startTime: 30880 }],\n *   unsynced: []\n * }\n *\n * @param lyrics - The raw lyrics string with optional tags and timestamps\n * @returns A ParsedLyrics object containing structured lyric data\n */\nfunction parseLocalLyrics(lyrics: string): ParsedLyrics {\n  // Preprocess lyrics by removing [tags] (e.g., [artist:Name]) and trimming extra whitespace\n  const lines = lyrics\n    .replace(/\\[[a-zA-Z]+:.+\\]/g, \"\") // Removes metadata tags like [artist:Name]\n    .trim()\n    .split(\"\\n\"); // Splits the lyrics into an array of lines\n\n  // Regular expressions for matching synced and karaoke timestamps\n  const syncedTimestamp = /\\[([0-9:.]+)\\]/; // Matches [00:12.34]\n\n  const unsynced: LyricLine[] = []; // Array to store unsynchronized lyrics\n  const synced: LyricLine[] = []; // Array to store synchronized lyrics\n\n  // Process each line to extract lyrics and timing information\n  lines.forEach((line) => {\n    // Match synchronized lyrics\n    const syncMatch = line.match(syncedTimestamp);\n    if (syncMatch) {\n      const startTime = parseTime(syncMatch[1]);\n      const text = line.replace(syncedTimestamp, \"\").trim();\n      if (text) {\n        synced.push({ text, startTime });\n      }\n    }\n    // Add to unsynchronized lyrics if no timestamps are found\n    else {\n      const text = line.trim();\n      if (text) {\n        unsynced.push({ text });\n      }\n    }\n  });\n\n  return {\n    synced: synced.length > 0 ? synced : null,\n    unsynced,\n  };\n}\n\n/**\n * Converts a timestamp string in the format \"mm:ss\" or \"mm:ss.SSS\" to a number in seconds.\n *\n * @param time - The timestamp string to parse\n * @returns The time in seconds as a number\n */\nfunction parseTime(time: string): number {\n  const [minutes, seconds] = time.split(\":\").map(Number);\n  return minutes * 60 + seconds;\n}\n\nexport { parseLocalLyrics, parseTime };\n","import { NoResultError, NotFoundError, RequestError } from \"./errors\";\nimport { ClientOptions } from \"./types/Client\";\nimport { FindLyricsResponse, Query, Search } from \"./types/Lyrics\";\nimport { LyricLine } from \"./types/Utils\";\nimport { parseLocalLyrics } from \"./utils\";\n\nexport class Client {\n  private _url: string = \"https://lrclib.net/api\";\n  private _key: string | undefined;\n  /**\n   * Creates a request client to api\n   *\n   * Example Usage;\n   * ```typescript\n   * const client = new Client();\n   *\n   * client.findLyrics({ track_name: \"The Chain\", artist_name: \"Fleetwood Mac\" }).then(console.log);\n   * ```\n   *\n   * @notigorwastaken: I'm still working on it.\n   *\n   * @param options - An optional object containing Client Options\n   *  - `url`: The base URL, e.g. you can set up a custom url that uses another lrclib.net instance\n   *  - `key`: The token used to publish lyrics to the api. [click here for more info](https://lrclib.net/docs)\n   */\n  constructor(options?: ClientOptions) {\n    this._url = options?.url || this._url;\n    this._key = options?.key;\n  }\n  private async request(\n    path: string,\n    options?: RequestInit,\n  ): Promise<Response> {\n    return await fetch(this._url + path, options);\n  }\n  /**\n   * Sends a request to the lyrics search API at https://lrclib.net/api/search.\n   *\n   * Example Usage:\n   * ```typescript\n   * const search = await searchLyrics({ query: \"The Chain\" });\n   * ```\n   *\n   * @param info - An object containing search parameters:\n   *  - `query`: The search term (conditional | e.g., song title or lyrics fragment).\n   *  - `track_name`: The name of the track (conditional).\n   *  - `artist_name`: The artist's name (optional).\n   *  - `duration`: The song duration in milliseconds (optional).\n   *\n   * @returns A promise that resolves to an array of {@link FindLyricsResponse | FindLyricsResponse[]}.\n   */\n  public async searchLyrics(\n    info: Search,\n    options?: RequestInit,\n  ): Promise<FindLyricsResponse[]> {\n    const baseURL = \"/search\";\n    const params = {\n      q: info.query || \"\",\n      track_name: info.track_name || \"\",\n      artist_name: info.artist_name || \"\",\n      duration: info.duration ? info.duration / 1000 : \"\",\n    };\n    const finalURL = `${baseURL}?${Object.entries(params)\n      .filter(([_, value]) => value !== undefined && value !== \"\")\n      .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`)\n      .join(\"&\")}`;\n    const response = await this.request(finalURL, options);\n\n    if (!response.ok) {\n      throw new RequestError();\n    }\n    const body = await response.json();\n\n    if (!body) {\n      throw new NoResultError();\n    }\n\n    return body;\n  }\n\n  /**\n   * Finds lyrics for a given track using the API at https://lrclib.net/api/get.\n   *\n   * Example Usage:\n   * ```typescript\n   * const lyrics = await findLyrics({ track_name: \"The Chain\", artist_name: \"Fleetwood Mac\" });\n   * ```\n   *\n   * @param info - An object containing query parameters:\n   *  - `id`: The unique identifier of the track (conditional).\n   *  - `track_name`: The name of the track (conditional).\n   *  - `artist_name`: The artist's name (conditional).\n   *  - `album_name`: The album's name (optional).\n   *  - `duration`: The song duration in milliseconds (optional).\n   *\n   * @returns A promise that resolves to a {@link FindLyricsResponse | FindLyricsResponse} object containing the track's lyrics.\n   * @throws Will throw an error if the request fails or the track is not found.\n   */\n  public async findLyrics(\n    info: Query,\n    options?: RequestInit,\n  ): Promise<FindLyricsResponse> {\n    const parseID = info.id ? `/${info.id}` : \"?\";\n    const baseURL = \"/get\" + parseID;\n    const durr = info?.duration ? info.duration / 1000 : undefined;\n    const params = {\n      track_name: info.track_name || \"\",\n      artist_name: info.artist_name || \"\",\n      album_name: info.album_name || \"\",\n      duration: durr || \"\",\n    };\n\n    const finalURL = `${baseURL}${Object.entries(params)\n      .filter(([_, value]) => value !== undefined && value !== \"\")\n      .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`)\n      .join(\"&\")}`;\n\n    const response = await this.request(finalURL, options);\n    if (!response.ok && response.status === 404) {\n      throw new NotFoundError();\n    } else if (!response.ok && response.status !== 200) {\n      throw new RequestError(response.statusText);\n    }\n\n    const body = await response.json();\n\n    return body;\n  }\n\n  /**\n   * Retrieves unsynchronized (plain) lyrics for a given track.\n   *\n   * Example Usage:\n   * ```typescript\n   * const unsyncedLyrics = await getUnsynced({ track_name: \"The Chain\", artist_name: \"Fleetwood Mac\" });\n   * ```\n   *\n   * @param info - An object containing query parameters:\n   *  - `id`: The unique identifier of the track (conditional).\n   *  - `track_name`: The name of the track (conditional).\n   *  - `artist_name`: The artist's name (conditional).\n   *  - `album_name`: The album's name (optional).\n   *  - `duration`: The song duration in milliseconds (optional).\n   *\n   * @returns A promise that resolves to an array of {@link LyricLine | LyricLine[]} objects\n   *          containing unsynchronized lyrics or `null` if no lyrics are found.\n   */\n  public async getUnsynced(info: Query): Promise<LyricLine[] | null> {\n    try {\n      const body = await this.findLyrics(info);\n      if (\"error\" in body) return null;\n\n      const unsyncedLyrics = body?.plainLyrics;\n      const isInstrumental = body.instrumental;\n      if (isInstrumental) return [{ text: \"[Instrumental]\" }];\n\n      if (!unsyncedLyrics) return null;\n\n      return parseLocalLyrics(unsyncedLyrics).unsynced;\n    } catch (e) {\n      console.error(e);\n      return null;\n    }\n  }\n\n  /**\n   * Retrieves synchronized (timed) lyrics for a given track.\n   *\n   * Example Usage:\n   * ```typescript\n   * const syncedLyrics = await getSynced({ track_name: \"The Chain\", artist_name: \"Fleetwood Mac\" });\n   * ```\n   *\n   * @param info - An object containing query parameters:\n   *  - `id`: The unique identifier of the track (conditional).\n   *  - `track_name`: The name of the track (conditional).\n   *  - `artist_name`: The artist's name (conditional).\n   *  - `album_name`: The album's name (optional).\n   *  - `duration`: The song duration in milliseconds (optional).\n   *\n   * @returns A promise that resolves to an array of {@link LyricLine | LyricLine[]} objects\n   *          containing synchronized lyrics or `null` if no lyrics are found.\n   */\n  public async getSynced(info: Query): Promise<LyricLine[] | null> {\n    try {\n      const body = await this.findLyrics(info);\n      const syncedLyrics = body?.syncedLyrics;\n      const isInstrumental = body.instrumental;\n      if (isInstrumental) return [{ text: \"[Instrumental]\" }];\n\n      if (!syncedLyrics) return null;\n\n      return parseLocalLyrics(syncedLyrics).synced;\n    } catch (e) {\n      console.error(e);\n      return null;\n    }\n  }\n}\n"],"mappings":"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","names":[]}