Modules and migrations
On this page:
- spider.module: Declares a module:
pub const spider_module = spider.module(.{ .name, .version, .spider, ... }), checked at compile time. Mounted withserver.mountModules(.{ ... }). - spider.Manifest: What a module declares about itself (
M.spider_module.manifest). - spider.ModuleEnv: The environment variables a module declares in its manifest (
.env). - spider.Migration: One database migration, a module's or the app's own:
.{ .name = "0001_init", .sql = @embedFile(...) }. - spider.Check: Given to a module's
check(c)before the server starts:c.fail(...),c.env(...). - spider.ModuleReport: The modules' checks (
server.check):report.ok(),report.write(w). - spider.ModuleProblem: One problem in a
ModuleReport: the module and the message.
spider.module
pub fn module(comptime spec: anytype) type
Declares a module. Put it in the module's root file as pub const spider_module = spider.module(.{ ... });: it checks the manifest at compile time (name, version, the Spider range against spider.version, requires, migrations, env) and fails the build with a message naming the module when something is wrong.
pub const spider_module = spider.module(.{
.name = "notify",
.version = "0.2.0",
.spider = ">=0.11.0 <0.13.0",
.migrations = &.{.{ .name = "0001_init", .sql = @embedFile("sql/0001_init.sql") }},
.env = .{ .optional = .{"VAPID_PUBLIC_KEY"} },
});
pub fn check(c: *spider.Check) !void {
if (c.env("VAPID_PUBLIC_KEY") != null and c.env("VAPID_PRIVATE_KEY") == null)
c.fail("VAPID_PRIVATE_KEY is empty while VAPID_PUBLIC_KEY is set", .{});
}
module.manifest
pub const manifest: Manifest = m
The checked manifest.
spider.Manifest
pub const Manifest = struct
What a module declares about itself. Built by spider.module; read from M.spider_module.manifest.
Fields
name: []const u8:[a-z][a-z0-9_]*, at most 64 bytes, unique in the app.version: []const u8: The module's own version (semver).spider: []const u8: The Spider versions it supports, as a range:">=0.11.0 <0.13.0".requires: []const []const u8 = &.{}: The modules it needs, by name; they start before it.migrations: []const Migration = &.{}: Its database migrations, in the order they run.env: Env = .{}: The environment variables it reads.
spider.ModuleEnv
pub const Env = struct
The environment variables a module reads: required ones must be set (and not empty) for the module to start; optional ones are listed for the reader and the surface lock.
Fields
required: []const []const u8 = &.{}: Must be set and not empty, orlisten()refuses to start.optional: []const []const u8 = &.{}: Read when present.
spider.Migration
pub const Migration = struct
One forward migration: a name and the SQL it runs. A module lists its own in its manifest; an app's come from its migrations folder (spider.addMigrations in build.zig, then server.migrations(...)).
The name is four or more digits, _, then lowercase letters, digits and _ (0001_init); names sort in the order they run. The SQL may hold several statements; it runs in one transaction that Spider opens, so it must not contain BEGIN, COMMIT or ROLLBACK. When the file has a -- migrate:up line, only what follows it runs, up to -- migrate:down.
.migrations = .{
.{ .name = "0001_init", .sql = @embedFile("sql/0001_init.sql") },
},
Fields
name: []const u8:0001_init: ordering digits,_, a lowercase description.sql: []const u8: The statements, PostgreSQL. Runs inside a transaction.
spider.Check
pub const Check = struct
Given to a module's check(c), which runs before any module boots and must not change anything. fail records a problem (the check goes on, so the report lists every one); a check that returns an error counts as one more.
Fields
arena: std.mem.Allocator: Lives until the report is written.io: Io: An Io for the check (a database query, a file).module: []const u8: The module being checked.
Check.fail
pub fn fail(self: *Check, comptime fmt: []const u8, args: anytype) void
Records a problem: c.fail("FCM_PRIVATE_KEY is empty", .{}).
Check.env
pub fn env(_: *Check, name: []const u8) ?[]const u8
The value of an environment variable (as spider.env.get), or null.
spider.ModuleReport
pub const Report = struct
The result of the checks every module runs before listen().
Fields
arena: std.mem.Allocatorproblems: std.ArrayList(Problem) = .empty: Every problem found, in the order the modules start.warnings: std.ArrayList(Problem) = .empty: What deserves attention without keeping the server from starting: the database holds migrations this binary does not know (a newer version migrated it; this one is a rollback).checked: usize = 0: How many modules were checked.
ModuleReport.ok
pub fn ok(self: *const Report) bool
True when no module reported a problem (warnings do not count).
ModuleReport.write
pub fn write(self: *const Report, w: *Io.Writer) Io.Writer.Error!void
Writes the report: one line per problem, under a summary line, then one line per warning.
spider.ModuleProblem
pub const Problem = struct
One thing a module needs and does not have.
Fields
module: []const u8: The module's name.message: []const u8: What is wrong, and what to do.