Update to .md-files
This commit is contained in:
@@ -1,361 +1,161 @@
|
|||||||
# Microservice Importer
|
# Microservice Importer
|
||||||
|
|
||||||
Standalone-tjänst för import och konvertering av dokument till Markdown-format. Primärt fokus på PDF-filer — textbaserad extraction samt OCR för skannade dokument. Webb-skrapning finns som sekundär funktion för referens och framtida integration.
|
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.
|
||||||
|
|
||||||
Kan användas helt oberoende som fristående microservice.
|
|
||||||
|
|
||||||
## Viktigt!! Kod- och byggpraxis!
|
## 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
|
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
|
## Features
|
||||||
|
|
||||||
### Dokument-Import via PDF
|
### Quick-import (`POST /api/quick-import`)
|
||||||
- **Textbaserad extraction** — Snabb och precis för digitalt skapade PDFs
|
- **URL-skrapning** — ICA.se (JSON-LD) och generisk parser. Extraherar `imageUrl` från receptbild.
|
||||||
- **OCR-detektering** — Identifierar skannade bild-PDFs och rapporterar tydligt (OCR-stöd under utveckling)
|
- **OCR (bild)** — tesseract.js, svenska+engelska. Returnerar `source: 'image'`.
|
||||||
- **Automatisk konvertering:**
|
- **PDF-parsning** — pdf-parse för digitala PDFs, OCR-fallback för skannade.
|
||||||
- Titeln extraheras från filnamnet
|
- **Multipart** — Tar emot antingen JSON-body (`{ url }`) eller FormData (`file`).
|
||||||
- Texten struktureras till Markdown-stycken
|
|
||||||
- Metadata sparas (antal sidor, teckenantal, producent, skapelsedatum)
|
|
||||||
- **Filstorlek:** Max 50 MB per fil
|
|
||||||
- **Format:** Multipart/form-data uppladdning
|
|
||||||
|
|
||||||
### Webb-skrapning (sekundär funktion)
|
### Parse-Markdown (`POST /api/recipes/parse-markdown`)
|
||||||
- **Skrapa från ICA.se** — JSON-LD structured data + HTML-parsing
|
Tolkar Markdown-recept till strukturerat JSON utan databas.
|
||||||
- **Generisk parser** — Fallback för andra webbplatser
|
|
||||||
- **Automatisk extraction:** Namn, beskrivning, ingredienser, instruktioner
|
|
||||||
|
|
||||||
### Parse-Markdown endpoint
|
### Kvittoparsning (`POST /api/receipt-import/parse`)
|
||||||
Tolka Markdown-format utan databaskomplikationer. Användbar för API-integration utan lokal DB.
|
- 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
|
## Arkitektur
|
||||||
|
|
||||||
### Backend (NestJS 10.3, TypeScript 5.4.5)
|
### Backend (NestJS 10, TypeScript 5, Node.js 22-alpine)
|
||||||
**Port:** 3001
|
**Port:** 3001 (intern, ej exponerad till host)
|
||||||
|
|
||||||
```
|
```
|
||||||
src/
|
src/
|
||||||
├── app.module.ts # Root module
|
├── app.module.ts # Root module + HealthController (GET /api/health)
|
||||||
├── main.ts # Startpunkt
|
├── main.ts
|
||||||
├── common/
|
├── common/
|
||||||
│ ├── filters/
|
│ ├── filters/global-exception.filter.ts
|
||||||
│ │ └── global-exception.filter.ts # Centraliserad felhantering (svenska meddelanden)
|
│ └── utils/normalize-name.ts
|
||||||
│ └── utils/
|
├── web-scraping-service/ # Quick-import (URL + fil)
|
||||||
│ └── normalize-name.ts # Namnormalisering (åäö-handling)
|
│ ├── web-scraping.module.ts
|
||||||
├── document-import/ # PDF-import & konvertering (primär funktion)
|
│ ├── controllers/quick-import.controller.ts # POST /api/quick-import
|
||||||
│ ├── document-import.controller.ts # POST /api/document-import
|
│ ├── services/quick-import.service.ts # Scraping, OCR, PDF
|
||||||
│ ├── document-import.service.ts # Filvalidering, parser-routing
|
|
||||||
│ ├── document-import.module.ts
|
|
||||||
│ └── parsers/
|
│ └── parsers/
|
||||||
│ ├── document.parser.ts # Abstrakt bas-klass
|
│ ├── base.parser.ts # ParsedRecipe interface
|
||||||
│ └── pdf.parser.ts # PDF-extraction via pdf-parse
|
│ ├── ica.parser.ts # ICA.se JSON-LD + imageUrl
|
||||||
├── quick-import/ # Webb-skrapning (sekundär funktion)
|
│ └── generic.parser.ts
|
||||||
│ ├── quick-import.controller.ts # POST /api/quick-import
|
├── receipt-parsing/ # Kvittoparsning via Mistral AI
|
||||||
│ ├── quick-import.service.ts # Scraping-logik, parser-selection
|
│ ├── receipt-parsing.module.ts
|
||||||
│ ├── quick-import.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/
|
│ └── parsers/
|
||||||
│ ├── base.parser.ts # Abstrakt bas-klass
|
│ ├── document.parser.ts
|
||||||
│ ├── ica.parser.ts # ICA.se-specifik (JSON-LD prioritet)
|
│ └── pdf.parser.ts
|
||||||
│ └── generic.parser.ts # Fallback för alla webbplatser
|
└── recipes/ # Markdown-tolkning
|
||||||
└── recipes/ # Markdown-tolkning (utan DB)
|
|
||||||
├── recipes.controller.ts # POST /api/recipes/parse-markdown
|
|
||||||
├── recipes.service.ts
|
|
||||||
├── recipes.module.ts
|
├── recipes.module.ts
|
||||||
└── dto/
|
├── recipes.controller.ts # POST /api/recipes/parse-markdown
|
||||||
└── parse-markdown.dto.ts
|
├── recipes.service.ts
|
||||||
|
└── dto/parse-markdown.dto.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
**Viktigt:** Backend har _INGEN_ databaskonfiguration — stateless service.
|
**Viktigt:** Backend har _INGEN_ databaskonfiguration — stateless service.
|
||||||
|
|
||||||
### Frontend (Next.js 16.2, React 19.2, TypeScript 5.4.5)
|
|
||||||
**Port:** 3000
|
|
||||||
|
|
||||||
```
|
|
||||||
app/
|
|
||||||
├── layout.tsx # Root layout
|
|
||||||
├── page.tsx # Home page
|
|
||||||
├── Navigation.tsx # Minimal nav (Home + Import)
|
|
||||||
├── import/page.tsx # PRIMARY FEATURE — Drag-and-drop filuppladdning
|
|
||||||
├── api/
|
|
||||||
│ ├── document-import-proxy/route.ts # Proxy: multipart/form-data → backend
|
|
||||||
│ └── parse-markdown-proxy/route.ts # Proxy: Markdown-tolkning → backend
|
|
||||||
└── lib/
|
|
||||||
├── api.ts # Centraliserad API-access (fetchJson)
|
|
||||||
└── error-handler.ts # parseErrorResponse (svenska meddelanden)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Quick-Start
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
- Node.js 22.x
|
|
||||||
- Docker & Docker Compose (valfritt)
|
|
||||||
|
|
||||||
### Local Development
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Installera backend
|
|
||||||
cd backend
|
|
||||||
npm install
|
|
||||||
npm run start:dev
|
|
||||||
# Backend kör på http://localhost:3001
|
|
||||||
|
|
||||||
# 2. (I ny terminal) Installera frontend
|
|
||||||
cd frontend
|
|
||||||
npm install
|
|
||||||
npm run dev
|
|
||||||
# Frontend kör på http://localhost:3000
|
|
||||||
```
|
|
||||||
|
|
||||||
Öppna http://localhost:3000 → Gå till `/import` → Klistra in URL
|
|
||||||
|
|
||||||
### Docker
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Bygg och starta
|
|
||||||
docker compose up -d
|
|
||||||
|
|
||||||
# Frontend: http://localhost:3000
|
|
||||||
# Backend: http://localhost:3001
|
|
||||||
```
|
|
||||||
|
|
||||||
Stoppa:
|
|
||||||
```bash
|
|
||||||
docker compose down
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API-dokumentation
|
|
||||||
|
|
||||||
### POST /api/document-import
|
|
||||||
|
|
||||||
**Syfte:** Ladda upp en PDF och returnera Markdown-text
|
|
||||||
|
|
||||||
**Request:** `multipart/form-data` med fältet `file` (PDF, max 50 MB)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -X POST http://localhost:3001/api/document-import \
|
|
||||||
-F "file=@dokument.pdf"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response (Success 200):**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"markdown": "# Dokument\n\nInnehåll från PDFen...",
|
|
||||||
"title": "Dokument",
|
|
||||||
"documentType": "pdf",
|
|
||||||
"metadata": {
|
|
||||||
"pageCount": 5,
|
|
||||||
"characterCount": 12400,
|
|
||||||
"producer": "Adobe PDF Library",
|
|
||||||
"creationDate": "D:20260101120000"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response (Error 400):**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"statusCode": 400,
|
|
||||||
"message": "Kunde inte läsa dokumentet: PDFen verkar vara en skannad bild utan textlager.",
|
|
||||||
"timestamp": "2026-04-12T10:30:00.000Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Error-scenarier:**
|
|
||||||
- `400` — Ingen fil bifogad
|
|
||||||
- `400` — Fel filtyp (ej PDF)
|
|
||||||
- `400` — Filen överstiger 50 MB
|
|
||||||
- `400` — Lösenordsskyddad PDF
|
|
||||||
- `400` — Skannad bild-PDF utan textlager (OCR ej implementerat ännu)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### POST /api/quick-import
|
|
||||||
|
|
||||||
**Syfte:** Skrapa webbsida och returnera Markdown (sekundär funktion)
|
|
||||||
|
|
||||||
**Request:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"input": "https://ica.se/recept/kottfarssas-1234"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response (Success 200):**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"markdown": "# Köttfärssås\n\nEn klassisk...",
|
|
||||||
"source": "ica"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Error-scenarier:**
|
|
||||||
- `400` — Tomt input, inte en URL
|
|
||||||
- `400` — HTML-parsing misslyckades
|
|
||||||
- `503` — Network-fel
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### POST /api/recipes/parse-markdown
|
|
||||||
|
|
||||||
**Syfte:** Tolka Markdown-format utan databas
|
|
||||||
|
|
||||||
**Request:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"markdown": "# Titel\n\n## Ingredienser\n- 500 g mjöl\n\n## Tillvägagångssätt\nBlanda..."
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response (Success 200):**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "Titel",
|
|
||||||
"description": "",
|
|
||||||
"instructions": "Blanda...",
|
|
||||||
"ingredients": [
|
|
||||||
{ "rawName": "mjöl", "quantity": 500, "unit": "g", "note": null }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Parser-arkitektur
|
## Parser-arkitektur
|
||||||
|
|
||||||
### Dokument-parsers (`document-import/parsers/`)
|
### Dokument-parsers (`document-service/parsers/`)
|
||||||
|
|
||||||
Abstrakt bas `DocumentParser` som alla dokumenttyp-specifika parsers ärver från:
|
Abstrakt bas `DocumentParser` som alla dokumenttyp-specifika parsers ärver från.
|
||||||
|
|
||||||
```typescript
|
|
||||||
abstract class DocumentParser {
|
|
||||||
abstract parse(buffer: Buffer, filename: string): Promise<ParsedDocument>;
|
|
||||||
|
|
||||||
protected textToMarkdown(text: string, title: string): string {
|
|
||||||
// Slår ihop sammanhängande textrader, bevarar stycken
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### PDF Parser (`pdf.parser.ts`)
|
### PDF Parser (`pdf.parser.ts`)
|
||||||
|
|
||||||
Hanterar textbaserade PDFs via `pdf-parse`.
|
Hanterar textbaserade PDFs via `pdf-parse`. Skannade PDFs varnas.
|
||||||
|
|
||||||
**Strategi:**
|
### Webb-parsers (`web-scraping-service/parsers/`)
|
||||||
1. Extrahera text med `pdf-parse`
|
|
||||||
2. Kontrollera att text hittades (annars: skannad PDF-varning)
|
|
||||||
3. Konvertera text → Markdown via `textToMarkdown()`
|
|
||||||
4. Returnera titel (från filnamn), innehåll och metadata
|
|
||||||
|
|
||||||
**Felhantering:**
|
|
||||||
- Lösenordsskyddade PDFs → tydligt felmeddelande
|
|
||||||
- Skannade bild-PDFs → informativt felmeddelande om OCR
|
|
||||||
|
|
||||||
### Webb-parsers (`quick-import/parsers/`)
|
|
||||||
|
|
||||||
Abstrakt bas `RecipeParser` med `canHandle(url)` + `parse(html)`. Implementationer:
|
Abstrakt bas `RecipeParser` med `canHandle(url)` + `parse(html)`. Implementationer:
|
||||||
|
|
||||||
- **`ica.parser.ts`** — ICA.se, prioriterar JSON-LD structured data
|
- **`ica.parser.ts`** — ICA.se, prioriterar JSON-LD structured data, extraherar `imageUrl`
|
||||||
- **`generic.parser.ts`** — Fallback för alla webbplatser, försöker JSON-LD sedan HTML
|
- **`generic.parser.ts`** — Fallback för alla webbplatser
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
### Docker Compose (Recommended)
|
`importer-api` byggs och startas via `recipe-app/compose.yml` — **ej via sin egen compose-fil**.
|
||||||
|
|
||||||
```bash
|
**Serverstruktur:**
|
||||||
cd microservice-importer
|
```
|
||||||
docker compose up -d
|
/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
|
||||||
```
|
```
|
||||||
|
|
||||||
**Services:**
|
**Deploy:**
|
||||||
- `importer-api` — NestJS backend (port 3001)
|
|
||||||
- `importer-frontend` — Next.js frontend (port 3000)
|
|
||||||
|
|
||||||
**Stoppa:**
|
|
||||||
```bash
|
```bash
|
||||||
docker compose down
|
# 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:**
|
**Loggar:**
|
||||||
```bash
|
```bash
|
||||||
docker compose logs -f importer-api
|
docker logs importer-api -f
|
||||||
docker compose logs -f importer-frontend
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Manuell Docker build
|
**Hälsokontroll:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Backend
|
docker exec importer-api wget -qO- http://localhost:3001/api/health
|
||||||
docker build -f backend/Dockerfile -t importer-api:local .
|
# → {"status":"ok"}
|
||||||
docker run -p 3001:3001 importer-api:local
|
|
||||||
|
|
||||||
# Frontend (ny terminal)
|
|
||||||
docker build -f frontend/Dockerfile -t importer-frontend:local .
|
|
||||||
docker run -p 3000:3000 importer-frontend:local
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Environment variables
|
**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`.
|
||||||
|
|
||||||
Konfigureras i `docker compose` eller `.env`:
|
|
||||||
|
|
||||||
**Backend:**
|
|
||||||
```
|
|
||||||
PORT=3001
|
|
||||||
NODE_ENV=production
|
|
||||||
```
|
|
||||||
|
|
||||||
**Frontend:**
|
|
||||||
```
|
|
||||||
NEXT_PUBLIC_API_URL_INTERNAL=http://importer-api:3001
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Integration med andra tjänster
|
|
||||||
|
|
||||||
Microservicen kan anropas som extern API från andra applikationer:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const IMPORTER_URL = process.env.MICROSERVICE_IMPORTER_URL || 'http://localhost:3001';
|
|
||||||
|
|
||||||
// PDF-konvertering
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('file', pdfFile);
|
|
||||||
|
|
||||||
const response = await fetch(`${IMPORTER_URL}/api/document-import`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { markdown, title, metadata } = await response.json();
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Tekniska detaljer
|
## Tekniska detaljer
|
||||||
|
|
||||||
### Backend Stack
|
### Backend Stack
|
||||||
- **NestJS** 10.3 — REST API & modular architecture
|
- **NestJS** 10 — REST API & modular architecture
|
||||||
- **TypeScript** 5.4.5 — Type safety
|
- **TypeScript** 5 — Type safety
|
||||||
- **Node.js** 22.x — Runtime
|
- **Node.js** 22-alpine — Runtime (Alpine Linux)
|
||||||
- **pdf-parse** 1.1.x — PDF text extraction
|
- **pdf-parse** — PDF text extraction
|
||||||
- **tesseract.js** 5.x — OCR (förberett, ej aktivt ännu)
|
- **tesseract.js** — OCR (bild och skannade PDFs, svenska + engelska)
|
||||||
|
- **@mistralai/mistralai** — AI-kvittoparsning
|
||||||
- **multer** — Multipart file upload handling
|
- **multer** — Multipart file upload handling
|
||||||
- **class-validator** — DTO validation (svenska felmeddelanden)
|
|
||||||
- **Ingen databas** — Stateless service
|
- **Ingen databas** — Stateless service
|
||||||
|
|
||||||
### Frontend Stack
|
### Systempaket (Alpine)
|
||||||
- **Next.js** 16.2 — React framework (App Router)
|
Installerade i Dockerfile runner-stage:
|
||||||
- **React** 19.2 — UI components
|
```
|
||||||
- **TypeScript** 5.4.5
|
tesseract-ocr
|
||||||
- **Inline CSS** — Minimal styling, inga framework-beroenden
|
tesseract-ocr-data-swe
|
||||||
|
tesseract-ocr-data-eng
|
||||||
|
```
|
||||||
|
|
||||||
### Error Handling
|
### Error Handling
|
||||||
- Centraliserad `GlobalExceptionFilter` (svenska meddelanden)
|
- Centraliserad `GlobalExceptionFilter` (svenska meddelanden)
|
||||||
@@ -367,13 +167,13 @@ const { markdown, title, metadata } = await response.json();
|
|||||||
## Framtida utbyggnader
|
## Framtida utbyggnader
|
||||||
|
|
||||||
- [x] PDF-import — textbaserad extraction
|
- [x] PDF-import — textbaserad extraction
|
||||||
- [ ] OCR för skannade bild-PDFs (Tesseract.js förberett)
|
- [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
|
- [ ] Word (.docx) import
|
||||||
- [ ] Batch-processing (flera filer samtidigt)
|
- [ ] Swagger/OpenAPI-dokumentation
|
||||||
- [ ] Strukturerad data-extraction (tabeller, listor)
|
- [ ] Rate limiting / Caching
|
||||||
- [ ] Stöd för fler webbplatser i webb-skraparen (mat.se, kokaihop.se, etc.)
|
|
||||||
- [ ] Caching av konverterade dokument
|
|
||||||
- [ ] Rate limiting
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,58 @@
|
|||||||
# Plan för vidareutveckling av Microservice Importer
|
# Plan för vidareutveckling av Microservice Importer
|
||||||
|
|
||||||
För att utveckla **Microservice Importer** vidare kan vi fokusera på att förbättra befintliga funktioner, lägga till nya funktioner, optimera arkitekturen och säkerställa skalbarhet. Nedan är en strukturerad plan för projektets fortsatta utveckling.
|
## Status (2026-04-30) — Integrerad med recipe-app
|
||||||
|
|
||||||
|
`microservice-importer` är nu driftsatt som intern tjänst (`importer-api`) i `recipe-app/compose.yml`. Alla tre importflöden är delegerade:
|
||||||
|
|
||||||
|
| Endpoint | Funktion | Status |
|
||||||
|
|---|---|---|
|
||||||
|
| `POST /api/quick-import` | URL-skrapning (ICA, generisk), PDF, OCR-bild | ✅ Driftsatt |
|
||||||
|
| `POST /api/recipes/parse-markdown` | Markdown → ingrediensstruktur (utan DB) | ✅ Driftsatt |
|
||||||
|
| `POST /api/receipt-import/parse` | Kvittobild/PDF → `ParsedReceiptItem[]` via Mistral AI | ✅ Driftsatt |
|
||||||
|
| `GET /api/health` | Hälsokontroll (används av Docker healthcheck) | ✅ Driftsatt |
|
||||||
|
|
||||||
|
**Serverstruktur:**
|
||||||
|
```
|
||||||
|
/opt/containers/
|
||||||
|
microservice-importer/ ← klonas och pullas separat
|
||||||
|
recipe-app/
|
||||||
|
compose.yml ← bygger importer-api från ../microservice-importer
|
||||||
|
deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Deploy:**
|
||||||
|
```bash
|
||||||
|
cd /opt/containers/microservice-importer && git pull
|
||||||
|
cd /opt/containers/recipe-app && git pull && ./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Återstående / Möjliga nästa steg
|
||||||
|
|
||||||
|
### Hög prioritet
|
||||||
|
- **Kvittoimport Fas 6b** — Granskningssteg och bulk-spara i Flutter-klienten (logiken är klar i backend)
|
||||||
|
|
||||||
|
### Medel prioritet
|
||||||
|
- **Fler webbplats-parsers** — Lägg till specifika parsers för t.ex. Arla, Tasteline, Köket.se
|
||||||
|
- **Swagger/OpenAPI** — Automatisk API-dokumentation via `@nestjs/swagger`
|
||||||
|
- **Testtäckning** — Enhetstester för parsers och receipt-parsing-service
|
||||||
|
|
||||||
|
### Låg prioritet / Framtida
|
||||||
|
- **Caching** — Cacha skrapade sidor för att minska belastning på externa webbplatser
|
||||||
|
- **Puppeteer** — Hantera JavaScript-renderade sidor
|
||||||
|
- **Word-dokument** — Stöd för `.docx`-import
|
||||||
|
- **Centraliserad loggning** — Prometheus/Grafana eller liknande
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arkitektur-noteringar
|
||||||
|
|
||||||
|
- Tjänsten är **helt stateless** — ingen databas, ingen session
|
||||||
|
- Kommunicerar **aldrig direkt** med internet-klienter — exponeras bara på `recipe-internal`-nätverket
|
||||||
|
- `MISTRAL_API_KEY` injiceras via env (samma nyckel som recipe-api använder)
|
||||||
|
- Alpine Docker-image: systempaket `tesseract-ocr`, `tesseract-ocr-data-swe`, `tesseract-ocr-data-eng` installerade via `apk`
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user