189 lines
6.1 KiB
Markdown
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`
|