|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +The PureScript Registry implements a package registry for PureScript. |
| 4 | + |
| 5 | +- @SPEC.md contains the registry specification. Use this to understand the core data types and operations of the registry. |
| 6 | +- @CONTRIBUTING.md describes the structure of the registry codebase, what the various packages in the monorepo represent, and how to build and test the registry code. |
| 7 | + |
| 8 | +## Development Environment |
| 9 | + |
| 10 | +We use Nix with direnv. Expect to be in a Nix shell automatically, but if you are not, you can enter one: |
| 11 | + |
| 12 | +```sh |
| 13 | +nix develop |
| 14 | +``` |
| 15 | + |
| 16 | +### Nix Quirks |
| 17 | + |
| 18 | +- If Nix tries to fetch from git during a build and fails, then most likely `spago.yaml` files have been changed but the lockfiles were not updated. Update them with `spago build`. |
| 19 | +- If a Nix build appears to be stale, then most likely files were modified but not tracked by Git. Nix flakes only consider Git-tracked files. Add modified files with `git add` and retry. |
| 20 | + |
| 21 | +### Build & Test Commands |
| 22 | + |
| 23 | +The registry is implemented in PureScript. Use spago to build it. |
| 24 | + |
| 25 | +```sh |
| 26 | +spago build # Build all PureScript code |
| 27 | +``` |
| 28 | + |
| 29 | +The registry contains unit tests, end-to-end tests, and nix flake checks. |
| 30 | + |
| 31 | +- Run unit tests when you complete a change with `spago test` or `spago test -p <package-name>`. |
| 32 | +- Run end-to-end tests when working on the registry server in `app`. |
| 33 | +- On Linux systems you can run all flake checks (the tests run in CI) using `nix flake check -L`. |
| 34 | + |
| 35 | +### End-to-End Tests |
| 36 | + |
| 37 | +The end-to-end (integration) tests are in `app-e2e`. They can be run via Nix on Linux: |
| 38 | + |
| 39 | +```sh |
| 40 | +nix build .#checks.x86_64-linux.integration |
| 41 | +``` |
| 42 | + |
| 43 | +Alternately, they can be run on macOS or for more iterative development of tests using two terminals: one to start the test env, and one to execute the tests. |
| 44 | + |
| 45 | +```sh |
| 46 | +# Terminal 1: Start test environment (wiremock mocks + registry server on port 9000) |
| 47 | +nix run .#test-env |
| 48 | + |
| 49 | +# Terminal 2: Run E2E tests once server is ready |
| 50 | +spago-test-e2e |
| 51 | +``` |
| 52 | + |
| 53 | +Options: `nix run .#test-env -- --tui` for interactive TUI, `-- --detached` for background mode to use a single terminal. |
| 54 | + |
| 55 | +State is stored in `/tmp/registry-test-env` and cleaned up on each `nix run .#test-env`. To examine state after a test run (for debugging), stop the test-env but don't restart it. This is useful, for example, to read the logs of the most recent run. For example: |
| 56 | + |
| 57 | +```sh |
| 58 | +# after a test run, see the logs (log name is today's date) |
| 59 | +cat /tmp/registry-test-env/scratch/logs/*.log |
| 60 | +``` |
| 61 | + |
| 62 | +#### Smoke Test (Linux only) |
| 63 | + |
| 64 | +The smoke test verifies that the server comes up properly and tests deployment. Only run this test if you are making changes which could break the deployment of the server. |
| 65 | + |
| 66 | +```sh |
| 67 | +nix build .#checks.x86_64-linux.smoke -L |
| 68 | +``` |
| 69 | + |
| 70 | +## Formatting |
| 71 | + |
| 72 | +```sh |
| 73 | +# Format PureScript |
| 74 | +purs-tidy format-in-place app app-e2e foreign lib scripts |
| 75 | +purs-tidy check app app-e2e foreign lib scripts |
| 76 | + |
| 77 | +# Format Nix files |
| 78 | +nixfmt *.nix nix/**/*.nix |
| 79 | +``` |
| 80 | + |
| 81 | +## Project Structure |
| 82 | + |
| 83 | +- `app/` — Registry server implementation. |
| 84 | +- `app-e2e/` — E2E tests for the server API. |
| 85 | +- `lib/` — **Public library** for consumers (Spago, Pursuit, etc.). Only types and functions useful to external tools belong here. Avoid implementation-specific code. |
| 86 | +- `foreign/` — FFI bindings to JavaScript libraries. |
| 87 | +- `scripts/` — Runnable modules for registry tasks (LegacyImporter, PackageTransferrer, PackageSetUpdater, etc.). Run via `nix run .#legacy-importer`, etc. |
| 88 | +- `test-utils/` — Shared test utilities. |
| 89 | +- `db/` — SQLite schemas and migrations (use `dbmate up` to initialize). |
| 90 | +- `types/` — Dhall type specifications. |
| 91 | +- `nix/` — Nix build and deployment configuration. |
| 92 | + |
| 93 | +## Scratch Directory & Caching |
| 94 | + |
| 95 | +The `scratch/` directory (gitignored) is used by scripts for: |
| 96 | +- `.cache/` — Cached API responses, downloaded packages, etc. |
| 97 | +- `logs/` — Log files |
| 98 | +- `registry/`, `registry-index/` — Local clones for testing, also modified and optionally committed to by scripts |
| 99 | + |
| 100 | +Caching is critical for the legacy importer due to the expense of downloading packages. The `Registry.App.Effect.Cache` module handles caching. |
| 101 | + |
| 102 | +## PureScript Conventions |
| 103 | + |
| 104 | +### Custom Prelude |
| 105 | + |
| 106 | +Always use `Registry.App.Prelude` in `app/` and `app-e2e/` directories: |
| 107 | + |
| 108 | +```purescript |
| 109 | +import Registry.App.Prelude |
| 110 | +``` |
| 111 | + |
| 112 | +### Effects via Run |
| 113 | + |
| 114 | +Use the `run` library for extensible effects. Do NOT perform HTTP calls, console logs, or other effects directly in `Aff`. Check for existing effects in `app/src/App/Effect/` or consider adding one. |
| 115 | + |
| 116 | +### Import Style |
| 117 | + |
| 118 | +Import types unqualified, values qualified. Use shortened module names: |
| 119 | + |
| 120 | +```purescript |
| 121 | +import Registry.App.Prelude |
| 122 | +
|
| 123 | +import Data.Array as Array |
| 124 | +import Data.String as String |
| 125 | +import Node.FS.Aff as FS.Aff |
| 126 | +import Parsing (Parser) |
| 127 | +import Parsing as Parsing |
| 128 | +import Parsing.Combinators as Parsing.Combinators |
| 129 | +import Registry.Operation (AuthenticatedData) |
| 130 | +import Registry.SSH as SSH |
| 131 | +``` |
| 132 | + |
| 133 | +### Syntax |
| 134 | + |
| 135 | +Never use `let/in` syntax unless in an `ado` block. Always `do/let`. |
| 136 | + |
| 137 | +```purs |
| 138 | +func = |
| 139 | + -- NEVER use let/in syntax |
| 140 | + let x = 1 |
| 141 | + in x + x |
| 142 | +
|
| 143 | +func = do |
| 144 | + -- ALWAYS use do/let syntax |
| 145 | + let x = 1 |
| 146 | + x + x |
| 147 | +``` |
0 commit comments