diff --git a/backend/deploy/README.md b/backend/deploy/README.md index 55701c1..9b8eae6 100644 --- a/backend/deploy/README.md +++ b/backend/deploy/README.md @@ -3,10 +3,10 @@ Mal for å kjøre GraphQL-backenden som egen systemd-tjeneste på `it2810-36.idi.ntnu.no`. Steg-for-steg på VM: [docs/vm-backend.md §7](../../docs/vm-backend.md#7-graphql-med-systemd-port-3001). -**Verifisert på VM (oktober 2026):** tjenesten kjører som `User=birkjr`, -`Group=eall_s`, med Node -`/home/birkjr/.nvm/versions/node/v24.21.0/bin/node`, -`WorkingDirectory=/home/birkjr/T36-Project-2/backend`, miljø fra +**Verifisert på VM (oktober 2026):** tjenesten kjører som +`User=`, `Group=eall_s` (primærgruppe på IT2810-VM), med Node +fra nvm (f.eks. `~/.nvm/versions/node/v24.21.0/bin/node`), +`WorkingDirectory=~/T36-Project-2/backend`, miljø fra `/etc/t36-project2/backend.env`. GraphQL svarer på `127.0.0.1:3001/graphql` (`health`, `listings`, `createListing`); `systemctl restart` og `enabled` er testet. VM-reboot er ikke testet. @@ -77,15 +77,21 @@ prosessen, men ikke for «alle» på VM: ```bash export DEPLOY_USER="" +# Samme gruppe som `Group=` i systemd-enheten (på VM ofte primærgruppen, f.eks. eall_s). +export DEPLOY_GROUP="$(id -gn "${DEPLOY_USER}")" sudo mkdir -p /etc/t36-project2 sudo cp "/home/${DEPLOY_USER}/T36-Project-2/backend/deploy/backend.env.example" \ /etc/t36-project2/backend.env sudo nano /etc/t36-project2/backend.env # DATABASE_URL, HOST, PORT sudo chmod 640 /etc/t36-project2/backend.env -sudo chown "root:${DEPLOY_USER}" /etc/t36-project2/backend.env +sudo chown "root:${DEPLOY_GROUP}" /etc/t36-project2/backend.env ``` +Med `640` kan prosessen lese filen når tjenesten kjører som `User=${DEPLOY_USER}` og +`Group=${DEPLOY_GROUP}`. Hvis `Group=` i unit-filen avviker fra `DEPLOY_GROUP`, juster +enten `chown` eller `Group=` slik at de stemmer. + **Krav i filen:** `HOST=127.0.0.1`, `PORT=3001`. GraphQL-implementasjonen må respektere disse. diff --git a/backend/src/db/listingsQuery.test.ts b/backend/src/db/listingsQuery.test.ts index 255bd58..07b1c07 100644 --- a/backend/src/db/listingsQuery.test.ts +++ b/backend/src/db/listingsQuery.test.ts @@ -1,3 +1,4 @@ +/** Enhetstester for SQL-bygging i listingsQuery. */ import { describe, expect, it } from 'vitest'; import type { ListingFilter } from '../validation/listingFilterArgs.js'; diff --git a/backend/src/db/listingsQuery.ts b/backend/src/db/listingsQuery.ts index b8a357b..4d97ee7 100644 --- a/backend/src/db/listingsQuery.ts +++ b/backend/src/db/listingsQuery.ts @@ -1,3 +1,4 @@ +/** Bygger WHERE- og ORDER BY-deler for listings-spørringer (parameterisert SQL). */ import type { ListingFilter, ListingSort, diff --git a/backend/src/db/listingsRepository.ts b/backend/src/db/listingsRepository.ts index 6b1d8bb..6f24f6e 100644 --- a/backend/src/db/listingsRepository.ts +++ b/backend/src/db/listingsRepository.ts @@ -1,3 +1,4 @@ +/** PostgreSQL-tilgang for listings: side, enkelt rad, områder og insert. */ import { randomUUID } from 'node:crypto'; import type { Listing, ListingRow } from '../types/listing.js'; diff --git a/backend/src/graphql/graphql.api.test.ts b/backend/src/graphql/graphql.api.test.ts index 6b3a361..1f3b4ff 100644 --- a/backend/src/graphql/graphql.api.test.ts +++ b/backend/src/graphql/graphql.api.test.ts @@ -1,3 +1,4 @@ +/** Integrasjonstester for health, listing, createListing og listingAreas. */ import type { ApolloServer } from '@apollo/server'; import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest'; diff --git a/backend/src/graphql/listingsFilter.api.test.ts b/backend/src/graphql/listingsFilter.api.test.ts index fdc6802..a32908f 100644 --- a/backend/src/graphql/listingsFilter.api.test.ts +++ b/backend/src/graphql/listingsFilter.api.test.ts @@ -1,3 +1,4 @@ +/** API-tester for listings med søk, filtre og sortering. */ import type { ApolloServer } from '@apollo/server'; import { afterAll, beforeAll, describe, expect, it } from 'vitest'; diff --git a/backend/src/graphql/listingsPagination.api.test.ts b/backend/src/graphql/listingsPagination.api.test.ts index 205763c..4d75af6 100644 --- a/backend/src/graphql/listingsPagination.api.test.ts +++ b/backend/src/graphql/listingsPagination.api.test.ts @@ -1,3 +1,4 @@ +/** API-tester for paginerte listings-spørringer. */ import type { ApolloServer } from '@apollo/server'; import { afterAll, beforeAll, describe, expect, it } from 'vitest'; diff --git a/backend/src/graphql/resolvers.ts b/backend/src/graphql/resolvers.ts index 884c3b5..e41fba6 100644 --- a/backend/src/graphql/resolvers.ts +++ b/backend/src/graphql/resolvers.ts @@ -1,3 +1,4 @@ +/** GraphQL resolvere — kobler spørringer og mutasjoner til repository og validering. */ import { GraphQLError } from 'graphql'; import { diff --git a/backend/src/graphql/schema.ts b/backend/src/graphql/schema.ts index 61d22b9..62a8996 100644 --- a/backend/src/graphql/schema.ts +++ b/backend/src/graphql/schema.ts @@ -1,3 +1,4 @@ +/** GraphQL typeDefs for annonser, vurderinger, paginering, filtre og mutasjoner. */ export const typeDefs = `#graphql enum ToolCategory { powerTools diff --git a/backend/src/scripts/seed.ts b/backend/src/scripts/seed.ts index 97c7f5b..f42406b 100644 --- a/backend/src/scripts/seed.ts +++ b/backend/src/scripts/seed.ts @@ -1,3 +1,4 @@ +/** Idempotent seed av de ti faste eksempelannonsene i listings. */ import { pool } from '../db/pool.js'; import { seedListings } from '../seed/listings.js'; import { seedReviews } from '../seed/reviews.js'; diff --git a/backend/src/seed/generateListings.test.ts b/backend/src/seed/generateListings.test.ts index 48b6173..baade89 100644 --- a/backend/src/seed/generateListings.test.ts +++ b/backend/src/seed/generateListings.test.ts @@ -1,3 +1,4 @@ +/** Enhetstester for deterministisk generateListings. */ import { describe, expect, it } from 'vitest'; import { diff --git a/backend/src/server.ts b/backend/src/server.ts index 1326def..2e6f8c0 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -1,3 +1,4 @@ +/** Starter Apollo Server (GraphQL) med HOST/PORT fra miljø. */ import 'dotenv/config'; import { ApolloServer } from '@apollo/server'; diff --git a/backend/src/test/apolloTestServer.ts b/backend/src/test/apolloTestServer.ts index a2ee9e4..3818dd9 100644 --- a/backend/src/test/apolloTestServer.ts +++ b/backend/src/test/apolloTestServer.ts @@ -1,3 +1,4 @@ +/** Apollo Server-instans for GraphQL API-tester (Vitest). */ import type { ApolloServer } from '@apollo/server'; export type TestApolloServer = ApolloServer; diff --git a/backend/src/test/env.ts b/backend/src/test/env.ts index c0411c9..c0f0800 100644 --- a/backend/src/test/env.ts +++ b/backend/src/test/env.ts @@ -1,3 +1,4 @@ +/** Laster test-miljø og sikrer at DATABASE_URL peker på *_test-database. */ import { assertAllowedTestDatabaseUrl, isAllowedTestDatabaseName, diff --git a/backend/src/test/listingExpectations.ts b/backend/src/test/listingExpectations.ts index 541020d..02ae373 100644 --- a/backend/src/test/listingExpectations.ts +++ b/backend/src/test/listingExpectations.ts @@ -1,3 +1,4 @@ +/** Felles Vitest-hjelpere for å asserte listing-felter i API-tester. */ import { expect } from 'vitest'; const TOOL_CATEGORIES = [ diff --git a/backend/src/test/testDatabaseUrl.test.ts b/backend/src/test/testDatabaseUrl.test.ts index fbe26fe..7c1f7f5 100644 --- a/backend/src/test/testDatabaseUrl.test.ts +++ b/backend/src/test/testDatabaseUrl.test.ts @@ -1,3 +1,4 @@ +/** Enhetstester for testDatabaseUrl-hjelpere. */ import { describe, it, expect } from 'vitest'; import { diff --git a/backend/src/validation/createListingInput.ts b/backend/src/validation/createListingInput.ts index 2ff408c..8c743b9 100644 --- a/backend/src/validation/createListingInput.ts +++ b/backend/src/validation/createListingInput.ts @@ -1,3 +1,4 @@ +/** Validerer createListing-input (speiler frontend listingForm-grenser). */ import { GraphQLError } from 'graphql'; import type { ToolCategory } from '../types/listing.js'; diff --git a/backend/src/validation/listingFilterArgs.test.ts b/backend/src/validation/listingFilterArgs.test.ts index 62f773e..fc447ab 100644 --- a/backend/src/validation/listingFilterArgs.test.ts +++ b/backend/src/validation/listingFilterArgs.test.ts @@ -1,3 +1,4 @@ +/** Enhetstester for listingFilterArgs-validering. */ import { GraphQLError } from 'graphql'; import { describe, expect, it } from 'vitest'; diff --git a/backend/src/validation/listingFilterArgs.ts b/backend/src/validation/listingFilterArgs.ts index 721505c..408d673 100644 --- a/backend/src/validation/listingFilterArgs.ts +++ b/backend/src/validation/listingFilterArgs.ts @@ -1,3 +1,4 @@ +/** Parser og validerer filter- og sorteringsargumenter for listings. */ import { GraphQLError } from 'graphql'; import type { ToolCategory, ToolCondition } from '../types/listing.js'; diff --git a/backend/src/validation/paginationArgs.test.ts b/backend/src/validation/paginationArgs.test.ts index 6d00dfb..7f3f9a0 100644 --- a/backend/src/validation/paginationArgs.test.ts +++ b/backend/src/validation/paginationArgs.test.ts @@ -1,3 +1,4 @@ +/** Enhetstester for paginationArgs-validering. */ import { GraphQLError } from 'graphql'; import { describe, expect, it } from 'vitest'; diff --git a/backend/src/validation/paginationArgs.ts b/backend/src/validation/paginationArgs.ts index 0726e97..74622b8 100644 --- a/backend/src/validation/paginationArgs.ts +++ b/backend/src/validation/paginationArgs.ts @@ -1,3 +1,4 @@ +/** Validerer limit/offset for paginerte listings-spørringer. */ import { GraphQLError } from 'graphql'; /** Antall annonser per side når klienten ikke ber om noe annet. */ diff --git a/package-lock.json b/package-lock.json index 3ae5ecb..3b2139b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "@testing-library/jest-dom": "^7.0.1", "@testing-library/react": "^16.3.3", "@testing-library/user-event": "^14.6.7", + "@types/node": "^24.10.1", "@types/react": "^19.3.0", "@types/react-dom": "^19.3.0", "@vitejs/plugin-react": "^6.1.1", @@ -1300,6 +1301,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/node": { + "version": "24.19.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.2.tgz", + "integrity": "sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, "node_modules/@types/react": { "version": "19.3.0", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz", @@ -3713,6 +3724,13 @@ "node": ">=22.19.0" } }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, + "license": "MIT" + }, "node_modules/update-browserslist-db": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.3.tgz", diff --git a/package.json b/package.json index 770d38e..063c9dd 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "@testing-library/jest-dom": "^7.0.1", "@testing-library/react": "^16.3.3", "@testing-library/user-event": "^14.6.7", + "@types/node": "^24.10.1", "@types/react": "^19.3.0", "@types/react-dom": "^19.3.0", "@vitejs/plugin-react": "^6.1.1", diff --git a/src/data/mockListings.ts b/src/data/mockListings.ts index 3f9ae6d..5abf690 100644 --- a/src/data/mockListings.ts +++ b/src/data/mockListings.ts @@ -1,15 +1,14 @@ /** - * Oppdiktede eksempelannonser for prototypen. Ingen av annonsene er ekte - * tilbud, og ingen personopplysninger er brukt. Illustrasjonene er laget for - * prosjektet. + * Ti faste eksempelannonser for Vitest, `listingMocks` og designsiden + * (`design.html`). Produksjon og appen henter data fra GraphQL. Innholdet + * speiler seed i backend og dekker gratis/betalt utlån, varierende titler og + * annonser uten bilde. * - * Dataene er valgt for å dekke ulike tilfeller i visningene: gratis og betalt - * utlån, korte og lange titler, tomt tilbehør og annonser uten bilde. * Snittscore og antall vurderinger er de samme som eksempelvurderingene i * backend/src/seed/reviews.ts gir, og noen annonser har ingen vurderinger. * - * Datakilden erstattes senere av GraphQL-backenden. Komponenter bør derfor få - * annonser gjennom props i stedet for å importere denne filen direkte. + * Sider og komponenter skal ikke importere denne filen direkte — bruk props + * eller mockede GraphQL-svar. */ import type { Listing } from '../types/listing.ts'; diff --git a/src/design/DesignPreview.tsx b/src/design/DesignPreview.tsx index 06a294f..2a8f418 100644 --- a/src/design/DesignPreview.tsx +++ b/src/design/DesignPreview.tsx @@ -1,3 +1,4 @@ +/** Designreferanse: komponenter og mock-annonser for design.html. */ import Button from '../components/Button/Button.tsx'; import ListingGrid from '../components/ListingGrid/ListingGrid.tsx'; import PriceTag from '../components/PriceTag/PriceTag.tsx'; diff --git a/src/design/main.tsx b/src/design/main.tsx index d42065f..6c7f128 100644 --- a/src/design/main.tsx +++ b/src/design/main.tsx @@ -1,3 +1,4 @@ +/** Entry for design.html — viser komponenter og mock-annonser, ikke med i build. */ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import { MemoryRouter } from 'react-router'; diff --git a/src/pages/CatalogPage/CatalogPage.tsx b/src/pages/CatalogPage/CatalogPage.tsx index 45c1829..a5f926b 100644 --- a/src/pages/CatalogPage/CatalogPage.tsx +++ b/src/pages/CatalogPage/CatalogPage.tsx @@ -1,3 +1,4 @@ +/** Katalog med server-side søk, filtre, sortering og paginering via GraphQL. */ import { useQuery } from '@apollo/client/react'; import { useCallback, useEffect, useRef } from 'react'; import { Link, useSearchParams } from 'react-router'; diff --git a/src/pages/ListingDetailPage/ListingDetailPage.tsx b/src/pages/ListingDetailPage/ListingDetailPage.tsx index 30f7083..c41d412 100644 --- a/src/pages/ListingDetailPage/ListingDetailPage.tsx +++ b/src/pages/ListingDetailPage/ListingDetailPage.tsx @@ -1,3 +1,4 @@ +/** Detaljvisning for én annonse og leieforespørsel (demo). */ import { useQuery } from '@apollo/client/react'; import { Link, useLocation, useParams } from 'react-router'; import ListingImage from '../../components/ListingImage/ListingImage.tsx'; diff --git a/src/pages/NotFoundPage/NotFoundPage.tsx b/src/pages/NotFoundPage/NotFoundPage.tsx index 487ce95..256b2b2 100644 --- a/src/pages/NotFoundPage/NotFoundPage.tsx +++ b/src/pages/NotFoundPage/NotFoundPage.tsx @@ -1,3 +1,4 @@ +/** Side for ukjente ruter, med lenke tilbake til katalogen. */ import { Link } from 'react-router'; import { usePageTitle } from '../../hooks/usePageTitle.ts'; diff --git a/src/pages/RentOutPage/RentOutPage.tsx b/src/pages/RentOutPage/RentOutPage.tsx index 0f6a87c..8f5df02 100644 --- a/src/pages/RentOutPage/RentOutPage.tsx +++ b/src/pages/RentOutPage/RentOutPage.tsx @@ -1,7 +1,7 @@ +/** Skjema for å opprette nye annonser via GraphQL createListing. */ import ListingForm from '../../components/ListingForm/ListingForm.tsx'; import { usePageTitle } from '../../hooks/usePageTitle.ts'; -/** Siden der brukere legger ut egne verktøy for utleie eller gratis utlån. */ function RentOutPage() { usePageTitle('Lei ut verktøy'); diff --git a/src/types/listing.ts b/src/types/listing.ts index b2d74bd..79db748 100644 --- a/src/types/listing.ts +++ b/src/types/listing.ts @@ -1,8 +1,8 @@ /** * Felles datatype for en verktøyannonse. * - * Kategori og tilstand er faste engelske nøkler slik at de senere kan bli - * GraphQL-enums. Norske visningsnavn ligger i utils/listingFormat.ts. + * Kategori og tilstand er faste engelske nøkler, i tråd med GraphQL-enums. + * Norske visningsnavn ligger i utils/listingFormat.ts. */ export type ToolCategory = diff --git a/tsconfig.node.json b/tsconfig.node.json index 351775c..39e7f43 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -3,6 +3,7 @@ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "ES2023", "lib": ["ES2023"], + "types": ["node"], "module": "ESNext", "skipLibCheck": true,