# CLAUDE.md — graphql-knowledge

This file provides guidance for AI assistants working in the graphql-knowledge repository.

## Project Overview

**graphql-knowledge** is an Apollo GraphQL server (TypeScript, Node.js) that serves as the knowledge graph layer for the Orchard Insights platform. It manages entity relationships (artists, labels, sound recordings, products) stored in Neo4j, with supplementary data from Snowflake and event publishing via Kafka. Part of the Apollo Federation supergraph served via `graphql-router`.

## Essential Commands

```bash
# Development
yarn start                  # Dev server with hot-reload (ts-node + nodemon)

# Build
yarn build                  # Production build (tsc + copy schema + copy cypher files)

# Testing
yarn test                   # Full suite: format check + lint + unit tests
yarn test:unit              # Jest unit tests only
yarn test:unit:watch        # Watch mode
yarn test:integration       # Integration tests (requires Neo4j + env setup)
yarn test:types             # TypeScript type checking (no emit)

# Linting & Formatting
yarn lint                   # ESLint + GraphQL schema linting
yarn lint:fix               # Auto-fix lint issues
yarn format                 # Prettier formatting
yarn format:check           # Check formatting only

# Code Generation
yarn generate:types         # Generate TypeScript types from GraphQL schema
```

To run a single test file:
```bash
yarn test:unit -- --testPathPattern="path/to/test"
```

## Setup

Copy `.env.shadow` to `.env` before running locally: `cp .env.shadow .env`

## Architecture

### Tech Stack

| Layer | Technology |
|-------|-----------|
| Framework | Apollo Server (via @theorchard/graphql-server wrapper) |
| Language | TypeScript 5.9, Node.js >=22.19.0 |
| GraphQL | Schema-first, Apollo Federation |
| Primary DB | Neo4j (via @theorchard/connector-neo4j 2.0, neo4j-driver 6.0) |
| Secondary DB | Snowflake (snowflake-sdk 2.3) |
| Event Streaming | Kafka (kafkajs 1.16) |
| Caching | Redis via ioredis 5.7 |
| Validation | Zod 4.1 |
| Testing | Jest 30.1 + ts-jest |
| Linting | ESLint 9.37 (@theorchard/eslint-config-ts) |
| Formatting | Prettier 3.6 |
| Observability | Sentry 10.27, Datadog (dd-trace 5.80) |
| Feature Flags | Split.io |

### Directory Structure

```
src/
├── connectors/              # DataSource abstraction layer
│   ├── neo4j/               # Neo4j driver + Cypher query execution
│   ├── snowflake/           # Snowflake SDK connection
│   ├── kafka/               # Kafka event publishing
│   ├── chartmetric/         # Chartmetric REST API client
│   ├── spotify/             # Spotify API connector
│   ├── GraphQLRouter/       # Federation gateway connector
│   └── ows-notifications/   # Notification service connector
├── resolvers/               # GraphQL resolvers
│   ├── mutation/            # Mutation resolvers
│   ├── __tests__/
│   └── __fixtures__/        # Test fixtures (some services)
├── schema/                  # Modular .graphql files
├── cypher/                  # .cypher query files (copied to build)
├── utils/                   # Shared utilities
│   └── __tests__/
├── __mocks__/               # Jest mocks
├── config.ts                # Environment configuration
└── types.ts                 # Shared TypeScript types

lib/                         # Test helpers
tests/
├── integration/             # Integration tests (with .cypher fixtures)
└── __tests__/
```

### Data Flow

```
GraphQL Query → Resolver → DataLoader → Connector → Neo4j (Cypher)
                    │                              → Snowflake (SQL)
                    │                              → Kafka (publish events)
                    ↑
              Redis cache
```

## Key Patterns

### Cypher Query Files

Neo4j queries are written in `.cypher` files under `src/cypher/`. These are copied to the build output. When adding new queries:
1. Create `.cypher` file in appropriate subdirectory
2. Reference it from the Neo4j connector
3. The build script copies all `.cypher` files to `build/`

### Neo4j Bookmark Manager

Neo4j sessions use a bookmark manager for causal consistency. This ensures read-after-write consistency across cluster members.

### Neo4j Aura Support

The service supports both Neo4j Premium and Neo4j Aura (cloud). The active backend is controlled via feature flags:
- `NEO4J_URL` / `NEO4J_USER` / `NEO4J_PASSWORD` — Premium
- `NEO4J_AURA_URL` / `NEO4J_AURA_USERNAME` / `NEO4J_AURA_PASSWORD` — Aura

### Kafka Event Publishing

Domain events (entity creates, updates, deletes) are published to Kafka topics. This enables event sourcing and downstream processing.

### Zod Validation

All external API responses are validated with Zod schemas. Always add/update Zod schemas when changing connector fetches.

### DataLoader Factory Pattern

Same pattern as other graphql-* services:
- `create<Name>DataLoader(post)` factory
- `<Name>DataLoader` type alias
- `dataSchema` (Zod schema)
- `cacheKeyFn` (format: `TypeName:${key}`)

### Mapper Keys

Every GraphQL object type has a `*Key` interface. These define the parent value that resolvers receive. Register new types in the codegen config.

## Environment Variables

| Variable | Purpose |
|----------|---------|
| `ENV` | `qa` / `prod` |
| `NODE_ENV` | `development` / `test` / `production` |
| `PORT` | Server port (default 8086) |
| `NEO4J_URL` | Neo4j Premium bolt URL |
| `NEO4J_USER` | Neo4j username |
| `NEO4J_PASSWORD` | Neo4j password |
| `NEO4J_AURA_URL` | Neo4j Aura bolt URL |
| `NEO4J_AURA_USERNAME` | Neo4j Aura username |
| `NEO4J_AURA_PASSWORD` | Neo4j Aura password |
| `SNOWFLAKE_*` | Snowflake connection params |
| `KAFKA_*` | Kafka broker configuration |
| `CACHE_FOR_APPLICATIONS` | Enable cache-by-client-name |
| `APOLLO_CLIENT_NAME` | Client identification header |
| `SPLIT_API_KEY` | Split.io feature flag API key |

## Testing

- **Unit tests**: `src/**/__tests__/*` — mock Neo4j, Snowflake, Kafka
- **Integration tests**: `tests/integration/` — require running Neo4j instance, uses `.cypher` fixtures for setup
- **Jest config**: `jest.local.config.js` for development, standard config for CI
- **Coverage target**: 80%+
- **Integration setup**: Pre-test scripts load Cypher fixtures into Neo4j

## Docker

Multi-stage build with `.cypher` file copying.

Base image: Node 22 (AWS ECR parent). Dev port: 8086.
