LOCAL_DEV_SETUP — reporting-service
Sibling: DEPLOYMENT_TOPOLOGY · TESTING_STRATEGY · API_CONTRACTS
1. Prerequisites
- Node.js 20.x (use
volta install node@20). - pnpm 9+.
- Docker 24+ with Compose v2.
- Google Cloud SDK (
gcloud) authenticated to the dev project (read-only roles only). - Make (optional but recommended).
- 8 GB free RAM (Chromium needs headroom).
2. Clone & install
git clone https://github.com/ghasi-tech/ghasi-melmastoon.git
cd ghasi-melmastoon/services/reporting-service
pnpm install
cp .env.example .env.local
.env.local contains only emulator-targeted values (no real GCP secrets). It is git-ignored.
3. Local stack
docker-compose.dev.yml (in this folder) starts:
| Service | Port | Image |
|---|---|---|
| Postgres 16 | 5432 | postgres:16-alpine |
| Pub/Sub emulator | 8085 | gcr.io/google.com/cloudsdktool/cloud-sdk:emulators |
GCS emulator (fake-gcs-server) | 4443 | fsouza/fake-gcs-server |
| Redis 7 | 6379 | redis:7-alpine |
| OTel collector | 4317, 4318 | otel/opentelemetry-collector-contrib |
SigNoz (optional --profile=obs) | 3301 | signoz/signoz |
pnpm dev:up # docker compose up -d
pnpm db:migrate # apply migrations to local Postgres
pnpm db:seed:dev # seed templates + 2 demo tenants (tnt_dev_a, tnt_dev_b)
pnpm dev # nest start --watch (api + worker via concurrently)
A clean re-start: pnpm dev:nuke && pnpm dev:up && pnpm db:migrate && pnpm db:seed:dev.
4. Stubbed dependencies
For local dev we stub upstream services rather than pull them in:
analytics-service→MockAnalyticsClientreturns canned rows fromtest/fixtures/analytics-rows/.notification-service→LoggingNotificationClientwrites deliveries to stdout.ai-orchestrator-service→EchoAIClientreturns deterministic placeholder callouts.- Regulatory adapters →
FakeRegulatoryAdapterreturns success after 500 ms (configurable per jurisdiction via.env.local).
To run against real upstream services in dev (rare), set USE_REAL_UPSTREAMS=true and provide service URLs/SA in .env.local.
5. Useful scripts
pnpm test # vitest unit + integration with emulators
pnpm test:domain # domain layer only (fast)
pnpm test:integration # integration suite with Testcontainers
pnpm test:renderer # PDF/XLSX/CSV golden-file suite
pnpm test:contract # event + REST contracts
pnpm lint && pnpm typecheck
pnpm db:make-migration <name> # scaffolds a new SQL migration
pnpm db:reset # drops & recreates local DB
pnpm openapi:generate # writes bin/openapi.yaml
pnpm cli -- run-now --tenant=tnt_dev_a --report=rep_dev_arrivals --formats=pdf,csv
6. Triggering scheduled runs locally
Cloud Scheduler is replaced with a local cron via cron package; pnpm dev:scheduler starts a tiny ticker that hits /internal/scheduler/fire for any active local schedule. You can also fire one manually:
curl -X POST http://localhost:8080/internal/scheduler/fire \
-H 'X-Tenant-Id: tnt_dev_a' \
-H 'X-Schedule-Id: sch_dev_arrivals' \
-H 'Authorization: Bearer dev-only'
Auth in dev mode bypasses real OIDC verification when NODE_ENV=development. Never ship that path: a hardcoded test in CI fails if the bypass branch is reachable in production builds.
7. Inspecting artifacts locally
fake-gcs-server exposes objects under http://localhost:4443/storage/v1/b/<bucket>/o/<object>. The pnpm cli artifacts list helper paginates artifacts for a tenant:
pnpm cli -- artifacts list --tenant=tnt_dev_a --limit=20
pnpm cli -- artifacts open --id=art_… # opens in default app
8. Debugging tips
- VS Code launch config
.vscode/launch.jsonincludes "API: attach", "Worker: attach", "Vitest: current file". - Set
LOG_LEVEL=debugto dump filter resolution and renderer step timings. - Set
RENDERER_HEADFUL=trueto launch Chromium with a visible window. - Pub/Sub emulator UI:
gcloud pubsub topics list --project=fake-project --emulator-host=localhost:8085.
9. Common pitfalls
- Chromium missing fonts → ensure
pnpm dev:install-fontsran (copies Noto + Vazirmatn into the local Chromium cache). - OOM during PDF tests → bump Docker memory to 8 GB.
- RLS test failing locally but passing in CI → you forgot
SET app.tenant_id. Use thewithTenant()helper intest/support/db.ts. - Pub/Sub message stuck → emulator does not auto-ack; ensure your handler returns successfully or call
messages ackmanually.
Cross-references: TESTING_STRATEGY, API_CONTRACTS.