# CLAUDE.md — graphql-product

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

## Project Overview

**graphql-product** is an Apollo GraphQL server (TypeScript, Node.js) that serves product catalog data for the Orchard Insights platform. It is the largest GraphQL subgraph by connector count, aggregating data from 25+ internal OWS microservices covering products, tracks, artists, pricing, delivery, territories, store availability, and more. 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)

# 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 running server)
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 (codegen v6)
```

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 5 (with @theorchard/graphql-server 5.0.0 wrapper) |
| Language | TypeScript 5.5, Node.js >=24.0.0 |
| GraphQL | Schema-first, Apollo Federation, Code Generator v6 |
| Data Access | 25+ OWS REST connectors via @theorchard/datasource-ows 3.0 |
| Search | OpenSearch 3.5 (content-search connector) |
| Caching | Redis via Keyv + KeyvAdapter |
| Validation | Zod 4.0 |
| Testing | Jest 29.5 + ts-jest |
| Linting | ESLint 9 (flat config) |
| Observability | Sentry 9.47, Datadog (dd-trace) |
| Feature Flags | Split.io |
| Secrets | AWS Secrets Manager (@aws-sdk/client-secrets-manager) |

### Directory Structure

```
src/
├── connectors/              # 25+ DataSource connectors
│   ├── ows-product/         # Product service
│   ├── ows-track/           # Track service
│   ├── ows-artist/          # Artist service
│   ├── ows-pricing/         # Pricing service
│   ├── ows-carveouts-python/# Carveouts service
│   ├── ows-delivery-history/# Delivery history
│   ├── ows-masters-registry/# Masters registry
│   ├── ows-notifications/   # Notifications
│   ├── ows-permissions/     # Permissions
│   ├── ows-store-availability/# Store availability
│   ├── ows-territories/     # Territories
│   ├── ows-timed-release/   # Timed release
│   ├── ows-project-manager/ # Project management
│   ├── ows-sales-goals/     # Sales goals
│   ├── content-search/      # OpenSearch integration
│   ├── graphql-router/      # Federation gateway
│   └── ... (12+ more)
├── resolvers/               # GraphQL resolvers
│   ├── enums/               # Enum value mappings
│   ├── utils/               # Resolver utilities
│   ├── __tests__/
│   └── generated/           # Some generated types here
├── schema/                  # Modular .graphql files
├── constants/               # URLs, cache TTL, feature flags
│   └── __tests__/
├── utils/                   # Shared utilities
│   └── __tests__/
├── generated/               # Auto-generated types (DO NOT EDIT)
├── config.ts                # Environment configuration
├── serverConfig.ts          # Apollo Server config factory
├── context.ts               # Per-request context creation
└── types.ts                 # Shared TypeScript types

tests/
└── integration/             # Integration tests
```

### Data Flow

```
GraphQL Query → Resolver → DataLoader (Zod-validated) → Connector → OWS REST API / OpenSearch
                    ↑                                                         ↓
              Redis cache                                              Snowflake (via OWS)
```

## Key Patterns

### Connector Architecture (25+)

Each connector in `src/connectors/` encapsulates a single OWS microservice:
- REST API calls via `@theorchard/datasource-ows`
- Zod schemas for response validation
- DataLoaders for batching and caching
- Type-safe formatters for response mapping

When adding a new OWS connector:
1. Create directory in `src/connectors/<ows-service-name>/`
2. Add DataSource class extending `@theorchard/datasource-ows`
3. Add Zod schemas for response validation
4. Create DataLoader factory with `cacheKeyFn`
5. Register in `src/context.ts`

### Field Resolution Optimization

Uses `graphql-parse-resolve-info` to inspect which fields are requested. This allows connectors to skip unnecessary API calls when only a subset of fields is needed.

### Custom Scalar Types

- `Long` — Large integers (via graphql-type-long)
- `JSON` — Arbitrary JSON (via graphql-type-json)
- `Date`, `DateTime` — ISO date strings (via graphql-iso-date)

### Context Factory

`src/context.ts` creates per-request context including all DataSource instances. `src/serverConfig.ts` is a factory for Apollo Server configuration.

### Zod Validation

All external API responses are validated with Zod schemas. Schemas use `.transform()` for snake_case → camelCase mapping.

### DataLoader Factory Pattern

Same convention 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 in `src/resolvers/types/`. Register new types in `codegen.yml` under `mappers:`.

## Environment Variables

| Variable | Purpose |
|----------|---------|
| `ENV` | `qa` / `prod` |
| `NODE_ENV` | `development` / `test` / `production` |
| `PORT` | Server port (default 8087) |
| `OWS_*_URL` | 25+ OWS service URL overrides |
| `CONTENT_OPENSEARCH_URL` | OpenSearch cluster endpoint |
| `CONTENT_OPENSEARCH_USERNAME` | OpenSearch auth |
| `CONTENT_OPENSEARCH_PASSWORD` | OpenSearch auth |
| `CACHE_USE_REDIS` | Enable Redis caching |
| `CACHE_REDIS_*` | Redis connection config |
| `SPLIT_API_KEY` | Split.io feature flag API key |
| `AUTH_ISSUERS` | Auth0 issuer URLs (comma-separated) |
| `FACEBOOK_CLIENT_ID` | Facebook API integration |

## Testing

- **Unit tests**: `src/**/__tests__/*` — mock OWS connectors and OpenSearch
- **Integration tests**: `tests/integration/` — hit running server
- **Test timeout**: 60 seconds (configured in jest.config.json)
- **Coverage target**: 80%+

## Docker

Multi-stage build. Base image: Node 22 (AWS ECR parent). Dev port: 8087. Extensive environment variables for 25+ OWS service URLs.
