shared-libs/crates/jsonpath/ARCHITECTURE.md
Rama master · réplica de lectura del repositorio original.
# jsonpath Architecture
A JsonPath engine: it compiles a JsonPath string into tokens, then walks an `imbl_value::Value`
tree to select, filter, transform, or delete matching nodes. This document covers how the crate is
laid out and how a query flows through it. For usage and the full API surface, see
[README.md](README.md).
## Place in the monorepo
- **Path:** `shared-libs/crates/jsonpath`
- **Package name:** `jsonpath_lib` (the Cargo package name differs from the directory name
`jsonpath`; always use `cargo … -p jsonpath_lib`). Library name is also `jsonpath_lib`.
- **Crate type:** `["cdylib", "rlib"]` — an rlib for Rust consumers plus a cdylib exporting the
deprecated C FFI.
- **Consumers:** `start-core` (`shared-libs/crates/start-core`) uses `jsonpath_lib::Compiled` in
`src/config/hook.rs` for configuration-hook processing.
- **First-party.** A direct path dependency (`jsonpath_lib = { path = "../jsonpath" }` in
start-core's `Cargo.toml`) — no `[patch]`, no crates.io pull. It originated as a fork of
[freestrings/jsonpath](https://github.com/freestrings/jsonpath) and has since fully diverged; it is
maintained as first-party code with no upstream sync.
- **Dependencies:** `imbl-value` (sibling crate; supplies the immutable `Value`/`Vector` types this
engine operates on), `serde` / `serde_json`, and `log`.
## How a query flows
A JsonPath string is processed in two stages — **parse** then **walk**:
1. **Parse.** `paths::PathParser::compile(path)` tokenizes the path (`paths::tokenizer`,
`paths::str_reader::StrRange`) and builds the token tree consumed during selection
(`paths::tokens`, `parser_node_visitor`, `parser_token_handler`). Compilation is fallible and
returns `TokenError` on a malformed path.
2. **Walk.** `selector::JsonSelector` (read-only) or `selector::JsonSelectorMut` (mutating) takes a
compiled `PathParser` and an `imbl_value::Value`, then evaluates the tokens against the value
tree: recursive descent, wildcards, array indexing/ranges/unions, and filter expressions
(`selector::terms`, `selector::value_walker`, `selector::cmp`). Read selectors yield
`Vector<&Value>`; mutating selectors return a rebuilt `Value` for `delete` / `replace_with`.
## Public API surface (`src/lib.rs`)
The crate root wraps the parse-then-walk pair behind convenience functions and one pre-compiled
type:
- **One-shot functions** (compile the path on each call): `select`, `select_as`, `select_as_str`,
`delete`, `replace_with`.
- **Reusable closures** (compile once, query many): `selector`, `selector_as` — return an
`FnMut(&str | ())` over a bound JSON value.
- **`PathCompiled<'a>`** — the preferred pre-compiled expression. `PathCompiled::compile(path)`
parses once; its `select` reuses the compiled form across many JSON inputs.
- **Selectors:** `JsonSelector` / `JsonSelectorMut`, re-exported from `selector`, for callers that
want direct control over the walk stage.
- **`JsonPathError`** — the error type (`Path`, `Serde`, … variants); marked deprecated upstream but
still the returned error.
### Deprecated surface
The crate also re-exports an older stack, kept for compatibility: `compile()` and the `Compiled`
struct (backed by `parser` + `select`), plus `Parser`, `Selector`, `SelectorMut`. `start-core`
currently depends on `Compiled`. New code should prefer `PathCompiled` and the `paths`/`selector`
modules; the `parser`, `select`, and `ffi` modules are deprecated.
## Supported path syntax
Root (`$`), recursive descent (`..`), wildcards (`*`), array indexing (`[n]`, negative indices),
ranges (`[n:m]`), unions (`[n,m,k]`), filters (`[?(@.field < 10)]`), and field access
(`$.store.book[*].author`). See the doc test at the top of `src/lib.rs` and `tests/` for worked
examples.
## Further reading
- [README.md](README.md) — usage and API examples.
- [AGENTS.md](AGENTS.md) — toolchain, build/test/format, conventions.
- Sibling: [`imbl-value`](../imbl-value) — the value types this engine queries.