|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +Sailor is a typesafe GraphQL client for PHP. It generates PHP classes from GraphQL schema and `.graphql` operation files, enabling fully typed GraphQL API interactions. |
| 8 | + |
| 9 | +## Commands |
| 10 | + |
| 11 | +```bash |
| 12 | +make it # Run fix, stan, approve, test, validate-examples (the full suite) |
| 13 | +make fix # Auto-fix code style (php-cs-fixer) |
| 14 | +make stan # Static analysis (PHPStan, level max + bleedingEdge) |
| 15 | +make test # Run all tests (PHPUnit) |
| 16 | +make approve # Generate code for examples and approve as expected output |
| 17 | +make validate-examples # Run integration tests on all examples |
| 18 | +make coverage # Run tests with coverage |
| 19 | +``` |
| 20 | + |
| 21 | +**Running a single test:** |
| 22 | +```bash |
| 23 | +vendor/bin/phpunit tests/Unit/ResponseTest.php |
| 24 | +vendor/bin/phpunit --filter testMethodName |
| 25 | +``` |
| 26 | + |
| 27 | +**Test suites:** `Unit`, `Integration` (run with `--testsuite`) |
| 28 | + |
| 29 | +## Architecture |
| 30 | + |
| 31 | +**Code generation flow:** `Console/CodegenCommand` → `Codegen/Generator` → reads schema + `.graphql` files → validates → `OperationBuilder`/`ObjectLikeBuilder` generate classes → `Writer` outputs PHP files. |
| 32 | + |
| 33 | +**Runtime flow:** `MyOperation::execute($args)` → `Operation::executeOperation()` → `Client` sends HTTP request → `Response` parsed into typed `Result` object. |
| 34 | + |
| 35 | +**Key base classes in `src/`:** |
| 36 | +- `EndpointConfig` — abstract configuration per GraphQL endpoint |
| 37 | +- `Operation` — base for all generated operation classes |
| 38 | +- `ObjectLike` — base for generated types/inputs, uses `__get`/`__set` with property validation |
| 39 | +- `Result` — typed operation result wrapper |
| 40 | +- `Client` — interface for HTTP clients (implementations: `Guzzle`, `Psr18`, `Log`) |
| 41 | + |
| 42 | +## Examples as Golden-File Tests |
| 43 | + |
| 44 | +The `examples/` directory (e.g., `simple/`, `polymorphic/`, `custom-types/`) serves triple duty: test fixtures, working documentation, and integration tests. Each example is a self-contained project with: |
| 45 | + |
| 46 | +- `sailor.php` — endpoint configuration |
| 47 | +- `schema.graphql` — GraphQL schema |
| 48 | +- `src/` — `.graphql` operation files (input) |
| 49 | +- `expected/` — approved generated PHP code (committed to git, the golden files) |
| 50 | +- `generated/` — freshly generated output (gitignored, ephemeral) |
| 51 | +- `test.php` — integration test using the generated code |
| 52 | + |
| 53 | +**CodegenTest** (`tests/Integration/CodegenTest.php`) is the critical test: it regenerates code for each example into `generated/`, then asserts every file matches `expected/` exactly. Any change to codegen logic causes this test to fail, making regressions immediately visible. |
| 54 | + |
| 55 | +**Workflow after changing codegen:** |
| 56 | +1. `make test` — CodegenTest fails, showing diffs against expected output |
| 57 | +2. Inspect diffs to verify correctness |
| 58 | +3. `make approve` — regenerates all examples and copies `generated/` → `expected/`, blessing the new output |
| 59 | +4. Commit both code changes and updated `expected/` files |
| 60 | + |
| 61 | +**`make validate-examples`** complements CodegenTest by running each example end-to-end as a real project: `composer install` → `vendor/bin/sailor` → `php test.php`, verifying generated code actually works at runtime. |
| 62 | + |
| 63 | +## Code Conventions |
| 64 | + |
| 65 | +- Every file: `<?php declare(strict_types=1);` |
| 66 | +- Use `protected` over `private` — allows extension for unforeseen use cases |
| 67 | +- Full type hints on all parameters and return types |
| 68 | +- PHPStan level max with bleedingEdge strict rules |
| 69 | +- Namespace root: `Spawnia\Sailor` |
| 70 | +- Test assertions use `self::assertSame()` (static calls) |
| 71 | +- Base `TestCase` uses Mockery integration + Sailor mock traits |
0 commit comments