Skip to content

Commit b38e547

Browse files
authored
feat: add new endpoints for api (#22)
* refractor: update package name (#21) * feat: add new type definitions for discovered endpoints * refractor: remove static war id * feat: add new database models * refractor: add data pulling logic for new endpoints * feat: add statistic route for planets * fix: delete reward data on refresh * lib(routes): add statistic routes * feat: integrate statistic routes * lib(routes): add assignment routes * feat: integrate assignment routes * lib(routes): add report routes * feat: integrate assignment routes * fix: resolve error in data refresh method * refractor: remove unused variable * chore(tests): add tests for assignments, reports and statistics --------- Signed-off-by: Fabio Nettis <nettisfabio@gmail.com>
1 parent 512ac11 commit b38e547

File tree

21 files changed

+1001
-19
lines changed

21 files changed

+1001
-19
lines changed

.github/workflows/tests.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ env:
44
# prisma setip
55
DATABASE_URL: "file:./database/data.db"
66
# api setup
7-
WAR_ID: "801"
87
RATE_LIMIT: "200"
98
API_URL: "https://api.live.prod.thehelldiversgame.com/api"
109
# stratagem setup

Dockerfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ FROM oven/bun:latest as base
44
WORKDIR /usr/src/app
55

66
# Set environment variables
7-
ENV WAR_ID="801"
87
ENV RATE_LIMIT="200"
98
ENV DATABASE_URL="file:./database/data.db"
109
ENV API_URL="https://api.live.prod.thehelldiversgame.com/api"

__tests__/routes/assignments.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import app from "../../src";
2+
import type { Order } from "@prisma/client";
3+
import { describe, expect, it } from "bun:test";
4+
5+
describe("Assignment endpoints work as expected", () => {
6+
it("GET /assignment", async () => {
7+
const response = await app.request("/api/assignments");
8+
const json: { data: Order[]; error: object | null } =
9+
(await response.json()) as any;
10+
expect(response.status).toBe(200);
11+
expect(json).toHaveProperty("data");
12+
expect(json.data).toBeInstanceOf(Array);
13+
});
14+
15+
it("GET /assignment/:id", async () => {
16+
try {
17+
const response = await app.request("/api/assignments/1");
18+
const json: { data: Order; error: object | null } =
19+
(await response.json()) as any;
20+
expect(response.status).toBe(200);
21+
expect(json).toHaveProperty("data");
22+
expect(json.data).toHaveProperty("id");
23+
} catch {
24+
// this is ok, there is not always an assignment with id 1
25+
// because they are more dynamic than other entities
26+
}
27+
});
28+
29+
it("GET /assignment/:id/rewards", async () => {
30+
try {
31+
const response = await app.request("/api/assignments/1/rewards");
32+
const json: { data: Order; error: object | null } =
33+
(await response.json()) as any;
34+
expect(response.status).toBe(200);
35+
expect(json).toHaveProperty("data");
36+
expect(json.data).toHaveProperty("id");
37+
} catch {
38+
// this is ok, there is not always an reward for assignment with id 1
39+
// because they are more dynamic than other entities
40+
}
41+
});
42+
});

__tests__/routes/orders.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import app from "../../src";
22
import type { Order } from "@prisma/client";
33
import { describe, expect, it } from "bun:test";
44

5-
let res = null;
6-
75
describe("Order endpoints work as expected", () => {
86
it("GET /orders", async () => {
97
const response = await app.request("/api/orders");

__tests__/routes/planets.test.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import app from "../../src";
2-
import type { Planet } from "@prisma/client";
2+
import type { Planet, Stats } from "@prisma/client";
33
import { describe, expect, it } from "bun:test";
44

55
describe("Planet endpoints work as expected", () => {
@@ -53,4 +53,13 @@ describe("Planet endpoints work as expected", () => {
5353
expect(json).toHaveProperty("data");
5454
expect(json.data).toBeInstanceOf(Array);
5555
});
56+
57+
it("GET /planets/:id/statistics", async () => {
58+
const response = await app.request("/api/planets/1/statistics");
59+
const json: { data: Stats; error: object | null } =
60+
(await response.json()) as any;
61+
expect(response.status).toBe(200);
62+
expect(json).toHaveProperty("data");
63+
expect(json.data).toHaveProperty("id");
64+
});
5665
});

__tests__/routes/reports.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import app from "../../src";
2+
import type { Order } from "@prisma/client";
3+
import { describe, expect, it } from "bun:test";
4+
5+
describe("Report endpoints work as expected", () => {
6+
it("GET /reports", async () => {
7+
const response = await app.request("/api/reports");
8+
const json: { data: Order[]; error: object | null } =
9+
(await response.json()) as any;
10+
expect(response.status).toBe(200);
11+
expect(json).toHaveProperty("data");
12+
expect(json.data).toBeInstanceOf(Array);
13+
});
14+
15+
it("GET /reports/:id", async () => {
16+
try {
17+
const response = await app.request("/api/reports/1");
18+
const json: { data: Order; error: object | null } =
19+
(await response.json()) as any;
20+
expect(response.status).toBe(200);
21+
expect(json).toHaveProperty("data");
22+
expect(json.data).toHaveProperty("id");
23+
} catch {
24+
// this is ok, there is not always an report with id 1
25+
// because they are more dynamic than other entities
26+
}
27+
});
28+
});

__tests__/routes/statistics.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import app from "../../src";
2+
import type { Order } from "@prisma/client";
3+
import { describe, expect, it } from "bun:test";
4+
5+
describe("Statistic endpoints work as expected", () => {
6+
it("GET /statistics", async () => {
7+
const response = await app.request("/api/statistics");
8+
const json: { data: Order[]; error: object | null } =
9+
(await response.json()) as any;
10+
expect(response.status).toBe(200);
11+
expect(json).toHaveProperty("data");
12+
expect(json.data).toBeInstanceOf(Array);
13+
});
14+
15+
it("GET /statistics/:id", async () => {
16+
try {
17+
const response = await app.request("/api/statistics/94");
18+
const json: { data: Order; error: object | null } =
19+
(await response.json()) as any;
20+
expect(response.status).toBe(200);
21+
expect(json).toHaveProperty("data");
22+
expect(json.data).toHaveProperty("id");
23+
} catch {
24+
// this is ok, there is not always an statistic with id 94
25+
// because they are more dynamic than other entities
26+
}
27+
});
28+
29+
it("GET /statistics/galaxy", async () => {
30+
const response = await app.request("/api/statistics/galaxy");
31+
const json: { data: Order; error: object | null } =
32+
(await response.json()) as any;
33+
expect(response.status).toBe(200);
34+
expect(json).toHaveProperty("data");
35+
expect(json.data).toHaveProperty("id");
36+
});
37+
});
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
Warnings:
3+
4+
- Added the required column `time` to the `War` table without a default value. This is not possible if the table is not empty.
5+
6+
*/
7+
-- CreateTable
8+
CREATE TABLE "News" (
9+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
10+
"index" INTEGER NOT NULL,
11+
"type" INTEGER NOT NULL,
12+
"tagIds" TEXT NOT NULL,
13+
"message" TEXT NOT NULL,
14+
"publishedAt" DATETIME NOT NULL,
15+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
16+
"updatedAt" DATETIME NOT NULL
17+
);
18+
19+
-- CreateTable
20+
CREATE TABLE "Stats" (
21+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
22+
"missionsWon" BIGINT NOT NULL,
23+
"missionsLost" BIGINT NOT NULL,
24+
"missionTime" BIGINT NOT NULL,
25+
"bugKills" BIGINT NOT NULL,
26+
"automatonKills" BIGINT NOT NULL,
27+
"illuminateKills" BIGINT NOT NULL,
28+
"bulletsFired" BIGINT NOT NULL,
29+
"bulletsHit" BIGINT NOT NULL,
30+
"timePlayed" BIGINT NOT NULL,
31+
"deaths" BIGINT NOT NULL,
32+
"revives" BIGINT NOT NULL,
33+
"friendlyKills" BIGINT NOT NULL,
34+
"missionSuccessRate" INTEGER NOT NULL,
35+
"accuracy" INTEGER NOT NULL,
36+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
37+
"updatedAt" DATETIME NOT NULL
38+
);
39+
40+
-- CreateTable
41+
CREATE TABLE "Reward" (
42+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
43+
"index" INTEGER NOT NULL,
44+
"type" INTEGER NOT NULL,
45+
"amount" INTEGER NOT NULL,
46+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
47+
"updatedAt" DATETIME NOT NULL
48+
);
49+
50+
-- CreateTable
51+
CREATE TABLE "Assignment" (
52+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
53+
"index" INTEGER NOT NULL,
54+
"progress" INTEGER NOT NULL,
55+
"expiresAt" DATETIME NOT NULL,
56+
"type" INTEGER NOT NULL,
57+
"title" TEXT NOT NULL,
58+
"briefing" TEXT NOT NULL,
59+
"description" TEXT NOT NULL,
60+
"rewardId" INTEGER NOT NULL,
61+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
62+
"updatedAt" DATETIME NOT NULL,
63+
CONSTRAINT "Assignment_rewardId_fkey" FOREIGN KEY ("rewardId") REFERENCES "Reward" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
64+
);
65+
66+
-- RedefineTables
67+
PRAGMA foreign_keys=OFF;
68+
CREATE TABLE "new_Planet" (
69+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
70+
"index" INTEGER NOT NULL,
71+
"name" TEXT NOT NULL,
72+
"ownerId" INTEGER NOT NULL,
73+
"sectorId" INTEGER NOT NULL,
74+
"health" INTEGER NOT NULL,
75+
"maxHealth" INTEGER NOT NULL,
76+
"players" INTEGER NOT NULL,
77+
"disabled" BOOLEAN NOT NULL,
78+
"regeneration" INTEGER NOT NULL,
79+
"initialOwnerId" INTEGER NOT NULL,
80+
"positionX" REAL NOT NULL,
81+
"positionY" REAL NOT NULL,
82+
"globalEventId" INTEGER,
83+
"statisticId" INTEGER,
84+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
85+
"updatedAt" DATETIME NOT NULL,
86+
CONSTRAINT "Planet_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "Faction" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
87+
CONSTRAINT "Planet_sectorId_fkey" FOREIGN KEY ("sectorId") REFERENCES "Sector" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
88+
CONSTRAINT "Planet_initialOwnerId_fkey" FOREIGN KEY ("initialOwnerId") REFERENCES "Faction" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
89+
CONSTRAINT "Planet_globalEventId_fkey" FOREIGN KEY ("globalEventId") REFERENCES "GlobalEvent" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
90+
CONSTRAINT "Planet_statisticId_fkey" FOREIGN KEY ("statisticId") REFERENCES "Stats" ("id") ON DELETE SET NULL ON UPDATE CASCADE
91+
);
92+
INSERT INTO "new_Planet" ("createdAt", "disabled", "globalEventId", "health", "id", "index", "initialOwnerId", "maxHealth", "name", "ownerId", "players", "positionX", "positionY", "regeneration", "sectorId", "updatedAt") SELECT "createdAt", "disabled", "globalEventId", "health", "id", "index", "initialOwnerId", "maxHealth", "name", "ownerId", "players", "positionX", "positionY", "regeneration", "sectorId", "updatedAt" FROM "Planet";
93+
DROP TABLE "Planet";
94+
ALTER TABLE "new_Planet" RENAME TO "Planet";
95+
CREATE UNIQUE INDEX "Planet_index_key" ON "Planet"("index");
96+
CREATE UNIQUE INDEX "Planet_statisticId_key" ON "Planet"("statisticId");
97+
CREATE TABLE "new_War" (
98+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
99+
"index" INTEGER NOT NULL,
100+
"startDate" DATETIME NOT NULL,
101+
"endDate" DATETIME NOT NULL,
102+
"time" DATETIME NOT NULL,
103+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
104+
"updatedAt" DATETIME NOT NULL
105+
);
106+
INSERT INTO "new_War" ("createdAt", "endDate", "id", "index", "startDate", "updatedAt") SELECT "createdAt", "endDate", "id", "index", "startDate", "updatedAt" FROM "War";
107+
DROP TABLE "War";
108+
ALTER TABLE "new_War" RENAME TO "War";
109+
CREATE UNIQUE INDEX "War_index_key" ON "War"("index");
110+
PRAGMA foreign_key_check;
111+
PRAGMA foreign_keys=ON;
112+
113+
-- CreateIndex
114+
CREATE UNIQUE INDEX "News_index_key" ON "News"("index");
115+
116+
-- CreateIndex
117+
CREATE UNIQUE INDEX "Reward_index_key" ON "Reward"("index");
118+
119+
-- CreateIndex
120+
CREATE UNIQUE INDEX "Assignment_index_key" ON "Assignment"("index");
121+
122+
-- CreateIndex
123+
CREATE UNIQUE INDEX "Assignment_rewardId_key" ON "Assignment"("rewardId");

prisma/schema.prisma

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ model War {
1616
index Int @unique
1717
startDate DateTime
1818
endDate DateTime
19+
time DateTime
1920
createdAt DateTime @default(now())
2021
updatedAt DateTime @updatedAt
2122
}
@@ -66,6 +67,8 @@ model Planet {
6667
homeWorld HomeWorld[] @relation("HomeWorld")
6768
attacking Attack[] @relation("Attack")
6869
defending Attack[] @relation("Defend")
70+
statistic Stats? @relation(fields: [statisticId], references: [id])
71+
statisticId Int? @unique
6972
createdAt DateTime @default(now())
7073
updatedAt DateTime @updatedAt
7174
}
@@ -155,3 +158,60 @@ model Stratagem {
155158
createdAt DateTime @default(now())
156159
updatedAt DateTime @updatedAt
157160
}
161+
162+
model News {
163+
id Int @id @default(autoincrement())
164+
index Int @unique
165+
type Int
166+
tagIds String
167+
message String
168+
publishedAt DateTime
169+
createdAt DateTime @default(now())
170+
updatedAt DateTime @updatedAt
171+
}
172+
173+
model Stats {
174+
id Int @id @default(autoincrement())
175+
missionsWon BigInt
176+
missionsLost BigInt
177+
missionTime BigInt
178+
bugKills BigInt
179+
automatonKills BigInt
180+
illuminateKills BigInt
181+
bulletsFired BigInt
182+
bulletsHit BigInt
183+
timePlayed BigInt
184+
deaths BigInt
185+
revives BigInt
186+
friendlyKills BigInt
187+
missionSuccessRate Int
188+
accuracy Int
189+
createdAt DateTime @default(now())
190+
updatedAt DateTime @updatedAt
191+
planet Planet?
192+
}
193+
194+
model Reward {
195+
id Int @id @default(autoincrement())
196+
index Int @unique
197+
type Int
198+
amount Int
199+
createdAt DateTime @default(now())
200+
updatedAt DateTime @updatedAt
201+
assignment Assignment?
202+
}
203+
204+
model Assignment {
205+
id Int @id @default(autoincrement())
206+
index Int @unique
207+
progress Int
208+
expiresAt DateTime
209+
type Int
210+
title String
211+
briefing String
212+
description String
213+
reward Reward @relation(fields: [rewardId], references: [id])
214+
rewardId Int @unique
215+
createdAt DateTime @default(now())
216+
updatedAt DateTime @updatedAt
217+
}

0 commit comments

Comments
 (0)