Extension based tasks, server intents & fuzzy hinting
Intents
The major blocker on using Katamari for "real" work is the present lack of a vehicle for implementing recognizable tasks such as repl
or test
. Because Katamari attempts to defer the majority of its heavy lifting to the server, there wasn't an obvious way to implement tasks which would occur in or take over the user's shell.
Katamari 0.0.3 introduces the concept of "response intents". Katamari's server handlers (should) respond uniformly with JSON payloads. The "intent"
key in the response JSON map is special, and may be used by server side tasks to communicate to the kat
script a desired interpretation of the response. For instance the "msg"
or "message"
intent may be used to display the "msg"
field of the response as a message to the user. Other examples of intents include the "sh"
or "subshell"
intent which may be used to execute a BASH script in the user's environment, and "exec"
which causes the kat
script to exec
into another program.
Intents are a secondary layer by which the server can provide default behavior. The kat
response handling flags -r
, -m
and -j
and their long equivalents all take precedence over the server's suggested interpretation. This also allows the user to debug and inspect server responses.
This makes it possible to implement recognizable repl
and test
tasks in the future, and enables the new restart-server
command which leverages the user's shell to bounce the server.
$ ./kat restart-server
Attempting to subshell...
{"intent":"sh","sh":"$KAT stop-server; $KAT start-server"}
Scheduling shutdown
Starting server ...
Waiting for it to become responsive \
Started server!
http port: 3636
nrepl port: 3637
Extension based tasks
Previously, Katamari's server handlers were pretty magical - the handler stack was hard coded in web_server.clj
, which made live development difficult due to having to reload both handlers and the server all the time and made the handlers themselves not particularly first class as a user couldn't inject more handlers as they pleased.
Katamari 0.0.3 introduces a middleware registry of sorts, into which dynamically loaded extensions can register their own middlewares either directly or using the defwrapper
and defhandler
macros. These two macros capture the main patterns for existing Katamari request middlewares - wrappers wrap an entire request, either monkeypatching the response or providing request context. Handlers on the other hand handle requests. The middleware registry solves the interactive development problem by re-compiling all the handlers and wrappers into a single middleware stack when changes to the registry occur.
The request server now requests the current compiled handler from the registry.
In extreme circumstances, the registry can be flushed using reset-middleware!
. This is mostly useful for dealing with handlers which should be removed from the registry, or changes to the root handler.
All existing handlers and wrappers have been successfully refactored over to this interface, except for the help
handler which needs some exceptional behavior.
$ ./kat help
Katamari - roll up your software into artifacts!
Usage:
./kat [-r|-j|-m] [command] [flags] [targets]
Flags:
-r, --raw - print the raw JSON of Katamari server responses
-j, --json - format the JSON of Katamari server responses
-m, --message - print only the message part of server responses
Commands:
meta:
Collect metadata for available tasks and handlers.
Tasks and handlers are expected to participate in handling requests starting
with `meta` by conjing their metadata into the response `[:body :metadata]`. By
failing to participate in this protocol, tasks and handlers become invisible to
reflective tools like `list-tasks` and `help` which rely on `meta`.
start-server:
A task which will cause the server to be started.
Reports the ports on which the HTTP and nREPL servers are running.
help:
Describe a command in detail, or sketch all commands
list-tasks:
Enumerate the available tasks.
Do not report their help information.
restart-server:
Reboot the server, reloading the config and other options.
show-request:
Show the request and config context as seen by the server (for debugging)
classpath:
Usage:
./kat classpath [deps-options] -- [target ...]
Compute a classpath and libs mapping for selected target(s)
uberjar:
Usage:
./kat uberjar [target]
Given a single target, produce an uberjar according to the target's config.
WARNING: As this is a special case of the compile task, it may be removed.
stop-server:
Shut down the server after all outstanding requests complete.
list-targets:
Enumerate all the available Rollfile targets.
Fuzzy hinting
As a minor UX improvement and a proof that the new middleware/handler machinery is up to the job, Katamari now ships with a request wrapper which offers suggestions of fuzzily matched possible commands when the user inputs a command for which no handler is found.
$ ./kat list
No handler found for request:
["list"]
Did you mean one of:
list-tasks
list-targets
classpath