diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..5114fe6 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,4 @@ +export default { + testEnvironment: "node", + transform: {}, +}; diff --git a/package-lock.json b/package-lock.json index 812dc9c..8e3c3d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jetsetradio-api", - "version": "1.1.5", + "version": "1.1.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jetsetradio-api", - "version": "1.1.5", + "version": "1.1.6", "license": "Apache 2.0", "dependencies": { "axios": "^1.11.0", @@ -2697,9 +2697,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz", + "integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", diff --git a/package.json b/package.json index 5438b11..c4ccbda 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jetsetradio-api", - "version": "1.1.5", + "version": "1.1.6", "description": "A Data Provider relating to the JSR/JSRF universe", "type": "module", "main": "src/app.js", diff --git a/src/controllers/artistController.js b/src/controllers/artistController.js index 3e33fa5..25483a4 100644 --- a/src/controllers/artistController.js +++ b/src/controllers/artistController.js @@ -3,6 +3,7 @@ import Constants from "../constants/dbConstants.js"; import {Actions} from "../config/dbActions.js"; import {performDBAction} from "../config/db.js"; import LOGGER from "../utils/logger.js"; +import {fetchRandom} from "./utilController.js"; const Artist = "Artist"; const Song = "Song"; @@ -21,6 +22,15 @@ export const getArtists = async (req, res) => { } }; +export const getRandomArtist = async (req, res) => { + try { + res.send(await fetchRandom(req, Artist, "N/A")); + } catch (err) { + LOGGER.error(`Could not fetch random Artist`, err); + res.status(500).json({error: "Failed to fetch random Artist"}); + } +}; + export const getArtistById = async (req, res) => { try { const artist = await performDBAction( diff --git a/src/controllers/graffitiSoulController.js b/src/controllers/graffitiSoulController.js new file mode 100644 index 0000000..7d1af1a --- /dev/null +++ b/src/controllers/graffitiSoulController.js @@ -0,0 +1,113 @@ +import Constants from "../constants/dbConstants.js"; +import {Actions} from "../config/dbActions.js"; +import {performDBAction} from "../config/db.js"; +import {sortObjects} from "../utils/utility.js"; +import LOGGER from "../utils/logger.js"; +import {fetchRandom} from "./utilController.js"; + +const GraffitiSoul = "GraffitiSoul"; +const {JSR_DB, JSRF_DB} = Constants; + +export const getAllGraffitiSouls = async (req, res) => { + try { + const sortByValue = req?.query?.sortBy ? req?.query?.sortBy : undefined; + const sortOrder = req?.query?.orderBy ? req?.query?.orderBy : "asc"; + const jsrSouls = await fetchJSRSouls(req); + const jsrfSouls = await fetchJSRFSouls(req); + if (sortByValue) { + const Souls = [...jsrSouls, ...jsrfSouls]; + return res.send(Souls.sort(sortObjects(sortByValue, sortOrder))); + } + res.send([...jsrSouls, ...jsrfSouls]); + } catch (err) { + LOGGER.error(`Could not fetch ALL GraffitiSouls`, err); + res + .status(500) + .json({message: "Failed to fetch ALL GraffitiSouls", err: err}); + } +}; + +export const getRandomGraffitiSoul = async (req, res) => { + try { + res.send(await fetchRandom(req, GraffitiSoul)); + } catch (err) { + LOGGER.error(`Could not fetch random GraffitiSoul`, err); + res.status(500).json({error: "Failed to fetch random GraffitiSoul"}); + } +}; + +export const getJSRGraffitiSouls = async (req, res) => { + try { + res.send(await fetchJSRSouls(req)); + } catch (err) { + LOGGER.error(`Could not fetch JSR GraffitiSouls`, err); + res + .status(500) + .json({message: "Failed to fetch JSR GraffitiSouls", err: err}); + } +}; + +export const getJSRFGraffitiSouls = async (req, res) => { + try { + res.send(await fetchJSRFSouls(req)); + } catch (err) { + LOGGER.error(`Could not fetch JSRF GraffitiSouls`, err); + res + .status(500) + .json({message: "Failed to fetch JSRF GraffitiSouls", err: err}); + } +}; + +export const getJSRGraffitiSoulById = async (req, res) => { + try { + const soulId = req?.params?.id; + res.send( + await performDBAction(Actions.fetchById, JSR_DB, GraffitiSoul, soulId) + ); + } catch (err) { + LOGGER.error(`Could not fetch JSR GraffitiSoul With ID: ${soulId}`, err); + res + .status(500) + .json({message: "Failed to fetch JSR GraffitiSoul By ID", err: err}); + } +}; + +export const getJSRFGraffitiSoulById = async (req, res) => { + try { + const soulId = req?.params?.id; + res.send( + await performDBAction(Actions.fetchById, JSRF_DB, GraffitiSoul, soulId) + ); + } catch (err) { + LOGGER.error(`Could not fetch JSRF GraffitiSoul With ID: ${soulId}`, err); + res + .status(500) + .json({message: "Failed to fetch JSRF GraffitiSoul By ID", err: err}); + } +}; + +export const fetchJSRSouls = async (req) => { + if (req?.query) { + return await performDBAction( + Actions.fetchWithQuery, + JSR_DB, + GraffitiSoul, + null, + req?.query + ); + } + return await performDBAction(Actions.fetchAll, JSR_DB, GraffitiSoul, null); +}; + +export const fetchJSRFSouls = async (req) => { + if (req?.query) { + return await performDBAction( + Actions.fetchWithQuery, + JSRF_DB, + GraffitiSoul, + null, + req?.query + ); + } + return await performDBAction(Actions.fetchAll, JSRF_DB, GraffitiSoul, null); +}; diff --git a/src/controllers/utilController.js b/src/controllers/utilController.js index efbedf9..ec22384 100644 --- a/src/controllers/utilController.js +++ b/src/controllers/utilController.js @@ -3,19 +3,19 @@ import {Actions} from "../config/dbActions.js"; import Constants from "../constants/dbConstants.js"; import LOGGER from "../utils/logger.js"; -const {JSR_DB, JSRF_DB, BRC_DB, gameMap} = Constants; +const {JSR_DB, JSRF_DB, BRC_DB, gameMap, CORE_DB} = Constants; /* Helper Functions to support all other Controllers */ export const fetchRandom = async (req, resource, game) => { try { - const games = + const games = game === 'N/A' ? [CORE_DB] : resource === "Audio" ? [JSR_DB, JSRF_DB] : [JSR_DB, JSRF_DB, BRC_DB]; const selectedGame = req?.query?.game; const count = Number(req?.query?.count); const safeCount = Number.isFinite(count) && count > 0 ? count : 1; /* if a game is provided */ - if (game || selectedGame) { + if ((game && game !== 'N/A') || selectedGame) { const dbName = game || gameMap[selectedGame]; return await performDBAction( Actions.fetchRandom, diff --git a/src/managers/MiddlewareManager.js b/src/managers/MiddlewareManager.js index 59fcc1f..119f4c1 100644 --- a/src/managers/MiddlewareManager.js +++ b/src/managers/MiddlewareManager.js @@ -164,7 +164,7 @@ const cacheMiddleware = (req, res, next) => { } res.sendResponse = res.send; res.send = (body) => { - cache.put(cacheKey, body, 3600000); // 1 hour cache time, restart the service to bypass + cache.put(cacheKey, body, 3600000); // 1 hour cache time, restart the service to bypass or run /cache/clear res.sendResponse(body); }; LOGGER.info(`Cache missed for url ${req.url}`); diff --git a/src/public/docs.html b/src/public/docs.html index 95530a0..bd8fac4 100644 --- a/src/public/docs.html +++ b/src/public/docs.html @@ -41,6 +41,7 @@

Resources

  • Locations
  • Levels
  • Graffiti Tags
  • +
  • Graffiti Souls
  • Songs
  • Artists
  • Collectibles
  • @@ -48,7 +49,6 @@

    Resources

    The following Resources will be added in a future release of JSRAPI.

    If you would like to contribute in adding any of these resources, see the Contributing Docs.