Type: Node.js CLI batch application
Purpose: Generate astronomical event calendars using NASA's JPL Horizons API
Outputs: iCalendar (.ics) and JSON files
cd applications/caelundas
cp .env.example .env # Configure dates, location, timezone, event types
nx run caelundas:developnx run caelundas:docker-build # Build for linux/amd64
nx run caelundas:helm-upgrade # Deploy as K8s Job
nx run caelundas:kubernetes-copy-files # Retrieve output after completionInput (ENV) → Ephemeris → Event Detection → Duration Synthesis → iCal Output
↓ ↓ ↓ ↓ ↓
Validation NASA API Exact moments Pair events .ics/.json
+ SQLite (minute precision) into periods
Key Components:
- Input Validation (input.schema.ts): Zod schema for environment variables
- Ephemeris Retrieval (ephemeris/): NASA JPL Horizons API with SQLite caching
- Event Detection (events/): Aspects, phases, eclipses, retrogrades
- Duration Synthesis: Pairs start/end moments into calendar events
- Output (output.utilities.ts): iCal and JSON formatters
- Aspects: Conjunctions (0°), oppositions (180°), squares (90°), trines (120°), sextiles (60°)
- Phases: New moon, full moon, first/last quarters
- Retrogrades: Apparent backward motion of planets
- Eclipses: Solar and lunar
- Ingresses: Planets entering zodiac signs
- Cycles: Solstices, equinoxes, moonrise/moonset, sunrise/sunset, twilights
See ephemeris-pipeline skill for:
- NASA JPL Horizons API details (endpoints, parameters, rate limits)
- Astronomical concepts (aspects, retrogrades, phases explained)
- Caching strategy (SQLite schema, temporal margins)
- Event detection algorithms
Required:
START_DATE,END_DATE: YYYY-MM-DD (inclusive range)LATITUDE,LONGITUDE: Decimal degreesTIMEZONE: IANA timezone (e.g., "America/New_York")
Optional:
EVENT_TYPES: Comma-separated list (defaults to all)OUTPUT_FORMAT:icalorjson(defaults toical)OUTPUT_PATH: File path (defaults to./output_{timestamp}.ics)
Full schema: src/input.schema.ts
nx run caelundas:test:unit # Fast (<100ms), mocked I/O
nx run caelundas:test:integration # Moderate (1-2s), real SQLite
nx run caelundas:test:end-to-end # Slow (30-60s), real NASA APISee Testing Strategy for patterns.
SQLite with three tables:
ephemeris: Cached NASA API responsesevents: Detected calendar eventsactive_aspects: Currently active aspect patterns
Inspect: sqlite3 caelundas.db
Caelundas runs as a Kubernetes Job (not Deployment):
- Single execution, terminates on completion
- Output stored in PersistentVolumeClaim
- No network exposure needed
See Deployment Models for Jobs vs. Deployments patterns.
# 1. Build and push image
nx run caelundas:docker-build
docker push ghcr.io/jimmypaolini/caelundas:latest
# 2. Deploy Job (auto-generated release name)
nx run caelundas:helm-upgrade
# 3. Monitor completion
kubectl wait --for=condition=complete job/<job-name> --timeout=600s
# 4. Retrieve output files
nx run caelundas:kubernetes-copy-files
# 5. Clean up
nx run caelundas:helm-uninstall
kubectl delete pvc caelundas-outputUses infrastructure/helm/kubernetes-job - reusable chart for batch jobs with PVC storage.
Values: infrastructure/helm/kubernetes-job/values/caelundas-production.yaml
See kubernetes-deployment skill for Helm chart details.
Stored as Kubernetes Secret (caelundas-env-secret):
kubectl apply -f applications/caelundas/kubernetes/secret.yamlnx run caelundas:docker-build # Builds for linux/amd64Platform targeting: Always use linux/amd64 for K8s deployment (Apple Silicon compatibility).
See docker-workflows skill for multi-stage builds and GHCR integration.
Single-stage build:
- Base: Node.js 20 Alpine
- Native deps: python3, make, g++ (for sqlite3 compilation)
- Workspace: Full monorepo copied (needed for path resolution)
- Entry:
pnpm start(runs TypeScript directly via tsx)
Execution times (1-year range, all event types):
- First run (empty cache): 8-12 minutes (NASA API calls)
- Subsequent runs (warm cache): 1-2 minutes (local computation)
Optimization strategies:
- Temporal margins: Fetch beyond date boundaries to catch edge events
- SQLite caching: ~95% hit rate after first run
- Batch API calls: Multiple days per request when possible
- Lazy evaluation: Minute-resolution only for detected event windows
See Common Gotchas for:
- Docker platform mismatch (exec format error)
- K8s Job not starting (image pull, PVC issues)
- PVC cleanup after job completion
- src/main.ts: Pipeline entry point
- src/input.schema.ts: Environment variable validation
- src/ephemeris/ephemeris.service.ts: NASA API client
- src/database.utilities.ts: SQLite operations
- src/output.utilities.ts: iCal and JSON formatters
- Dockerfile: Container build configuration