Skip to main content

Patient Chart Service — Local Dev Setup

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template

1. Prerequisites

ToolVersionPurpose
Node.js22 LTSRuntime
pnpm9.xPackage manager
Docker Desktop4.xCompose stack
kubectl1.29+Optional — K8s access
nats-clilatestNATS stream inspection

2. Repository layout

Patient-chart-service lives in the application monorepo at services/patient-chart-service/. Documentation lives at d:/GhasiTech/ghasi-e-documentation/Ghasi-eHealth/services/patient-chart-service/.

3. docker-compose.yml (patient-chart dev stack)

version: "3.9"
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: patient_chart_dev
POSTGRES_USER: patient_chart_app
POSTGRES_PASSWORD: dev_password
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./docker/init.sql:/docker-entrypoint-initdb.d/init.sql

nats:
image: nats:2.10-alpine
command: ["--jetstream", "--store_dir=/data"]
ports:
- "4222:4222"
- "8222:8222" # monitoring
volumes:
- nats_data:/data

terminology-service-mock:
image: mockserver/mockserver:latest
ports:
- "3020:1080"
environment:
MOCKSERVER_INITIALIZATION_JSON_PATH: /config/terminology.json
volumes:
- ./docker/mocks/terminology.json:/config/terminology.json

registration-service-mock:
image: mockserver/mockserver:latest
ports:
- "3000:1080"
volumes:
- ./docker/mocks/registration.json:/config/registration.json

ai-gateway-mock:
image: mockserver/mockserver:latest
ports:
- "3050:1080"
volumes:
- ./docker/mocks/ai-gateway.json:/config/ai-gateway.json

volumes:
postgres_data:
nats_data:

4. Environment variables (.env.example)

# App
NODE_ENV=development
PORT=3010
LOG_LEVEL=debug

# Database
DATABASE_URL=postgresql://patient_chart_app:dev_password@localhost:5432/patient_chart_dev
DATABASE_SCHEMA=patient_chart

# NATS
NATS_URL=nats://localhost:4222
NATS_STREAM_PATIENT_CHART=PATIENT_CHART

# Downstream services (mock ports for local)
TERMINOLOGY_SERVICE_URL=http://localhost:3020
REGISTRATION_SERVICE_URL=http://localhost:3000
AI_GATEWAY_URL=http://localhost:3050
PROVIDER_DIR_SERVICE_URL=http://localhost:3030
FACILITY_SERVICE_URL=http://localhost:3040
DOCUMENT_SERVICE_URL=http://localhost:3060
MEDICATION_SERVICE_URL=http://localhost:3070
LAB_SERVICE_URL=http://localhost:3080
RADIOLOGY_SERVICE_URL=http://localhost:3090
IMMUNIZATIONS_SERVICE_URL=http://localhost:3091
CARE_PLAN_SERVICE_URL=http://localhost:3092

# Keycloak (local dev — bypass with mock JWT)
KEYCLOAK_REALM_URL=http://localhost:8080/realms/dev
JWT_PUBLIC_KEY_PATH=./docker/dev-jwt-public.pem

# Telemetry
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_SERVICE_NAME=patient-chart-service

5. Start the dev stack

# 1. Clone monorepo
git clone <repo>
cd services/patient-chart-service

# 2. Install dependencies
pnpm install

# 3. Start dependencies
docker compose up -d postgres nats terminology-service-mock registration-service-mock ai-gateway-mock

# 4. Run DB migrations
pnpm db:migrate

# 5. Seed dev data
pnpm db:seed

# 6. Start service in watch mode
pnpm dev

6. Database migration commands

CommandDescription
pnpm db:migrateApply pending Drizzle migrations
pnpm db:migrate:dryShow pending SQL without executing
pnpm db:seedLoad dev seed data (synthetic patients, problems, allergies, vitals, notes)
pnpm db:resetDrop schema + re-run migrations + seed (dev only)
pnpm db:studioOpen Drizzle Studio UI at localhost:4983

7. Common development commands

CommandDescription
pnpm devNestJS watch mode
pnpm buildTypeScript compile
pnpm testAll tests (unit + integration)
pnpm test:unitUnit tests only
pnpm test:integrationIntegration tests (requires compose stack running)
pnpm test:e2eE2E tests against running service
pnpm test:coverageCoverage report
pnpm lintESLint
pnpm typechecktsc --noEmit

8. Seed data overview

The seed script creates the following synthetic (non-PHI) data:

EntityCountNotes
Tenants2ten_dev_a and ten_dev_b for tenant-isolation testing
Patients10 per tenantSynthetic names; pat_dev_* prefix
Problems3–5 per patientMix of active, resolved, inactive
Allergies1–3 per patientIncludes 1 NKA patient
VitalsSets5–10 per patientLast 30 days; normal and abnormal values
ClinicalNotes2–4 per patientMix of draft, signed, amended

9. NATS stream inspection

# View messages in PATIENT_CHART stream
nats stream view PATIENT_CHART --count 10

# Publish a test event
nats pub patient_chart.problem.added.v1 '{"decisionId":"test","tenantId":"ten_dev_a"}'

# Check consumer lag
nats consumer info PATIENT_CHART audit-service-consumer

10. Troubleshooting

IssueResolution
DATABASE_URL connection refusedEnsure docker compose up -d postgres is running
Migration error: relation already existsRun pnpm db:reset (dev only)
JWT validation failsCheck JWT_PUBLIC_KEY_PATH points to dev public key
Terminology service 503Verify mock container is running on port 3020
Outbox events not publishingCheck NATS connection; inspect outbox table for unpublished rows