Changes for version 0.001000 - 2026-07-15

  • Initial release.
  • app { } block-scoped collector returning an assembled PAGI app value (no global state), built on PAGI::App::Router, PAGI::Middleware, PAGI::Lifespan, and PAGI::App::File.
  • Routing verbs get/post/put/patch/del/any; group (prefix + shared middleware) and mount (nest any PAGI app); path placeholders (:name, {name}, {name:regex}, *splat) map to the handler signature.
  • Return-value coercion: PAGI::Response as-is; hashref/arrayref to JSON (convert_blessed, so nested TO_JSON objects serialize); scalar to text/plain; undef/return; a loud 500. Thrown respond-ables are sent.
  • enable (app-wide) and [\@middleware] (route/group) event-layer middleware; named middleware resolved like PAGI::Middleware::Builder.
  • startup/shutdown lifecycle with app-lifetime shared state ($c->state).
  • static file serving, custom not_found, websocket and sse (imperative), and streaming request/response bodies.
  • $c->params strong parameters via PAGI::StructuredParameters (PAGI::Nano::Context::HTTP).
  • Two run shapes: single-file app.pl and a lib/MyApp.pm modulino.
  • Requires PAGI::Tools 0.002002 (extension-aware default WebSocket declines; stricter Test::Client lifespan-startup) and PAGI::StructuredParameters.
  • Per-request service makers run at most once per service name per request even when they return undef; memoization is based on cache-key existence rather than value definedness.
  • ServiceRegistry: a service builder that returns a Future croaks loudly at lifespan startup, naming the service, rather than silently storing the unresolved Future as the "service" (which fails cryptically later at $c->service). Service builders are synchronous by design; use a per-request maker (a plain coderef) or factory(...) for deferred or per-call construction.
  • PAGI::Nano::resolve_service($app, $name): a test-facing seam to resolve an app-scoped service value after lifespan startup without issuing a request, via a private probe token on the assembled app coderef. Returns the raw app-scoped value (a per-request maker or factory marker comes back as-is, not per-request-resolved).
  • Custom not_found responses emit protocol-valid decline events: SSE uses sse.http.response.*, and WebSocket uses websocket.http.response.* when the server advertises that extension. WebSockets without it bypass the handler and close for a portable body-less 403. Translated byte bodies may be buffered or streamed; SSE and WebSocket file/fh bodies fail loudly.
  • Context uri_for percent-encodes decoded strings from UTF-8 bytes. Ordinary placeholders encode one segment and reject slash-containing values in favor of *splat routes; splats preserve separators while encoding each segment. Query keys and values remain sorted and use %20 for spaces.

Modules

A compact micro-framework front door over PAGI-Tools
Shared behavior for the contexts PAGI::Nano vends
The HTTP request context vended by PAGI::Nano
The SSE context vended by PAGI::Nano
The WebSocket context vended by PAGI::Nano
The per-app registry backing PAGI::Nano's service keyword