NAME

Punk::App - the per-application registry and boot compiler

DESCRIPTION

use Punk; creates one of these per application class. The DSL keywords and plugins record into it; to_app calls "compile", which resolves every target string, flattens guard chains, freezes the route tables and returns the PSGI coderef. Everything wrong croaks at boot; the returned closure is the only code on the request path.

THE REGISTRAR SURFACE

Plugins receive this object; each method mirrors a DSL keyword: route, under, api, docs, static, mount, websocket, sse, session, logging, views, database, model_class, hook, middleware, on_error, helper, plugin, config, secret. model_auto toggles auto-discovery of MyApp::Model::* (on unless models are named explicitly). caller_class and config_object give a plugin the app's controller namespace and its Punk::Config; new and the compile-time helpers (compile, model_instance, render_view) are called by the framework, not apps.

helper

$app->helper(rid => sub { my ($c, @args) = @_; ... });

Installed as a real method on the application's context subclass at compile time. Collisions with core context methods or another helper croak, naming both owners.

log

The application Punk::Logger (cached on the app), for logging outside a request - startup, background work: $app->log->info(...). Its lines have no method or path. See Punk::Logger and the logging keyword.

COMPILE

compile

Freezes the configuration and returns the PSGI app. Dispatch order: static table, PSGI/static-file mounts (longest prefix first), dynamic buckets, then 404/405. Matched requests construct the context, run before_dispatch hooks and the route's frozen guard chain (a reference return short-circuits), call the handler, and coerce the return value:

  • a PSGI triplet passes through untouched;

  • a Punk::Response is finalized;

  • a Future is chained on psgi.nonblocking servers (the server awaits it) and awaited inline on blocking ones;

  • anything else is JSON-encoded as 200 application/json, folding in any status/headers set through the context;

  • a die runs on_error, then answers 500 {"errors":[{"message":...}]}.

after_dispatch hooks see the finalized triplet (mutate it, or return a replacement); HEAD responses are stripped of their body.

AUTHOR

LNATION <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)