# endpoint-validator
Interactive test harness for [`endpoint-libs`](https://crates.io/crates/endpoint-libs)
WebSocket RPC services.
It reads `services.json` — the machine-readable endpoint description written by
[`endpoint-gen`](https://crates.io/crates/endpoint-gen) — plus a `config.toml` of preset
parameter values, connects to a running server, and lets you exercise endpoints from a
terminal UI.
```sh
cargo install endpoint-validator
endpoint-validator \
--services-path path/to/docs/services.json \
--config-path path/to/config.toml
```
Both paths are prompted for interactively if omitted.
## What it needs
| `services.json` | Generated by `endpoint-gen` into your project's `docs/`. Holds every `frontend_facing` endpoint with its parameters, returns, errors and roles, plus the shared enums and structs. |
| `config.toml` | Yours, written by hand. Preset parameter values per endpoint so you are not retyping them every run. |
Generate `services.json` with:
```sh
cargo install endpoint-gen
endpoint-gen --config-dir config/ --output-dir .
```
`config.toml` is keyed by endpoint code:
```toml
[10020]
name = "Login"
params.username = "alice"
params.password = "hunter2"
params.remember = true
```
## Using it
The TUI shows endpoints on the left, parameters in the middle, responses on the right.
`Tab` moves between panes, arrow keys move within one, `Enter` activates. Connect with a
username and password first; the endpoint list populates from `services.json` once the
connection is up.
## Schema types come from `endpoint-libs`
This crate does not define its own `Type`, `Field`, `EnumVariant` or `EndpointSchema`. It
re-exports them from `endpoint_libs::model` — the same types `endpoint-gen` used to write
the file it is reading.
That is deliberate and load-bearing. It previously kept hand-copied duplicates, which
drifted until every current `services.json` failed to parse with
`missing field 'comment'`: upstream had renamed `EnumVariant.comment` to `description` and
the copy never followed. The vendored `Type` had rotted further, still listing `Date`,
`Int`, `BigInt`, `Numeric`, `Inet` and `DataTable` — none of which exist upstream — while
missing `UInt32`, `Int32`, `Int64`, `Float64`, `NanoId`, `IpAddr` and `StructTable`.
`tests/parses_generated_services.rs` parses a real generated file, so that class of rot
now fails the build rather than the tool. If a future `services.json` stops parsing, the
fix is an `endpoint-libs` bump here — not a patch to a local type.
## Values on the wire
Strings in `config.toml` are converted to the JSON the server expects, following
`endpoint_libs::model::Type::to_json_schema`:
- Integers, floats and booleans are parsed, not passed through as strings.
- An empty value for an `Optional` field becomes `null`.
- **Enums travel as their integer value, not their name.** Either spelling works in config
— `Owner` or `0` — and both send `0`. (The pre-1.0 code sent the name as a string, which
a server rejects.)
- `Struct` values are `field: value` pairs. Nesting inside `{}` or `[]` is respected, so a
nested struct or array is not split on its internal commas.
- `Object`, `StructRef`, `EnumRef` and `StructTable` values are parsed as raw JSON.
An unsupported type is a hard error naming it, rather than a silently mis-encoded request.
## License
MIT