UNPKG

@yuna0x0/anilist-node

Version:

A lightweight Node.js wrapper for the AniList API

105 lines (86 loc) 3.43 kB
const mediaFilterType = require("../types/mediaFilterTypes"); const activityFilterType = require("../types/activityFilterTypes"); /** * Validates the filter object for searching. * @private * @param {String} type The type of query that the filter would be applied to. * @param {Object} filterObj A key/value paired filter object. * @returns Will throw an error if the filter object is bad (ie: Non-existent key or incorrect value type). * Returns nothing upon success. */ const validateFilters = function (type, filterObj) { const filterKeys = Object.keys(filterObj); let filterTest; if (type === "activity") { filterTest = activityFilterType; } if (type === "anime" || type === "manga") { filterTest = mediaFilterType; } if (!filterTest) { throw new Error(`Filter type not recognized by internal function. Bad type: ${type}.`); } for (let x = 0; x < filterKeys.length; x++) { let myKey = filterKeys[x]; let myValue = filterObj[myKey]; let filterType = filterTest[myKey]; if (!filterType) { throw new Error(`Filter key not recognized. Bad key: ${myKey}.`); } if (myValue instanceof Array) { let typeDef = typeof filterType[0]; myValue.forEach((value) => { if (typeof value !== typeDef) { throw new Error(`Value (${value}) type does not match filter type in array key (${myKey})!`); } }); continue; } if (typeof myValue !== filterType) { throw new Error(`Value (${myValue}) type does not match filter type in key (${myKey})!`); } } }; /** * Generate a query header with filter options. * @private * @param {String} searchType The search type to build the query with * @param {Object} filterObj A simple key-value pair object for setting filters. * @returns {String} Returns the query header if the filter is valid. Else, it will throw an error. */ const filterBuilder = function (searchType, filterObj = null) { if (typeof filterObj !== "object") { throw new Error(`Filter object used is of a non-object type! Expected an object but got ${filterObj} instead.`); } if (filterObj) { validateFilters(searchType, filterObj); } let baseQuery = `query ($page: Int, $perPage: Int, $search: String) { Page (page: $page, perPage: $perPage) { pageInfo { total currentPage lastPage hasNextPage perPage } `; if (searchType === "activity") { baseQuery = `query ($page: Int, $perPage: Int, $id: Int) { Page (page: $page, perPage: $perPage) { pageInfo { total currentPage lastPage hasNextPage perPage } activities (id: $id`; } else if (searchType === "anime") { baseQuery += "media (type: ANIME, search: $search"; } else if (searchType === "manga") { baseQuery += "media (type: MANGA, search: $search"; } if (filterObj) { let filterKeys = Object.keys(filterObj); for (let x = 0; x < filterKeys.length; x++) { let filterValue = filterObj[filterKeys[x]]; // If a value is completely uppercase, we are going to assume it's an ENUM if (filterValue instanceof Array) { filterValue = `[${filterValue .map((value) => typeof value === "string" && value !== value.toUpperCase() ? `"${value}"` : value) .join(", ")}]`; } else if (typeof filterValue === "string" && filterValue !== filterValue.toUpperCase()) { filterValue = `"${filterValue}"`; } baseQuery += `, ${filterKeys[x]}: ${filterValue}`; } } return `${baseQuery}) {`; }; module.exports = filterBuilder;