wielorzeczownik / pepito-client
Pepito API client: SSE events, state, cache and historical statistics. Plain PHP, with the Rust core as opt-in FFI.
Package info
github.com/wielorzeczownik/pepito-client
Type:composer-plugin
pkg:composer/wielorzeczownik/pepito-client
Requires
- php: >=8.2
- composer-plugin-api: ^2.0
- composer-runtime-api: ^2.0
- ext-curl: *
- ext-json: *
- ext-phar: *
- ext-zlib: *
- psr/clock: ^1.0
- psr/event-dispatcher: ^1.0
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.1 || ^2.0
- psr/log: ^1.1 || ^2.0 || ^3.0
- psr/simple-cache: ^1.0 || ^2.0 || ^3.0
Requires (Dev)
- laravel/pint: 1.30.4
- nyholm/psr7: 1.8.2
- phpunit/phpunit: 11.5.56
Suggests
- ext-ffi: The Rust core through Client::withFfi(), for raw speed on large archives
- psr/event-dispatcher-implementation: Events from watch(), through setEventDispatcher()
- psr/http-client-implementation: Your own HTTP client for refresh(), through setHttpClient()
- psr/simple-cache-implementation: Snapshot cache instead of files, through setCache()
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-24 19:21:22 UTC
README
Pepito API client for Rust (crate), JS/TS (npm) and PHP (Composer). The npm and Composer packages are plain TypeScript and plain PHP by default, with nothing native to install. The Rust core is there as an opt-in backend in both wasm under @wielorzeczownik/pepito-client/wasm, FFI through Client::withFfi().
Reaching for Rust as the shared core just to hand-roll FFI and wasm-bindgen for a cat-door tracker was probably overkill. Three thin implementations in their native languages turned out to be the better default, so that is what the JS and PHP packages ship now. The Rust core stayed, as a crate and as the opt-in backend.
Every implementation does SSE parsing, the Way/State/Update enums, the in/out state machine, dedup of repeats after a reconnect, an age-aware status cache, connection heartbeat checks, and statistics from the Clement87/Pepito-data archive.
The Rust core never touches the network. Transport belongs to the binding, which is why the same code runs in wasm (no sockets there) and in PHP. Each binding lives in its own crate so its dependencies never leak into the others: building for PHP does not compile wasm-bindgen, and the wasm build never touches reqwest.
crates/core/ no-IO core: state, cache, dedup, heartbeat, -> crates.io
archive + stats, feature "net" (your reqwest client)
crates/ffi/ C ABI, JSON in / JSON out -> PHP
crates/wasm/ wasm-bindgen, JS objects with no JSON round trip -> npm /wasm
js/src/ core.ts: the plain TS port, the default backend
pepito.ts: transport (fetch, reconnect, EventTarget), TS types
wasm.ts: the same API over crates/wasm, opt-in
php/src/ Tracker + History: the plain PHP port, the default backend
FfiTracker: the same API over crates/ffi, opt-in; PHP 8.2+, PSR-4
php/lib/ pepito.h generated from crates/ffi + the built library
php/tests/ php/examples/ not shipped in the Composer package
The events, status(), the statistics and the snapshot JSON are the shared contract. Snapshots move freely between backends, so a cache written by the plain port restores in the Rust one and back. Parity tests keep the ports honest: js/tests runs the TS port against the wasm build and php/tests/BackendParityTest.php runs the PHP port against FFI, on the same stream, snapshots and the full archive.
Usage
Each package has its own README with installation and an example:
- crates/core/README.md: Rust / crates.io
- js/README.md: JS / TS / Node / npm
- php/README.md: PHP / Composer
Building
Only the Rust core and the opt-in backends need building. The default JS and PHP packages do not.
make wasm # js/dist/ through wasm-bindgen make header # php/lib/pepito.h straight from crates/ffi (needs cbindgen) make dylib # php/lib/pepito.h + php/lib/libpepito.{dylib,so,dll}
Tools needed only for building the bindings:
cargo install cbindgen
cargo install wasm-bindgen-cli --version 0.2.128 # must match crates/wasm/Cargo.toml down to the patch
Disclaimer
This project is community-made and unofficial, and may break if the backend API changes.