Validation, list queries and settings¶
The schema is the type. body, query and params in a got struct are decoded from the
request; every problem is reported with its path, as a 422 problem body:
pub const CreateProject = struct {
title: []const u8,
description: ?[]const u8 = null,
pub fn validate(self: *const CreateProject, issues: *kzig.Issues) !void {
if (self.title.len < 1 or self.title.len > 200) try issues.add("title", "must be 1 to 200 characters");
}
};
// A list endpoint (sketch; tasks arrive in a later milestone):
pub fn list(self: *TaskController, ctx: *kzig.Ctx, got: struct {
query: kzig.ListQuery(.{ .filterable = &.{"status"}, .sortable = &.{"created"} }),
}) !kzig.Paginated(Task) {
// ?filter=status:eq:open&sort=-created&page=2&limit=20
const rows = try self.tasks.find(ctx.arena, got.query);
return got.query.paginate(ctx, Task, rows.items, rows.total);
}
Settings sections are structs with a prefix, read and validated at boot when the module that declares them is mounted:
pub const FeatureSettings = struct {
pub const prefix = "FEATURES";
signups: bool = true, // FEATURES_SIGNUPS
beta_testers: []const []const u8 = &.{}, // FEATURES_BETA_TESTERS=a@x.io,b@x.io
};
pub const AppSettings = struct {
pub const prefix = "APP";
pub const dev_defaults = .{ .public_url = "http://localhost:3000" }; // only when KZIG_ENV is development/test
public_url: []const u8, // APP_PUBLIC_URL, or APP_PUBLIC_URL_FILE=/run/secrets/…
};
Development, test, production¶
KZIG_ENV says how the app runs: development, test, or anything else (unset included) for
production. development and test turn on a section's dev_defaults, apply migrations at
boot (kzig.db.migrate.onBoot's usual policy) and keep Swagger UI when the plugin has
disable_in_prod. kzig dev sets KZIG_ENV=development and kzig start sets
KZIG_ENV=production, unless one is set already.
When KZIG_ENV isn't set, NODE_ENV is read instead, with the same values, so a KickJS app's
.env files and deployment configs work unchanged.
In code, inject *const kzig.Process and read env (.development, .@"test",
.production) or dev_or_test:
pub const MailService = struct {
process: *const kzig.Process,
pub fn send(self: *MailService, msg: Message) !void {
if (self.process.env == .@"test") return; // tests send nothing
…
}
};