Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
7 changes: 2 additions & 5 deletions src/docs/DEV_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,15 @@ 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=
JSRF_DB=
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
Expand Down
5 changes: 4 additions & 1 deletion src/managers/MiddlewareManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -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")
) {
Expand All @@ -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);
Expand Down
24 changes: 23 additions & 1 deletion src/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@
name="keywords"
content="jet set radio, api, documentation, bomb rush cyberfunk, video game"
/>
<meta name="author" content="Jet Set Radio API Community" />
<meta property="og:title" content="Jet Set Radio API" />
<meta
property="og:description"
content="Integrate Jet Set Radio, JSRF, and Bomb Rush Cyberfunk data into your applications with this free API."
/>
<meta
property="og:image"
content="https://jetsetradio-api.onrender.com/img/jsrapi-wallpaper.webp"
/>
<meta property="og:url" content="https://jetsetradio-api.onrender.com/" />
<meta name="twitter:card" content="summary_large_image" />
<title>Jet Set Radio API</title>
<link rel="canonical" href="https://jetsetradio-api.onrender.com/" />
<link rel="stylesheet" href="./style/index.css" />
Expand All @@ -29,13 +41,17 @@ <h2>JSRAPI</h2>
<div class="main-container text-center">
<p>
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.
</p>
<p>games, characters, songs, graffiti-tags, locations, and more!</p>
<p>
Check out the <a class="inline-a" href="/docs">documentation</a> to
get started
</p>
<p>
Click <a class="inline-a" href="/api-docs">here</a> to view a list of
available endpoints
</p>
<p>
Interested in contributing to the project? Check out the
<a
Expand All @@ -50,6 +66,7 @@ <h2>JSRAPI</h2>
</p>
</div>
</div>
<div id="api-docs"></div>
<footer>
<a href="https://github.com/Jet-Set-Radio-API/JetSetRadio-API"
><img src="./img/github.webp" alt="github-page-link"
Expand All @@ -58,5 +75,10 @@ <h2>JSRAPI</h2>
><img src="./img/swagger.webp" alt="swagger-docs-button"
/></a>
</footer>

<script type="module">
import {createApiTable} from "/js/apiTable.js";
document.getElementById("api-docs").appendChild(createApiTable());
</script>
</body>
</html>
88 changes: 88 additions & 0 deletions src/public/js/apiTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/* Displays a Table on the home page Showing Some Available Endpoints */
export function createApiTable() {
const container = document.createElement("div");
container.className = "api-table-container";

const table = document.createElement("table");
table.className = "api-table";

const headerRow = document.createElement("tr");
["Endpoint", "Description"].forEach((text) => {
const th = document.createElement("th");
th.textContent = text;
headerRow.appendChild(th);
});
table.appendChild(headerRow);

const baseUrl = "https://jetsetradio-api.onrender.com";
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");
const link = document.createElement("a");
link.href = `${baseUrl}${endpoint}`;
link.textContent = endpoint;
link.target = "_blank";
link.rel = "noopener noreferrer";
link.style.color = "inherit"; // keep the same color as the table text
link.style.textDecoration = "none";
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;
}
78 changes: 27 additions & 51 deletions src/public/js/docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,56 +8,32 @@ 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";
});
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";
}
});
}
});
54 changes: 49 additions & 5 deletions src/public/style/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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%;
Expand Down Expand Up @@ -102,4 +103,47 @@ footer a img {
width: 100%;
height: auto;
min-width: 50px;
}
}

/* 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;
}
Loading