Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
86e3058
feature: db scripts, apollo install
Oct 2, 2026
2ff6a31
Merge pull request #18 from IT2810-H26/feature/apollo-server
albertpl Oct 2, 2026
4c60d7f
la til enkelt eksempel med apollo
Oct 2, 2026
4bd4544
Create ssh-tunnel.md
albertpl Oct 8, 2026
d532d44
Update database-usage.md
albertpl Oct 8, 2026
40b14e4
Create grants.sql
albertpl Oct 8, 2026
bded41f
feat(frontend): legg til GameSummary-type for spillkort
laspark Oct 8, 2026
ac70bf5
feat(frontend): legg til GameCard-komponent
laspark Oct 8, 2026
885d705
feat(frontend): stil for GameCard
laspark Oct 8, 2026
b75b8f7
Merge pull request #19 from IT2810-H26/feature/spillkort
johabort Oct 9, 2026
759c451
feat(frontend): legg til view-prop i GameCard for liste og rutenett
laspark Oct 9, 2026
68b16e3
style(frontend): mindre bilde i liste og ny rutenett-visning for Game…
laspark Oct 9, 2026
1303f64
feat(frontend): legg til GameList som viser spill i liste eller rutenett
laspark Oct 9, 2026
9a16951
style(frontend): layout for GameList (4 per rad i rutenett)
laspark Oct 9, 2026
015cb55
chore(frontend): midlertidige mockdata for spill til GraphQL er klart
laspark Oct 9, 2026
967d0f0
feat(frontend): vis spill-lista med bytte mellom liste og rutenett
laspark Oct 9, 2026
ce63258
Merge pull request #22 from IT2810-H26/feature/spillkort
johabort Oct 9, 2026
015fbb8
feat(frontend): legg til useDebounce-hook
Oct 9, 2026
1a01103
feat(frontend): legg til SearchBar-komponent
Oct 9, 2026
567f324
style(frontend): firkantet søkefelt med skjult label og fokusramme
Oct 9, 2026
a72e089
Update database-setup.md
albertpl Oct 9, 2026
05a0f6f
feat(frontend): koble søk til spill-lista (midlertidig klientfiltreri…
Oct 9, 2026
ffd0f58
Merge pull request #23 from IT2810-H26/feature/apollo-server
albertpl Oct 9, 2026
a5f1664
Merge pull request #24 from IT2810-H26/feature/sok
clemenbe Oct 9, 2026
e40317b
lagt inn logo top left, og fjernet SPILL
Oct 9, 2026
ff2f1e5
Merge pull request #41 from IT2810-H26/feat/logo-top-right
clemenbe Oct 9, 2026
9414016
Merge branch 'dev' into server/fix-db-import
albertpl Oct 9, 2026
e300f65
Merge pull request #42 from IT2810-H26/server/fix-db-import
albertpl Oct 9, 2026
a457414
#27 fungerende graphql server
Oct 12, 2026
e512f22
readd .env.*
Oct 12, 2026
e1f726c
Merge pull request #45 from IT2810-H26/feature/graphql-server
albertpl Oct 12, 2026
ef2d526
search
Oct 12, 2026
c482411
Merge pull request #47 from IT2810-H26/feature/backend-search
albertpl Oct 12, 2026
6930865
filtering!
Oct 12, 2026
dda083a
Merge pull request #48 from IT2810-H26/feature/backend-filtering
albertpl Oct 12, 2026
b404781
backend api docs
Oct 12, 2026
712fedc
Merge pull request #49 from IT2810-H26/documentation/backend
albertpl Oct 12, 2026
2c72b64
Merge branch 'main' into dev
albertpl Oct 12, 2026
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
9 changes: 8 additions & 1 deletion backend/.env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
DATABASE_URL=postgresql://gameapp:<FYLL-INN-PASSORD>@localhost:5432/gamesdb
# tunnel script env vars
VM_USER=<ntnu-brukernavn>
VM_HOST=it2810-02.idi.ntnu.no
TUNNEL_PORT=5433

# backend server env vars
DATABASE_URL=postgresql://webapp:<PASSORD>@localhost:5433/gamesdb
PORT=3001
JWT_TOKEN=<server-rand-token>
293 changes: 293 additions & 0 deletions backend/backend-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
# Backend-API
## Queries
### game

Henter informasjon om ett enkelt spill ved ID.

```graphql
game(id: ID!): Game
```

#### Argumenter

| Navn | Type | Default | Beskrivelse |
| ---- | ----- | ------- | --------------- |
| `id` | `ID!` | — | ID til spillet. |

#### Returnerer

[`Game`](#game-1). Returnerer `null` hvis spillet ikke finnes eller id-en er ugyldig.

#### Eksempel

```graphql
{
game(id: "3498") {
name
esrbRating
genres { name }
}
}
```

```json
{
"data": {
"game": {
"name": "Grand Theft Auto V",
"esrbRating": "Mature",
"genres": [{ "name": "Action" }]
}
}
}
```

---

### games

Henter en side med spill, med valgfritt søk og filtre. Resultatet er sortert etter popularitet.

```graphql
games(search: String, filter: GameFilter, first: Int = 20): GameConnection!
```

#### Argumenter

| Navn | Type | Default | Beskrivelse |
| -------- | --------------------------- | ------- | --------------------------------------------------------------------------------------------- |
| `search` | `String` | — | Søk i tittel og alternative navn. Skiller ikke mellom store og små bokstaver, og matcher deler av navnet. |
| `filter` | [`GameFilter`](#gamefilter) | — | Filtrering på sjanger, plattform og utgivelsesår. |
| `first` | `Int` | `20` | Antall spill på siden. Begrenset til 1–50. |

Alle argumenter er valgfrie og kan kombineres.

#### Returnerer

[`GameConnection`](#gameconnection) med spillene på siden og totalt antall treff.

#### Eksempel: søk

```graphql
{
games(search: "zelda", first: 3) {
totalCount
edges { node { name } }
}
}
```

```json
{
"data": {
"games": {
"totalCount": 55,
"edges": [
{ "node": { "name": "The Legend of Zelda: Breath of the Wild" } },
{ "node": { "name": "The Legend of Zelda: Ocarina of Time" } },
{ "node": { "name": "The Legend of Zelda: Tears of the Kingdom" } }
]
}
}
}
```

#### Eksempel: filtre

Action- og RPG-spill på PC, utgitt 2015–2020:

```graphql
{
games(
filter: { genreIds: ["1", "14"], platformIds: ["9"], releasedFrom: 2015, releasedTo: 2020 }
first: 3
) {
totalCount
edges { node { name released } }
}
}
```

```json
{
"data": {
"games": {
"totalCount": 2006,
"edges": [
{ "node": { "name": "The Witcher 3: Wild Hunt", "released": "2015-05-18" } },
{ "node": { "name": "Fallout 4", "released": "2015-11-09" } },
{ "node": { "name": "Cyberpunk 2077", "released": "2020-12-10" } }
]
}
}
}
```

---

### genres

Henter alle sjangre, sortert alfabetisk.

```graphql
genres: [Facet!]!
```

#### Argumenter

Ingen.

#### Returnerer

Liste med [`Facet`](#facet).

#### Eksempel

```graphql
{
genres { id name }
}
```

```json
{
"data": {
"genres": [
{ "id": "1", "name": "Action" },
{ "id": "2", "name": "Adventure" },
{ "id": "3", "name": "Arcade" }
]
}
}
```

---

### platforms

Henter alle plattformfamilier (PC, PlayStation, Xbox, …), sortert alfabetisk.

```graphql
platforms: [Facet!]!
```

#### Argumenter

Ingen.

#### Returnerer

Liste med [`Facet`](#facet).

Merk: ID-ene her er plattformfamilier og er ikke de samme som ID-ene i `Game.platforms`, som er enkeltkonsoller.

#### Eksempel

```graphql
{
platforms { id name }
}
```

```json
{
"data": {
"platforms": [
{ "id": "9", "name": "PC" },
{ "id": "10", "name": "PlayStation" },
{ "id": "13", "name": "Xbox" }
]
}
}
```

## Mutations
> Dette skal legges til når funksjonalitet for brukere blir lagt til
## Types
### Game

Et spill med detaljer og relasjoner.

| Felt | Type | Beskrivelse |
| --------------------------- | ------------------- | ----------------------------------------------------------------- |
| `id` | `ID!` | ID til spillet. |
| `name` | `String!` | Tittel. |
| `description` | `String` | Beskrivelse i ren tekst. |
| `released` | `String` | Utgivelsesdato, `YYYY-MM-DD`. |
| `website` | `String` | Offisiell nettside. |
| `added` | `Int!` | Antall RAWG-brukere som har lagt spillet til i en liste. Brukes som mål på popularitet. |
| `metacritic` | `Int` | Metacritic-score, 0–100. |
| `esrbRating` | `String` | Amerikansk aldersgrense, f.eks. `Mature`. |
| `dominantColor` | `String` | Hovedfargen i forsidebildet som hex, f.eks. `0f0f0f`. |
| `backgroundImage` | `String` | URL til forsidebildet. |
| `backgroundImageAdditional` | `String` | URL til et ekstra bilde. |
| `screenshots` | `[String!]!` | URL-er til skjermbilder. Tom liste hvis ingen. |
| `genres` | [`[Facet!]!`](#facet) | Sjangre. |
| `platforms` | [`[Facet!]!`](#facet) | Enkeltkonsoller, f.eks. PlayStation 4. |
| `stores` | [`[Facet!]!`](#facet) | Butikker spillet selges i. |
| `developers` | [`[Facet!]!`](#facet) | Utviklere. |
| `publishers` | [`[Facet!]!`](#facet) | Utgivere. |
| `tags` | [`[Facet!]!`](#facet) | Tagger fra RAWG, f.eks. Open World. |

Relasjonene returnerer en tom liste hvis spillet ikke har noen.

---

### Facet

Felles type for sjangre, plattformer, butikker, utviklere, utgivere og tagger.

| Felt | Type | Beskrivelse |
| ------ | --------- | ----------- |
| `id` | `ID!` | ID. |
| `name` | `String!` | Navn. |

---

### GameConnection

Resultatet av [`games`](#games). Følger Relay-mønsteret for paginering (se [dokumentasjon](https://graphql.org/learn/pagination/)).

| Felt | Type | Beskrivelse |
| ------------ | --------------------------- | --------------------------------------------------- |
| `edges` | [`[GameEdge!]!`](#gameedge) | Spillene på denne siden. |
| `pageInfo` | [`PageInfo!`](#pageinfo) | Informasjon for å hente neste side. |
| `totalCount` | `Int!` | Totalt antall spill som matcher søk og filtre. |

---

### GameEdge

Ett spill i en [`GameConnection`](#gameconnection).

| Felt | Type | Beskrivelse |
| -------- | -------------------- | ------------------------------------ |
| `node` | [`Game!`](#game-1) | Spillet. |
| `cursor` | `String!` | Posisjonen til spillet i listen. |

---

### PageInfo

| Felt | Type | Beskrivelse |
| ------------- | ---------- | ------------------------------------------------------------- |
| `hasNextPage` | `Boolean!` | `true` hvis det finnes flere spill etter denne siden. |
| `endCursor` | `String` | Cursor til siste spill på siden. Sendes som `after` for neste side. |

---

### GameFilter

Input-type for filtrering i [`games`](#games). Alle felt er valgfrie.

| Felt | Type | Beskrivelse |
| -------------- | -------- | ------------------------------------------------------------------------------ |
| `genreIds` | `[ID!]` | Spill som har **alle** de valgte sjangrene. ID-er fra [`genres`](#genres). |
| `platformIds` | `[ID!]` | Spill på **minst én** av de valgte plattformfamiliene. ID-er fra [`platforms`](#platforms). |
| `releasedFrom` | `Int` | Utgitt dette året eller senere, f.eks. `2015`. |
| `releasedTo` | `Int` | Utgitt dette året eller tidligere, f.eks. `2020`. |

Merk: Spill uten utgivelsesdato utelates når `releasedFrom` eller `releasedTo` er satt. ID-er som ikke er tall ignoreres.


7 changes: 4 additions & 3 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"dev": "tsx watch src/index.ts",
"dev": "tsx watch --env-file=.env src/index.ts",
"compile": "tsc",
"build": "tsc",
"start": "node dist/index.js",
"start": "pnpm run build && node dist/index.js",
"lint": "eslint ."
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@apollo/server": "^5.5.1",
"dotenv": "^18.0.5",
Expand Down
3 changes: 3 additions & 0 deletions backend/src/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

// server jwt secret
// const secret = process.env.JWT_SECRET;
7 changes: 7 additions & 0 deletions backend/src/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import pg from 'pg';

const url = process.env.DATABASE_URL;
if (!url) throw new Error("DATABASE_URL not set in .env ...")

//pg pool
export const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL})
23 changes: 21 additions & 2 deletions backend/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,21 @@
// placeholder, erstattes av apollo server senere
console.log('backend');
import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
import { pool } from './db.js';
import { typeDefs } from './schema.js';
import { resolvers } from './resolvers.js';

// apollo-server port number [default port 3001]
const port = Number(process.env.PORT ?? 3001)

// tester db tilkobling med en query
await pool.query('SELECT 1');

// apollo server instance
const server = new ApolloServer({ typeDefs, resolvers });

// pass apolloserver to standaloneserver
const { url } = await startStandaloneServer(server, {
listen: { port },
});

console.log(`Server ready at: ${url}`);
Loading
Loading