Developer-Dashboard
view release on metacpan or search on metacpan
lib/Developer/Dashboard.pm view on Meta::CPAN
stable saved-bookmark endpoint such as
C</ajax/name.json?type=text>. Skill pages use the same helper contract. Without
extra skill route metadata the generated saved endpoint is namespaced under the
longest matching skill route, for example
C</ajax/example-skill/name.json?type=text> or
C</ajax/example-skill/sub-skill/name.json?type=text>. The runtime config tree
and installed skills can both ship C<config/routes.json> to declare canonical
custom paths for normal saved app pages, skill-local app pages, Ajax handlers,
JavaScript assets, CSS assets, and other public assets. The schema is a JSON
object whose keys are the public custom paths and whose values are either one
smart local route string or an object with C<to> plus an optional C<type>, for
example
{
"/java" : "/app/learn.ai",
"/v1/status" : {
"to" : "/ajax/status",
"type" : "json"
},
"/hello/world" : "/app/hello/world",
"/main.css" : "/css/hello/world.css",
"/hey.js" : "/js/hey/how/are/you.js",
"/what/are/you" : "/others/hello/world/you.html"
}
When that file is present, skill pages emit the declared canonical
C<ajax> path such as C</v1/status> instead of the default C</ajax/...> url,
and runtime-level aliases such as C</java> can point at normal saved bookmark
ids such as C</app/learn.ai> without treating the dot as skill notation. The
same manifest also makes the declared custom C</app>, C</js>, C</css>, and
C</others> paths requestable. The smart longest-prefix routes remain the
parent resolvers:
C</app/example-skill/...>, C</ajax/example-skill/...>,
C</js/example-skill/...>, C</css/example-skill/...>, and
C</others/example-skill/...> are always checked first, and any declared custom
path is checked only after the normal smart route misses. Runtime-level custom
paths from the active C<config/routes.json> layer chain follow the same
fallback rule against the built-in C</app>, C</ajax>, C</js>, C</css>, and
C</others> route handlers. If neither the smart route nor the custom path
resolves, the request falls through to the normal C<404> response. Ajax custom
routes default to C<json> when no explicit C<type> is present, and the
optional C<type> value can also be C<html>,
C<text>, or an arbitrary raw mime type such as
C<application/vnd.example+json>. Those saved Ajax handlers run the stored file
as a real process, defaulting to Perl unless the file starts with a shebang,
and stream both C<stdout> and C<stderr> back to the browser as they happen.
That keeps bookmark Ajax workflows usable even while transient token URLs stay
disabled by default, and it means bookmark Ajax code can rely on normal
C<print>, C<warn>, C<die>, C<system>, and C<exec> process behaviour instead of
a buffered JSON wrapper.
The same layered runtime config chain and installed-skill config trees can now
ship C<config/api.json> files that authorize selected C</ajax/...> routes for
machine-to-machine callers without forcing a helper login form. The schema is a
JSON object keyed by API client name. Each entry must provide a stored SHA-256
hex digest under C<secret> plus an C<ajax> array of exact saved Ajax route
paths such as C</ajax/stream.txt> or
C</ajax/example-skill/status.json>. When a non-admin remote request targets one
of those registered C</ajax/...> paths, the caller can send
C<X-DD-API-Key: NAME> and C<X-DD-API-Secret: RAW-SECRET>. Developer Dashboard
hashes the raw secret with SHA-256, compares it to the stored digest, and
executes the saved Ajax handler when they match. Missing or wrong credentials
for a registered API route return C<403> with the JSON body
C<{"status":"forbidden"}>. Existing helper-session auth still works on the
same saved Ajax routes, so browser workflows and machine callers can coexist on
one handler without adding a second copy of the route. Like the rest of
C<DD-OOP-LAYERS>, runtime C<config/api.json> files merge from home to the
deepest active child layer, and installed skills contribute their own layered
C<config/api.json> fragments for skill-local saved Ajax routes. The built-in
C<dashboard api> command is the supported way to inspect or update the writable
runtime layer for that registry.
Saved bookmark Ajax handlers also default to C<text/plain> when no explicit
C<type =E<gt> ...> argument is supplied, and the generated Perl wrapper now
enables autoflush on both C<STDOUT> and C<STDERR> so long-running handlers
show incremental output in the browser instead of stalling behind process
buffers.
If a saved handler also needs refresh-safe process reuse, pass
C<singleton =E<gt> 'NAME'> in the C<Ajax> helper. The generated url then carries
that singleton name, the Perl worker runs as C<dashboard ajax: NAME>, and the
runtime terminates any older matching Perl Ajax worker before starting the
replacement stream for the refreshed browser request. Singleton-managed Ajax
workers are also terminated by C<dashboard stop> and C<dashboard restart>, and
the bookmark page now registers a C<pagehide> cleanup beacon against
C</ajax/singleton/stop?singleton=NAME> so closing the browser tab also tears
down the matching worker instead of leaving it behind.
If C<code =E<gt> ...> is omitted, C<Ajax(file =E<gt> 'name')> targets the
existing executable at C<dashboards/ajax/name> instead of rewriting it.
Static files referenced by saved bookmarks are resolved from the effective
runtime public tree first and then from the saved bookmark root. The web layer
also provides a built-in bundled C</js/jquery.js> asset that serves the local
copy of jQuery 4.0.0, with C</js/jquery-4.0.0.min.js> kept as a compatibility
alias for the same shipped payload even when no runtime file has been copied
into C<dashboard/public/js> yet. Skills can ship the same classes of assets
under their own dashboard tree: C<dashboards/ajax/*> resolves at
C</ajax/E<lt>repo-nameE<gt>/...> or
C</ajax/E<lt>repo-nameE<gt>/E<lt>sub-skillE<gt>/...>, and
C<dashboards/public/js/*>, C<dashboards/public/css/*>, and
C<dashboards/public/others/*> resolve at
C</js/E<lt>repo-nameE<gt>/...>, C</css/E<lt>repo-nameE<gt>/...>, and
C</others/E<lt>repo-nameE<gt>/...> with the same nested-skill extension,
for example C</js/E<lt>repo-nameE<gt>/E<lt>sub-skillE<gt>/path/file.js>. If a
request such as C</js/E<lt>repo-nameE<gt>/foo/bar.js> or
C</js/E<lt>repo-nameE<gt>/E<lt>sub-skillE<gt>/foo/bar.js> does not exist in the
skill-local public tree, the web layer falls back to the normal nested
saved-bookmark asset path C<dashboards/public/js/...> or saved Ajax file path
C<dashboards/ajax/...> instead of assuming the leading path segments must
belong to a skill.
Saved bookmark editor and view-source routes also protect literal inline
script content from breaking the browser bootstrap. If a bookmark body
contains HTML such as C</script>, the editor now escapes the inline JSON
assignment used to reload the source text, so the browser keeps the full
bookmark source inside the editor instead of spilling raw text below the page.
Saved browser workspaces can also show a request-specific token form above the
editor whenever the current request uses C<{{token}}> placeholders, carrying
those token values across matching placeholders in the same workflow so later
requests can reuse the operator-supplied values without manual copy-and-paste.
Bookmark rendering now emits saved C<set_chain_value()> bindings after
the bookmark body HTML, so pages that declare C<var endpoints = {}> and then
call helpers from C<$(document).ready(...)> receive their saved C</ajax/...>
endpoint URLs without throwing a play-route JavaScript C<ReferenceError>.
Bookmark pages now also expose
( run in 0.853 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )