Files
microservice-importer/README.md
T
Nils-Johan Gynther 1bb0eedd4f Update to .md-files
2026-05-01 00:27:30 +02:00

189 lines
6.1 KiB
Markdown

# Microservice Importer
Intern import-tjänst (`importer-api`) för [recipe-app](../recipe-app). Hanterar URL-skrapning, OCR, PDF-parsning och AI-kvittoparsning utan databas. Körs som Docker-tjänst på det interna `recipe-internal`-nätverket — exponeras ej externt.
## Viktigt!! Kod- och byggpraxis!
Säkerställ att inga absoluta Windows-sökvägar används i koden, för att stödja bygg och drift på Linux/Ubuntu
---
## Features
### Quick-import (`POST /api/quick-import`)
- **URL-skrapning** — ICA.se (JSON-LD) och generisk parser. Extraherar `imageUrl` från receptbild.
- **OCR (bild)** — tesseract.js, svenska+engelska. Returnerar `source: 'image'`.
- **PDF-parsning** — pdf-parse för digitala PDFs, OCR-fallback för skannade.
- **Multipart** — Tar emot antingen JSON-body (`{ url }`) eller FormData (`file`).
### Parse-Markdown (`POST /api/recipes/parse-markdown`)
Tolkar Markdown-recept till strukturerat JSON utan databas.
### Kvittoparsning (`POST /api/receipt-import/parse`)
- Bild (JPEG/PNG/WebP/HEIC/HEIF) eller PDF
- Mistral AI vision med retry-logik (3 försök vid 503/429)
- Returnerar `ParsedReceiptItem[]`
### Health (`GET /api/health`)
Används av Docker-healthcheck i `recipe-app/compose.yml`. Returnerar `{ status: "ok" }`.
---
## Miljövariabler
| Variabel | Beskrivning | Standardvärde |
|---|---|---|
| `MISTRAL_API_KEY` | API-nyckel för Mistral AI | (krävs för kvittoparsning) |
| `PORT` | HTTP-port | `3001` |
---
## Arkitektur
### Backend (NestJS 10, TypeScript 5, Node.js 22-alpine)
**Port:** 3001 (intern, ej exponerad till host)
```
src/
├── app.module.ts # Root module + HealthController (GET /api/health)
├── main.ts
├── common/
│ ├── filters/global-exception.filter.ts
│ └── utils/normalize-name.ts
├── web-scraping-service/ # Quick-import (URL + fil)
│ ├── web-scraping.module.ts
│ ├── controllers/quick-import.controller.ts # POST /api/quick-import
│ ├── services/quick-import.service.ts # Scraping, OCR, PDF
│ └── parsers/
│ ├── base.parser.ts # ParsedRecipe interface
│ ├── ica.parser.ts # ICA.se JSON-LD + imageUrl
│ └── generic.parser.ts
├── receipt-parsing/ # Kvittoparsning via Mistral AI
│ ├── receipt-parsing.module.ts
│ ├── receipt-parsing.controller.ts # POST /api/receipt-import/parse
│ └── receipt-parsing.service.ts
├── document-service/ # PDF-dokumentimport
│ ├── document-service.module.ts
│ ├── controllers/document-import.controller.ts
│ ├── services/document-import.service.ts
│ └── parsers/
│ ├── document.parser.ts
│ └── pdf.parser.ts
└── recipes/ # Markdown-tolkning
├── recipes.module.ts
├── recipes.controller.ts # POST /api/recipes/parse-markdown
├── recipes.service.ts
└── dto/parse-markdown.dto.ts
```
**Viktigt:** Backend har _INGEN_ databaskonfiguration — stateless service.
---
## Parser-arkitektur
### Dokument-parsers (`document-service/parsers/`)
Abstrakt bas `DocumentParser` som alla dokumenttyp-specifika parsers ärver från.
### PDF Parser (`pdf.parser.ts`)
Hanterar textbaserade PDFs via `pdf-parse`. Skannade PDFs varnas.
### Webb-parsers (`web-scraping-service/parsers/`)
Abstrakt bas `RecipeParser` med `canHandle(url)` + `parse(html)`. Implementationer:
- **`ica.parser.ts`** — ICA.se, prioriterar JSON-LD structured data, extraherar `imageUrl`
- **`generic.parser.ts`** — Fallback för alla webbplatser
---
## Deployment
`importer-api` byggs och startas via `recipe-app/compose.yml`**ej via sin egen compose-fil**.
**Serverstruktur:**
```
/opt/containers/
microservice-importer/ ← klonas separat, pullas vid deploy
recipe-app/
compose.yml ← definierar importer-api-tjänsten
deploy.sh ← kör docker compose build + up
```
**Deploy:**
```bash
# 1. Uppdatera importer (om ändringar gjorts)
cd /opt/containers/microservice-importer && git pull
# 2. Bygg och starta alla containers
cd /opt/containers/recipe-app && git pull && ./deploy.sh
```
**Loggar:**
```bash
docker logs importer-api -f
```
**Hälsokontroll:**
```bash
docker exec importer-api wget -qO- http://localhost:3001/api/health
# → {"status":"ok"}
```
**OBS:** Host-port 3001 används av `wetty` på servern. `importer-api` exponeras **aldrig** utanför Docker-nätverket — anropas via `http://importer-api:3001` från `recipe-api`.
---
## Tekniska detaljer
### Backend Stack
- **NestJS** 10 — REST API & modular architecture
- **TypeScript** 5 — Type safety
- **Node.js** 22-alpine — Runtime (Alpine Linux)
- **pdf-parse** — PDF text extraction
- **tesseract.js** — OCR (bild och skannade PDFs, svenska + engelska)
- **@mistralai/mistralai** — AI-kvittoparsning
- **multer** — Multipart file upload handling
- **Ingen databas** — Stateless service
### Systempaket (Alpine)
Installerade i Dockerfile runner-stage:
```
tesseract-ocr
tesseract-ocr-data-swe
tesseract-ocr-data-eng
```
### Error Handling
- Centraliserad `GlobalExceptionFilter` (svenska meddelanden)
- Konsistent JSON-responsformat: `{ statusCode, message, timestamp, path }`
- HTTP status codes: 200, 400, 503
---
## Framtida utbyggnader
- [x] PDF-import — textbaserad extraction
- [x] OCR för skannade bild-PDFs (tesseract.js + Alpine-paket)
- [x] Kvittoparsning via Mistral AI
- [x] ICA-receptbildsextraktion (`imageUrl` i `ParsedRecipe`)
- [ ] Fler webbplats-parsers (Arla, Tasteline, Köket.se)
- [ ] Word (.docx) import
- [ ] Swagger/OpenAPI-dokumentation
- [ ] Rate limiting / Caching
---
## Licens
MIT
---
## Support
- **Git Repo** — Gitea på `192.168.50.2:2222/nilsjohan/microservice-importer`