class
Analyzer::Zig::Tokamak
- Analyzer::Zig::Tokamak
- Analyzer
- Reference
- Object
Overview
Tokamak declares routes two ways:
-
Inline
tk.Routearrays: const routes: []const tk.Route = &.{ .get("/", hello), .group("/api", &.{ .get("/health", health) }), };.group(prefix, &.{ … })composes its prefix onto every nested route;.post0/.put0/.patch0are body-less verb variants. -
Controller modules mounted with
.router(T). The controller declares one handler per route, naming the function with the method + path: pub fn @"GET /chat/:id"(db: *Session, id: u32) !Chat { … }.router(chat)(wherechat = @import("api/chat.zig")) mounts every such function, composing any enclosing.group(...)prefix. The mount and the controller usually live in different files, so the mount prefixes are resolved project-wide and keyed by controller file.
A controller's routes can also be declared as const bindings rather than
functions — the handler lives in another file and the route is just a name:
pub const Protected = struct { pub const @"GET /projects" = getAllProjects; pub const @"PUT /projects/:id" = updateProject; };
Such structs are mounted by qualified name (.router(api.Protected),
where api = @import("api.zig") and Protected is a struct inside it), so
the route set of one file is partitioned across several mounts. Each route
therefore carries the prefix of every mount that targets its enclosing
struct (or any whole-file mount).
Not yet resolved: a .group(prefix, RouteConst) whose body is a reference
to a tk.Route const (rather than an inline &.{ … } array) — those
controllers' routes are emitted without the referenced-group prefix.
Defined in:
analyzer/analyzers/zig/tokamak.crConstant Summary
-
GROUP_RE =
/\.\s*group\s*\(\s*"([^"]*)"\s*,\s*&?\s*\.\s*\{/ -
GROUP_VALUE_RE =
/\.\s*group\s*\(\s*"([^"]*)"\s*,(?!\s*&?\s*\.\s*\{)/ -
Value-form group whose body is a single route value rather than an
&.{ … }array (tk.group("/api", tk.router(api))). The negative lookahead — which must absorb its own leading whitespace, so a backtracking\s*can't slip past it — keeps the array form to GROUP_RE. -
IMPORT_RE =
/(?:pub\s+)?(?:const|var)\s+([A-Za-z_]\w*)\s*=\s*@import\(\s*"([^"]+\.zig)"\s*\)/ -
ROUTE_CONST_RE =
/pub\s+const\s+@"(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\/[^"]*)"/ -
ROUTE_FN_RE =
/pub\s+fn\s+@"(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\/[^"]*)"/ -
ROUTE_RE =
/\.\s*(get|post0|post|put0|put|patch0|patch|delete|head|options)\s*\(\s*"(\/[^"]*)"\s*,\s*([A-Za-z_][\w.]*)/ -
The path must be a rooted URL (
"/..."). Tokamak handlers commonly build a JSON response withroot.put("name", value)/data.get("key"); those data-object calls share the verb names but never take a/-rooted key, so the leading-slash guard keeps them out of the route set. -
ROUTER_MOUNT_RE =
/\.\s*router\s*\(\s*([A-Za-z_][\w.]*)\s*\)/ -
STRUCT_DECL_RE =
/(?:^|[^A-Za-z0-9_.])(?:pub\s+)?const\s+([A-Za-z_]\w*)\s*=\s*struct\s*\{/ -
VERB_METHOD =
{"get" => "GET", "post" => "POST", "post0" => "POST", "put" => "PUT", "put0" => "PUT", "patch" => "PATCH", "patch0" => "PATCH", "delete" => "DELETE", "head" => "HEAD", "options" => "OPTIONS"}