From 138b815d92e652d1e2a692e809f8d7795f9430c3 Mon Sep 17 00:00:00 2001 From: Kaipo Wilmeth Date: Mon, 8 Sep 2025 14:17:48 -0500 Subject: [PATCH 1/6] docs --- src/public/index.html | 24 +++++++++- src/public/js/apiTable.js | 92 ++++++++++++++++++++++++++++++++++++++ src/public/js/docs.js | 79 ++++++++++++-------------------- src/public/style/index.css | 54 +++++++++++++++++++--- 4 files changed, 192 insertions(+), 57 deletions(-) create mode 100644 src/public/js/apiTable.js diff --git a/src/public/index.html b/src/public/index.html index a2981b0..3b70901 100644 --- a/src/public/index.html +++ b/src/public/index.html @@ -13,6 +13,18 @@ name="keywords" content="jet set radio, api, documentation, bomb rush cyberfunk, video game" /> + + + + + + Jet Set Radio API @@ -29,13 +41,17 @@

JSRAPI

All The Data from Jet Set Radio, Jet Set Radio Future, and Bomb Rush - Cyberfunk you could want + Cyberfunk you could want in JSON format.

games, characters, songs, graffiti-tags, locations, and more!

Check out the documentation to get started

+

+ Click here to view a list of + available endpoints +

Interested in contributing to the project? Check out the JSRAPI

+
+ + diff --git a/src/public/js/apiTable.js b/src/public/js/apiTable.js new file mode 100644 index 0000000..daf614f --- /dev/null +++ b/src/public/js/apiTable.js @@ -0,0 +1,92 @@ +export function createApiTable() { + const container = document.createElement("div"); + container.className = "api-table-container"; + + const table = document.createElement("table"); + table.className = "api-table"; + + // Header + const headerRow = document.createElement("tr"); + ["Endpoint", "Description"].forEach((text) => { + const th = document.createElement("th"); + th.textContent = text; + headerRow.appendChild(th); + }); + table.appendChild(headerRow); + + // Base URL + const baseUrl = "https://jetsetradio-api.onrender.com"; + + // Example rows + const rows = [ + { + endpoint: "/v1/api/audio/jsrf?speaker=DJ Professor K", + description: "Returns all quotes/audio from DJ Professor K from JSRF", + }, + { + endpoint: "/v1/api/games", + description: + "Lists all games in the Jet Set Radio series and surrounding games", + }, + { + endpoint: "/v1/api/songs/brc", + description: "Returns all songs in Bomb Rush Cyberfunk", + }, + { + endpoint: "/v1/api/characters", + description: "Returns character information from all games", + }, + { + endpoint: "/v1/api/characters/jsrf", + description: "Returns character information from Jet Set Radio Future", + }, + { + endpoint: "/v1/api/songs/random?count=3", + description: + "Returns 3 random songs from any game. The /random route works on most endpoints.", + }, + { + endpoint: "/v1/api/artists/643865b4af5362b86b844d60/songs", + description: + "Returns all songs by an artist. This example is Hideki Naganuma", + }, + { + endpoint: "/v1/api/locations/random?game=jsr", + description: + "Returns a random location from Jet Set Radio/Jet Grind Radio", + }, + { + endpoint: "/v1/api/graffitiTags?size=L", + description: "Returns all Large Graffiti Tags from any game", + }, + { + endpoint: "/v1/api/collectibles?type=Outfit", + description: "Returns all Outfit collectibles from Bomb Rush Cyberfunk", + }, + ]; + + rows.forEach(({endpoint, description}) => { + const tr = document.createElement("tr"); + + const tdEndpoint = document.createElement("td"); + // Create clickable link + const link = document.createElement("a"); + link.href = `${baseUrl}${endpoint}`; + link.textContent = endpoint; + link.target = "_blank"; // open in new tab + link.rel = "noopener noreferrer"; // security + link.style.color = "inherit"; // keep the same color as the table text + link.style.textDecoration = "none"; // remove underline if needed + tdEndpoint.appendChild(link); + + const tdDesc = document.createElement("td"); + tdDesc.textContent = description; + + tr.appendChild(tdEndpoint); + tr.appendChild(tdDesc); + table.appendChild(tr); + }); + + container.appendChild(table); + return container; +} diff --git a/src/public/js/docs.js b/src/public/js/docs.js index 358b569..59cfe83 100644 --- a/src/public/js/docs.js +++ b/src/public/js/docs.js @@ -8,56 +8,33 @@ import artistResource from "./examples/artistExample.js"; import collectibleResource from "./examples/collectibleExample.js"; import audioResource from "./examples/audioExample.js"; -const gameResponse = document.querySelector('#game-response'); -if (gameResponse) { - gameResponse.textContent = JSON.stringify(gameResource, null, 4); -} -const characterResponse = document.querySelector('#character-response'); -if (characterResponse) { - characterResponse.textContent = JSON.stringify(characterResource, null, 4); -} -const locationResponse = document.querySelector('#location-response'); -if (locationResponse) { - locationResponse.textContent = JSON.stringify(locationResource, null, 4); -} -const levelResponse = document.querySelector('#level-response'); -if (levelResponse) { - levelResponse.textContent = JSON.stringify(levelResource, null, 4); -} -const graffitiTagResponse = document.querySelector('#graffiti-tag-response'); -if (graffitiTagResponse) { - graffitiTagResponse.textContent = JSON.stringify(graffitiTagResource, null, 4); -} -const songResponse = document.querySelector('#song-response'); -if (songResponse) { - songResponse.textContent = JSON.stringify(songResource, null, 4); -} -const artistResponse = document.querySelector('#artist-response'); -if (artistResponse) { - artistResponse.textContent = JSON.stringify(artistResource, null, 4); -} -const collectibleResponse = document.querySelector('#collectible-response'); -if (collectibleResponse) { - collectibleResponse.textContent = JSON.stringify(collectibleResource, null, 4); -} -const audioResponse = document.querySelector('#audio-response'); -if (audioResponse) { - audioResponse.textContent = JSON.stringify(audioResource, null, 4); -} +const resources = [ + {selector: "#game-response", data: gameResource}, + {selector: "#character-response", data: characterResource}, + {selector: "#location-response", data: locationResource}, + {selector: "#level-response", data: levelResource}, + {selector: "#graffiti-tag-response", data: graffitiTagResource}, + {selector: "#song-response", data: songResource}, + {selector: "#artist-response", data: artistResource}, + {selector: "#collectible-response", data: collectibleResource}, + {selector: "#audio-response", data: audioResource}, +]; -const expandableButtons = document.querySelectorAll(".expandable-button"); -if (expandableButtons) { - expandableButtons.forEach(button => { - button.addEventListener("click", () => { - if (!button.classList.contains('expanded')) { - button.classList.add('expanded'); - button.textContent = 'Collapse'; - } else { - button.classList.remove('expanded'); - button.textContent = 'Expand'; - } - const content = button.parentElement.nextElementSibling; - content.style.display = content.style.display === "none" ? "block" : "none"; - }); +// Render JSON data into response elements +resources.forEach(({selector, data}) => { + const el = document.querySelector(selector); + if (el) el.textContent = JSON.stringify(data, null, 4); +}); + +// Expand/collapse buttons +document.querySelectorAll(".expandable-button").forEach((button) => { + button.addEventListener("click", () => { + const expanded = button.classList.toggle("expanded"); + button.textContent = expanded ? "Collapse" : "Expand"; + + const content = button.parentElement.nextElementSibling; + if (content) { + content.style.display = expanded ? "block" : "none"; + } }); -} \ No newline at end of file +}); diff --git a/src/public/style/index.css b/src/public/style/index.css index 56bef00..a21b266 100644 --- a/src/public/style/index.css +++ b/src/public/style/index.css @@ -19,12 +19,12 @@ a { @font-face { font-family: jetSet; - src: url('/font/Jet-Set.ttf'); + src: url("/font/Jet-Set.ttf"); } @font-face { font-family: jetSetItalic; - src: url('/font/Jet-Set-Italic.ttf'); + src: url("/font/Jet-Set-Italic.ttf"); } #img-container { @@ -46,11 +46,12 @@ a { position: absolute; left: 50%; top: 50%; - transform: translate(-50%,-50%); + transform: translate(-50%, -50%); font-size: 5.5vw; } -#documentation, #swagger { +#documentation, +#swagger { position: absolute; right: 3%; top: 3%; @@ -102,4 +103,47 @@ footer a img { width: 100%; height: auto; min-width: 50px; -} \ No newline at end of file +} + +/* API TABLE */ +.api-table-container { + width: 100%; + overflow-x: auto; + margin-top: 4rem; + padding: 0 6rem; +} + +.api-table { + font-family: jetSet; + width: 100%; + border-collapse: collapse; +} + +.api-table th, +.api-table td { + border: 1px solid #747474; + padding: 1rem; + text-align: left; + vertical-align: top; +} + +.api-table th { + background: #1ed31e7b; + font-size: 1.3rem; +} +.api-table td { + font-size: 1.2rem; +} + +.api-table th:nth-child(2) { + text-align: right; +} + +.api-table td:first-child { + width: 40%; /* endpoint column */ +} + +.api-table td:nth-child(2) { + width: 40%; /* endpoint column */ + text-align: right; +} From c05a4c85460c6b31d968990b72ec254988cf2a1e Mon Sep 17 00:00:00 2001 From: Kaipo Wilmeth Date: Mon, 8 Sep 2025 14:54:17 -0500 Subject: [PATCH 2/6] cleanup --- src/public/js/apiTable.js | 12 ++++-------- src/utils/swagger-docs.json | 14 +++++++------- src/utils/swagger.js | 15 ++++++++------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/public/js/apiTable.js b/src/public/js/apiTable.js index daf614f..7475479 100644 --- a/src/public/js/apiTable.js +++ b/src/public/js/apiTable.js @@ -1,3 +1,4 @@ +/* Displays a Table on the home page Showing Some Available Endpoints */ export function createApiTable() { const container = document.createElement("div"); container.className = "api-table-container"; @@ -5,7 +6,6 @@ export function createApiTable() { const table = document.createElement("table"); table.className = "api-table"; - // Header const headerRow = document.createElement("tr"); ["Endpoint", "Description"].forEach((text) => { const th = document.createElement("th"); @@ -14,10 +14,7 @@ export function createApiTable() { }); table.appendChild(headerRow); - // Base URL const baseUrl = "https://jetsetradio-api.onrender.com"; - - // Example rows const rows = [ { endpoint: "/v1/api/audio/jsrf?speaker=DJ Professor K", @@ -69,14 +66,13 @@ export function createApiTable() { const tr = document.createElement("tr"); const tdEndpoint = document.createElement("td"); - // Create clickable link const link = document.createElement("a"); link.href = `${baseUrl}${endpoint}`; link.textContent = endpoint; - link.target = "_blank"; // open in new tab - link.rel = "noopener noreferrer"; // security + link.target = "_blank"; + link.rel = "noopener noreferrer"; link.style.color = "inherit"; // keep the same color as the table text - link.style.textDecoration = "none"; // remove underline if needed + link.style.textDecoration = "none"; tdEndpoint.appendChild(link); const tdDesc = document.createElement("td"); diff --git a/src/utils/swagger-docs.json b/src/utils/swagger-docs.json index 76dd75e..310c045 100644 --- a/src/utils/swagger-docs.json +++ b/src/utils/swagger-docs.json @@ -3,22 +3,22 @@ "info": { "title": "JetSetRadio-API", "version": "1.1.4", - "description": "Providing data for all things JSR and JSRF!" + "description": "Providing data for all things Jet Set Radio, Future, and Bomb Rush Cyberfunk!" }, "host": "localhost:9005", "basePath": "/v1/api/", "tags": [ { "name": "Games", - "description": "Titles from the JetSetRadio Franchise" + "description": "Titles from the JetSetRadio Franchise & Surrounding games" }, { "name": "Characters", - "description": "Characters from JSR/JSRF" + "description": "Characters from JSR/JSRF/BRC" }, { "name": "Locations", - "description": "Locations from JSR/JSRF" + "description": "Locations from JSR/JSRF/BRC" }, { "name": "Levels", @@ -26,15 +26,15 @@ }, { "name": "GraffitiTags", - "description": "All Graffiti-Points from the games" + "description": "All Graffiti-Points from JSR and JSRF" }, { "name": "Songs", - "description": "Soundtrack Data from JSR and JSRF" + "description": "Soundtrack Data from JSR/JSRF/BRC" }, { "name": "Artists", - "description": "Artist Data from JSR and JSRF" + "description": "Artist Data from JSR/JSRF/BRC" }, { "name": "Collectibles", diff --git a/src/utils/swagger.js b/src/utils/swagger.js index 90ab27b..51aad18 100644 --- a/src/utils/swagger.js +++ b/src/utils/swagger.js @@ -6,7 +6,8 @@ const doc = { info: { title: "JetSetRadio-API", version: process.env.npm_package_version, - description: "Providing data for all things JSR and JSRF!", + description: + "Providing data for all things Jet Set Radio, Future, and Bomb Rush Cyberfunk!", }, host: process.env.BASE_URL.split("http://")[1], schemes: ["https", "http"], @@ -14,15 +15,15 @@ const doc = { tags: [ { name: "Games", - description: "Titles from the JetSetRadio Franchise", + description: "Titles from the JetSetRadio Franchise & Surrounding games", }, { name: "Characters", - description: "Characters from JSR/JSRF", + description: "Characters from JSR/JSRF/BRC", }, { name: "Locations", - description: "Locations from JSR/JSRF", + description: "Locations from JSR/JSRF/BRC", }, { name: "Levels", @@ -30,15 +31,15 @@ const doc = { }, { name: "GraffitiTags", - description: "All Graffiti-Points from the games", + description: "All Graffiti-Points from JSR and JSRF", }, { name: "Songs", - description: "Soundtrack Data from JSR and JSRF", + description: "Soundtrack Data from JSR/JSRF/BRC", }, { name: "Artists", - description: "Artist Data from JSR and JSRF", + description: "Artist Data from JSR/JSRF/BRC", }, { name: "Collectibles", From e29baed6afaf439a3cc98512fdbb5a9bfe1ddd6e Mon Sep 17 00:00:00 2001 From: Kaipo Wilmeth Date: Mon, 8 Sep 2025 14:55:54 -0500 Subject: [PATCH 3/6] cleanup --- src/public/js/docs.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/public/js/docs.js b/src/public/js/docs.js index 59cfe83..2f130b7 100644 --- a/src/public/js/docs.js +++ b/src/public/js/docs.js @@ -20,7 +20,6 @@ const resources = [ {selector: "#audio-response", data: audioResource}, ]; -// Render JSON data into response elements resources.forEach(({selector, data}) => { const el = document.querySelector(selector); if (el) el.textContent = JSON.stringify(data, null, 4); From c3654c8bb1e4e362dadb007cdd355094f2755d63 Mon Sep 17 00:00:00 2001 From: Kaipo Wilmeth Date: Mon, 8 Sep 2025 15:27:00 -0500 Subject: [PATCH 4/6] adjust pipe route --- src/docs/DEV_SETUP.md | 7 ++----- src/managers/MiddlewareManager.js | 5 ++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/docs/DEV_SETUP.md b/src/docs/DEV_SETUP.md index a770f6c..95b6a4d 100644 --- a/src/docs/DEV_SETUP.md +++ b/src/docs/DEV_SETUP.md @@ -35,10 +35,7 @@ This page will guide you on setting up a development environment for this projec LOG_LEVEL=info # MONGO CONNECT (get from connection string) - MONGO_USER= - MONGO_PASS= - MONGO_CLUSTER= - MONGO_DOMAIN= + MONGO_URI= # MONGO DATABASES (names do not matter) JSR_DB= @@ -46,7 +43,7 @@ This page will guide you on setting up a development environment for this projec BRC_DB CORE_DB= ``` - The databases section in the env file are names of the databases. For development purposes it does not matter what these names are just as long as you can distinguish one from the other and you know which one is which. + The databases section in the env file are names of the databases. For development purposes it does not matter what these names are but I recommend labeling it as QA-JSR, QA-JSRF, QA-BRC, or something similar. 6. Run the project ```sh diff --git a/src/managers/MiddlewareManager.js b/src/managers/MiddlewareManager.js index c371da6..59fcc1f 100644 --- a/src/managers/MiddlewareManager.js +++ b/src/managers/MiddlewareManager.js @@ -103,6 +103,7 @@ const filterPipeRoutes = async (req, endpoints) => { if ( ((jsrCollections.includes(model) || jsrCollections.includes(model + "s")) && + !endpoint.includes("random") && endpoint.includes("jsr")) || endpoint.includes("levels") ) { @@ -111,12 +112,14 @@ const filterPipeRoutes = async (req, endpoints) => { if ( (jsrfCollections.includes(model) || jsrCollections.includes(model + "s")) && - endpoint.includes("jsrf") + endpoint.includes("jsrf") && + !endpoint.includes("random") ) { filteredEndpoints.push(endpoint); } if ( brcCollections.includes(model) && + !endpoint.includes("random") && (endpoint.includes("brc") || endpoint.includes("collectibles")) ) { filteredEndpoints.push(endpoint); From 6ebe0dbd24097524bb2fe3fdf7c37f1416911cc3 Mon Sep 17 00:00:00 2001 From: Kaipo Wilmeth Date: Mon, 8 Sep 2025 15:27:24 -0500 Subject: [PATCH 5/6] version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1b23a98..812dc9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jetsetradio-api", - "version": "1.1.4", + "version": "1.1.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jetsetradio-api", - "version": "1.1.4", + "version": "1.1.5", "license": "Apache 2.0", "dependencies": { "axios": "^1.11.0", diff --git a/package.json b/package.json index 8bc5047..5438b11 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jetsetradio-api", - "version": "1.1.4", + "version": "1.1.5", "description": "A Data Provider relating to the JSR/JSRF universe", "type": "module", "main": "src/app.js", From 6e007e18cbd450dfdbb341fd282f57a7ca405782 Mon Sep 17 00:00:00 2001 From: Kaipo Wilmeth Date: Mon, 8 Sep 2025 15:29:33 -0500 Subject: [PATCH 6/6] cleanup --- src/utils/swagger-docs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/swagger-docs.json b/src/utils/swagger-docs.json index 310c045..dd86a79 100644 --- a/src/utils/swagger-docs.json +++ b/src/utils/swagger-docs.json @@ -2,7 +2,7 @@ "swagger": "2.0", "info": { "title": "JetSetRadio-API", - "version": "1.1.4", + "version": "1.1.5", "description": "Providing data for all things Jet Set Radio, Future, and Bomb Rush Cyberfunk!" }, "host": "localhost:9005",