Services

The builtin services are always available - no import of an instance, no construction. The ADM service manager starts them before application.new runs and stops them on shutdown, so calling one is just Cache.get("k"). For the language rules behind service declarations, see Services in the docs.

A service's public surface is exactly its annotated methods. Fields are always private, and a def with no annotation is internal to the service: it can be called by the service's own methods (method "helper" is internal to service Counter, field "count" is internal to service Counter). Only the members the manager relies on are exempt: the ServiceDescriptor fields (description, dependencies, lifecycle, permissions, status) and the ServiceHooks methods (config, start, stop, restart). Every public method is one of three kinds:

query Reads a snapshot of the service's state. Never async.
commit Mutates state and emits a typed event. Implicitly atomic; may be async.
emit Describes an event's shape only - you subscribe to it with @on(Service.method) and never call it.
usage.adm
use std.services::(Cache, Diagnostics)
use std.metrics::(Counter)

def warm(email string) !none {
	Cache.set("user.{email}", email, ttl = 5m)

	let hits = try Diagnostics.register<Counter>("cache.warm")
	hits.inc()
	return none
}

@on(Cache.expired)
def onExpiry(evt Event<string>) {
	println("expired {evt.result}")
}

Events and observers

Every @commit() call emits an event; there is no way to run a commit silently. The event is named after the method, carries the arguments it was called with, and carries what it returned. It is an ordinary value, Event<T> from the prelude:

builtin
struct Event<T> {
	source service           // the service that emitted it
	name   string            // the method name: "open"
	params map<string, any>  // the call's named arguments: {"path": "data.txt"}
	result T                 // the method's return value, exactly its declared type (T, ?T or !T)
	time   time.Time         // reserved; not populated yet
}

So Storage.open("data.txt") hands the caller the file and hands every observer an Event<os.File> with name = "open", params["path"] = "data.txt" and result set to that same file. An @emit() method is the secondary form: the service calls it from inside a commit (opened(file)) to publish a named event whose result is the value it was given and whose params are empty. @query() methods never emit. Emitting an event that no method declares is a compile error.

@on(Service.method) subscribes a handler: a free function or a method, taking exactly one argument, the Event<T> for that method's return type. Handlers run synchronously inside the commit, after the method body returns and before the caller gets the result, so by the time Storage.open returns every observer has seen the event. A handler cannot change the commit's result. A second argument filters: @on(Storage.open, audit) with def audit(ev Event<os.File>) bool runs the handler only for events the filter accepts; the filter sees the same event record. A method handler on a service runs on that service's singleton; a method handler on any other type runs on one lazily created instance of it.

The Event is read straight through its fields: ev.result, ev.params["path"], ev.name. Commits are serialized per service (implicitly atomic), so observers only ever see completed state, and events are not stored: a handler registered after a commit does not see it.

The service manager owns lifecycle. Services whose lifecycle.start is StartMode.Automatic are started before application.new runs, in the order their dependencies require; StartMode.Manual services wait for code to call start(). lifecycle.restart decides what a failed start gets: Never, OnFailure (retried) or Always (retried more), and the outcome lands in the service's status field as a ServiceStatus (Starting, Started, Stopping, Stopped, Restarting, Failed). Calling start/stop/ restart yourself goes through the manager too, so status stays truthful. Services are singletons that never expire and cannot be constructed with new; all of them stop at shutdown.

Services also ship annotations - @cache, @metric, @measureTime and friends - that wrap a declaration instead of being called. Import them by name (use std.services::(cache)). An annotation that accepts more than one kind of target must be written qualified (use std.services then @services.trace()), because a by-name import narrows it to a single target.

Signatures on this page are generated from the standard library source. Some services are still filling in method bodies; annotations whose behavior is not wired up yet are marked planned.

Builtin services

Application

Identity and lifecycle of the running application.

  • querydef files(name string = "") !string

    The folder holding a package's shipped files, its [package] files: the calling package's when name is empty, else the library named namespace:name (local:name for one installed from a file). Once the program is installed that is share/<namespace>/<name> beside the executable, or the install root for the application itself; while it runs from its source tree it is the package cache for a library and the tree for the application. Fails when no folder exists in either layout.

  • querydef filePath(path string) !string

    Resolves a package path: package://assets/logo.png is a file the calling package shipped, acme:imaging://assets/logo.png one a library shipped. Any other path comes back unchanged. Every Storage method, and so every std.os call, resolves its path this way, so os.readFile("package://assets/logo.png") works from adm run, from a build in the tree and from an installed program alike. Fails when the package has no shipped files.

  • querydef pid() int

    Returns process id of the application

  • querydef executablePath() string

    Returns path to the application executable.

  • querydef startTime() Time

    Returns time when the application process started.

  • querydef name() string

    Returns the name the application is known by: the adm.toml slug when one is configured, else the declared application name.

  • commitdef home() !string

    Returns the application's home folder, creating it on first use and bringing it up to date with this version: the version marker, a snapshot of data/ and the @migration chain. Fails on a downgrade without @allowDowngrade, on a foreign folder at the same path, or when no home directory is known. See Application home & migrations.

  • querydef version() string

    Returns application version, or an empty string if the application is not versioned.

  • querydef build() string

    Returns application build number, or an empty string if unavailable.

  • querydef instanceId() string

    Returns identifier of the current application instance.

    The identifier is unique to this running instance and changes between runs.

  • querydef arguments() string[]

    Returns command-line arguments passed to the application.

  • querydef uptime() duration

    Returns how long the application has been running.

  • commitdef shutdown(code int = 0) !none

    Requests graceful application shutdown.

  • querydef shuttingDown() bool

    Returns whether graceful application shutdown has been requested.

  • emitdef shutdownRequested(code int) int

    Emitted when graceful application shutdown is requested.

  • commitdef exit(code int)

    Terminates the application using the specified exit code.

Cache

Fast in-memory cache with TTL, idle expiration, glob selectors, and size limits.

  • commitatomic def set(key string, value any, ttl ?duration = none, idle ?duration = none)

    Stores a value under the key.

    ttl caps how long the key lives; idle is how long it may go unread before it expires. Either may be left off.

  • queryatomic def get(key string) ?any

    The value under the key, or none when there is none or it has expired.

    Reading restarts the idle timer.

  • queryatomic def get(keys string[]) map<string, any>

    The values under the given keys; missing and expired keys are left out.

    Reading restarts each key's idle timer.

  • queryatomic def get(selector Glob) map<string, any>

    The values under every key the selector matches.

    Reading restarts each key's idle timer.

  • commitatomic def delete(key string)

    Removes the key.

  • commitatomic def delete(keys string[])

    Removes the keys.

  • commitatomic def delete(selector Glob) int

    Removes every key the selector matches and returns how many went.

  • commitatomic def renew(key string, ttl ?duration = none, idle ?duration = none)

    Gives the key a new ttl, idle time, or both.

    A ttl counts from now; an idle time restarts the idle timer.

  • commitatomic def renew(selector Glob, ttl ?duration = none, idle ?duration = none) int

    Renews every key the selector matches and returns how many.

    A ttl counts from now; an idle time restarts each idle timer.

  • commitatomic def take(key string) ?any

    Removes the key and returns what it held, or none when nothing live was there.

  • commitatomic def touch(key string)

    Restarts the key's idle timer; the ttl is untouched.

  • commitatomic def touch(keys string[])

    Restarts the idle timer of each key; ttls are untouched.

  • commitatomic def touch(selector Glob) int

    Restarts the idle timer of every key the selector matches and returns how many.

  • queryatomic def has(key string) bool

    Whether the key is live.

  • queryatomic def has(keys string[]) map<string, bool>

    Whether each key is live.

  • queryatomic def has(selector Glob) bool

    Whether any live key matches the selector.

  • queryatomic def ttl(key string) ?duration

    How long the key has left to live, or none when it is gone or has no ttl.

  • queryatomic def ttl(keys string[]) map<string, ?duration>

    How long each key has left to live; none for a key that is gone or has no ttl.

  • queryatomic def ttl(selector Glob) map<string, ?duration>

    How long each matching key has left to live; none for one with no ttl.

  • queryatomic def idle(key string) ?duration

    How long the key may still go unread, or none when it is gone or has no idle time.

  • queryatomic def idle(keys string[]) map<string, ?duration>

    How long each key may still go unread; none for a key that is gone or has no idle time.

  • queryatomic def idle(selector Glob) map<string, ?duration>

    How long each matching key may still go unread; none for one with no idle time.

  • queryatomic def keys() string[]

    Every live key.

  • queryatomic def keys(selector Glob) string[]

    Every live key the selector matches.

  • queryatomic def size() int

    How many keys are live.

  • queryatomic def size(selector Glob) int

    How many live keys the selector matches.

  • commitatomic def clear()

    Empties the cache.

  • emitdef expired(key string) string

    Emitted when a key expires.

  • emitdef deleted(key string) string

    Emitted when a key is removed by a call rather than by expiry.

  • emitdef created(key string) string

    Emitted when a key is stored for the first time.

Clipboard

Text copy and paste through the system clipboard. The service drives the desktop's clipboard program: wl-copy and wl-paste on Wayland, xclip or xsel on X11, pbcopy and pbpaste on macOS. A machine without one reports nothing available and the calls fail. Reading needs adm.clipboard.read, writing adm.clipboard.write, and both run the program through Runtime.run, so adm.runtime.spawn as well. copy, paste and clear are commits, so @on(Clipboard.copy), @on(Clipboard.paste) and @on(Clipboard.clear) observe them. The programs run through the shell, which the OS sandbox refuses.

  • commitdef copy(text string) !none

    Puts the text on the clipboard, replacing what was there.

    Fails when the policy denies it, this machine has no clipboard program, or the program fails.

  • commitdef paste() !string

    Returns the text on the clipboard, "" when it holds none.

    Fails when the policy denies it, this machine has no clipboard program, or the program fails.

  • commitdef clear() !none

    Empties the clipboard.

  • querydef has() !bool

    Whether the clipboard holds any text. Needs the read permission.

  • querydef capabilities() ClipboardCapabilities

    Reports whether this machine has a clipboard program and which one: wl-clipboard, xclip, xsel or pbcopy.

  • commitdef watch(period duration = 500ms) !none

    Starts watching the clipboard: a task reads it every period and emits changed when the text differs from what it saw last, whichever program changed it. Calling it while watching only changes the period.

    Fails when the policy denies reading or this machine has no clipboard program.

  • commitdef unwatch()

    Stops the watcher task; nothing happens when none runs.

  • querydef watching() bool

    Whether the watcher task runs.

  • emitdef changed(change ClipboardChange) ClipboardChange

    Emitted by the watcher when the clipboard text changed. ClipboardChange carries the text ("" when emptied), whether this program put it there through copy, and when the watcher noticed.

Config

Layered configuration with profiles, typed reads, and reload events.

  • commitdef switchProfile(profile ?string) !none

    Switches to the profile and reloads every source.

    When the reload fails the old profile and its values stay in place.

  • querydef profile() ?string

    The active profile, or none when no profile is selected.

  • querydef get(key string) ?any

    The value the key resolves to, or none when no source defines it.

  • querydef get<T>(key string) !?T

    The value the key resolves to, converted to T; none when no source defines it, an error when it does not convert.

  • querydef has(key string) bool

    Whether some source defines the key.

  • commitdef set(key string, value any)

    Overrides the key for this process.

    An override wins over every source and is never written back to one.

  • commitdef reset(key string)

    Drops the override on the key.

    The key goes back to whatever the sources say.

  • commitdef reload() !none

    Reloads every source.

  • querydef sources() ConfigSourceConfig[]

    The sources, highest precedence first.

  • querydef source(name string) ?ConfigSourceConfig

    The source with that name, or none.

  • querydef sourceOf(key string) ?ConfigSource

    The source the key's value comes from; none for an override or an unknown key.

  • querydef lastLoaded() time.Time

    When the sources last loaded without error.

  • emitdef changed(change ConfigChange) ConfigChange

    Emitted when a key's value changes.

    A reload that leaves the value as it was emits nothing.

  • emitdef reloadFailed(event ConfigReloadError) ConfigReloadError

    Emitted when a source fails to reload.

    The values from the last good load stay in place.

Debugger

Profiling, tracing, heap snapshots, and debug control.

  • commitdef profileStart(kind ProfileKind) !ProfileId

    Starts a profile of the given kind and returns its id.

  • commitdef profileStop(id ProfileId) !Profile

    Stops the profile and returns what it collected.

  • commitdef traceStart() !TraceId

    Starts a trace and returns its id.

  • commitdef traceStop(id TraceId) !Trace

    Stops the trace and returns what it recorded.

  • commitdef gc() !none

    Triggers a garbage collection cycle.

  • querydef stackTrace() errors.StackTrace

    The stack trace of the calling task.

  • querydef heapSnapshot() !HeapSnapshot

    Takes a heap snapshot.

  • commitdef pause() !none

    Breaks into the debugger when one is attached; otherwise does nothing.

  • emitdef watched(event WatchEvent) WatchEvent

    Emitted when a watched field or variable is read or written.

    Which accesses count is the watch's mode.

Devices

Cameras, microphones, USB, and other attached hardware.

Planned - no public methods yet.

Diagnostics

Named metric registry - counters, gauges, histograms, and toggles.

  • commitdef register<T: Metric>(name string) !T

    Registers a metric under the specified name.

    If a metric with the same name and type already exists, it is returned. Fails if the name is already registered with a different metric type.

  • querydef get(name string) ?Metric

    Returns the metric registered under the specified name.

    Returns none if no metric with that name exists.

  • querydef has(name string) bool

    Returns whether a metric with the specified name is registered.

  • querydef list() map<string, Metric>

    Returns all registered metrics.

  • querydef names() string[]

    Returns all registered metric names.

I18n

Locale selection and message catalogs.

Planned - no public methods yet.

IPC

Inter-process communication between ADM applications.

Planned - no public methods yet.

Logging

Leveled logging with structured fields.

  • commitdef debug(message string, fields map<string, any> = {}) !none

    Writes a log entry at debug level.

  • commitdef info(message string, fields map<string, any> = {}) !none

    Writes a log entry at info level.

  • commitdef warning(message string, fields map<string, any> = {}) !none

    Writes a log entry at warning level.

  • commitdef error(message string, fields map<string, any> = {}) !none

    Writes a log entry at error level.

  • commitdef fatal(message string, fields map<string, any> = {}) !none

    Writes a log entry at fatal level.

  • commitdef log(level LogLevel, message string, fields map<string, any> = {}) !none

    Writes a log entry at the given level.

  • querydef level() LogLevel

    The lowest level that is written.

  • commitdef setLevel(level LogLevel)

    Sets the lowest level that is written.

    Entries below it are dropped before they reach any writer.

Messaging

In-memory queues and topics.

Planned - no public methods yet.

Network

Sockets, addressing, name resolution, and socket options.

  • commitdef socket(domain net.SocketDomain, typ net.SocketType) !net.Socket

    Opens a socket for the domain and type; the protocol follows from them. The socket owns its descriptor and must be closed. Errors carry the errno as `error.code` (`std.net.EAddrInUse`) and name the failing operation.

  • commitdef socketFd(domain net.SocketDomain, typ net.SocketType) !int

    Opens a socket and returns its raw descriptor, for code that works with descriptors rather than `std.net.Socket`.

  • commitdef bind(fd int, addr Endpoint) !none

    Binds a socket to a local address: `host:port` or `:port` for IPv4, `[host]:port` or `[]:port` for IPv6, an absolute path for a Unix socket. An empty host binds every interface, port 0 picks a free one (`localAddr` tells which). An existing Unix socket path is not removed.

  • commitdef connect(fd int, addr Endpoint, timeout duration = 30s) !none

    Connects a socket to a remote endpoint, waiting at most `timeout` for the handshake; a timeout fails with `ETIMEDOUT` and leaves the socket open for the caller to close or retry.

  • commitdef accept(fd int) !int

    Accept a new connection from a listening stream socket FD.

    Returns the accepted connection as a new file descriptor; the caller owns the returned FD and must close it.

  • commitdef close(fd int) !none

    Close a socket FD.

    Closing an already-closed FD is an OS error; `std.net` wrappers typically expose `close()` and forward to this method.

  • commitdef listen(fd int, backlog int) !none

    Mark a bound stream socket as a listener.

    `backlog` is passed through to the OS; its effective value may be clamped by the platform.

  • commitdef write(fd int, data byte[], timeout duration = 30s) !int

    Write bytes to a connected stream socket FD.

    Returns the number of bytes written; short writes are normal and callers must loop if they need to send the full buffer (see `std.net.Connection.writeAll`).

    `timeout` bounds the wait for the FD to become writable, not an end-to-end "flush to peer" guarantee.

  • commitdef read(fd int, data byte[], timeout duration = 30s) !int

    Read bytes from a connected stream socket FD.

    Returns the number of bytes read (0 indicates EOF / peer shutdown).

    `timeout` bounds the wait for the FD to become readable.

  • commitdef resolve(dns string) !string[]

    Resolve a DNS name to IP literals (IPv4 and/or IPv6).

    The returned strings never include ports. For "host:port" parsing and socket endpoint construction, see `std.net.Address`.

  • commitdef dialStream(addr Endpoint, timeout duration = 30s) !int

    Resolve + connect a stream socket and return a connected file descriptor.

    This is the lowest-level "dial" helper: it returns a raw FD so higher-level wrappers (`std.net.dialStream`, connection pools, etc.) can build on it.

  • commitdef sendTo(fd int, data byte[], addr Endpoint, timeout duration = 30s) !int

    Send a datagram to a remote address (UDP / Unix datagram).

    Returns the number of bytes sent. For datagrams this is usually either `data.len()` or an error.

  • commitdef recvFrom(fd int, data byte[], timeout duration = 30s) !(int, string)

    Receive a datagram and return the byte count and sender address string.

    The returned address uses the same string format accepted by `sendTo` and `std.net.Address.parse`.

  • commitdef shutdown(fd int, how int = 2) !none

    Shutdown one or both halves of a connection.

    `how` values: - 0: read half (further reads fail/EOF) - 1: write half (further writes fail) - 2: both (full shutdown)

  • commitdef setReuseAddr(fd int, enabled bool = true) !none

    Enable or disable SO_REUSEADDR.

    This is typically required for servers that need to restart quickly.

  • commitdef setNoDelay(fd int, enabled bool = true) !none

    Enable or disable TCP_NODELAY (TCP only).

    For non-TCP sockets this may fail with an OS error.

  • commitdef setKeepAlive(fd int, enabled bool = true) !none

    Enable or disable SO_KEEPALIVE.

    Keepalive behavior is OS-configured; this only toggles it.

  • commitdef setReusePort(fd int, enabled bool = true) !none

    Enable or disable SO_REUSEPORT when supported by the platform.

    Some OSes do not expose this option; in that case this returns an error.

  • commitdef setLinger(fd int, enabled bool, seconds int = 0) !none

    Control SO_LINGER.

    When enabled, `seconds` controls how long the OS may block during `close` in an attempt to deliver queued data.

  • commitdef setRecvBuf(fd int, bytes int) !none

    Set SO_RCVBUF.

  • commitdef setSendBuf(fd int, bytes int) !none

    Set SO_SNDBUF.

  • commitdef setSockOptInt(fd int, level int, opt int, val int) !none

    Sets an integer socket option by its `setsockopt` level and name, for options `std.net.Socket` does not wrap.

  • commitdef getSockOptInt(fd int, level int, opt int) !int

    Read an integer socket option.

  • querydef localAddr(fd int) !string

    Return the local endpoint of a socket FD, formatted as an address string.

    For stream sockets, this is useful after binding `:0` to discover the chosen ephemeral port. For Unix sockets, this is typically the bound path.

  • querydef remoteAddr(fd int) !string

    Return the remote endpoint of a connected socket FD, formatted as an address string.

  • querydef publicAddr() !string

    Returns the host's public address as seen from outside the local network.

  • querydef netIface() !net.NetInterface[]

    Lists the host's network interfaces with their addresses and `std.net.NetIface*` flags.

  • querydef sockets() SocketInfo[]

    Returns runtime information for all sockets owned by the Network service.

  • querydef socketInfo(fd int) ?SocketInfo

    Returns runtime information for the specified socket.

Notifications

Desktop notifications through the platform's notification server. On Linux this is the freedesktop server on the D-Bus session bus; other platforms report nothing available yet. Showing one needs the adm.notifications.show permission.

  • commitdef show(notification Notification) !NotificationId

    Shows a notification and returns the id the server gave it. Notification carries the title, body, an icon name or absolute image path, the level (Info to Critical), action buttons, a timeout and an id to replace.

    Fails when the policy denies it, there is no notification server, or the server refuses it.

  • commitdef show(title string, body string = "") !NotificationId

    Shows a notification with a title and an optional body and returns its id.

  • commitdef close(id NotificationId) !none

    Takes a shown notification off the screen.

    Fails when there is no connection or the server does not know the id.

  • commitdef ask(notification Notification, wait duration = 60s) !string

    Shows a notification whose buttons are a question and waits for the answer: the pressed action's id, or "" when the user dismissed it or nobody answered within wait (the notification is then closed).

    Fails when there is no notification server or it refuses the notification.

  • querydef capabilities() NotificationCapabilities

    Reports what the notification server can do: actions, body text, markup, images, sound, persistence. Nothing is available when there is no server.

  • querydef shown() NotificationId[]

    The ids of the notifications shown by this program that the server has not closed yet.

  • emitdef action(event NotificationAction) NotificationAction

    Emitted when the user presses one of a notification's buttons; the event names the notification and the action id.

  • emitdef closed(id NotificationId) NotificationId

    Emitted when a notification leaves the screen: dismissed, expired or closed.

Policy

Permissions and policy decisions.

  • commitdef registerSpec(name string, factory PolicySpecFactory) !none

    Registers the spec type a permission names, so the file's rules for it can be checked against arguments.

  • commitdef registerResolver(handler PolicyResolver) !none

    Registers the resolver that answers `ask` rules. Without one an `ask` prompts through a desktop notification (Allow, Always allow, Deny); with prompts off (`ADM_POLICY_PROMPT=0`) it denies.

  • commitdef configure(text string) !none

    Loads rules from policy-file text instead of the file, replacing what was loaded. Fails on an unknown permission, field or kind, or a malformed line, naming the line.

  • querydef requirePermissions(permissions string[]) !none

    Fails unless every package on the call chain holds each permission.

  • commitdef revokePermissions(permissions string[]) !none

    Drops permissions from the application's own grants for the rest of the run.

  • querydef hasPermissions(permissions string[]) bool

    Whether every package on the call chain holds each permission.

  • commitdef register(registration PolicyRegistration) !none

    Registers an owner's rules and validators for one action.

  • querydef evaluate(request PolicyRequest) !PolicyDecision

    Decides a request and reports why: which package lacks the permission, or the merged rules that apply.

  • querydef explain(request PolicyRequest) !PolicyDecision

    Explains a request: the decision, the rule and layer behind it.

  • querydef require(request PolicyRequest) !none

    Evaluates the specified policy request against the compiled grant table for every package on the current call chain, the application first.

    Returns successfully when allowed. When denied, fails with a `PolicyDenied` naming the permission and the package lacking it.

  • querydef text() string

    The policy file as it would be written from the loaded rules and settings: one table per subject and permission, the comment preamble kept.

  • querydef validate(permission string, spec string, value string) !none

    Checks one constrained argument of a gated function against the merged rule for its permission: the file's rules for the program and for every package on the chain, then the registered spec's own check. An `ask` outcome goes to the resolver, else to a desktop notification the user answers; unanswered denies. The policy state itself is denied to every subject.

  • querydef list() Permission[]

    Lists every permission the program's services declare.

  • emitdef decided(entry PolicyLogEntry) PolicyLogEntry

    Emitted for every denial, ask and live answer.

Runtime

The ADM runtime itself - host info, memory, environment, service registry, and the one door to other programs: run starts a command through the system shell behind the adm.runtime.spawn permission, whose description says what granting it means: trusting the package completely. Foreign code (@c, @link, @native, @extern) is not a permission: a dependency binding it is accepted by the developer at install and refused by the build otherwise, see Policy.

  • querydef systemInfo() SystemInfo

    Returns information about the host system running the ADM runtime.

  • querydef workingDir() string

    Returns current process working directory.

  • querydef memoryUsage() MemoryUsage

    Returns memory usage statistics for the current ADM runtime.

  • querydef sizeOf(val any) int

    Returns the value's deep retained footprint in bytes. Runtime object and allocation headers, collection capacity, and recursively retained values are included; shared allocations are counted once. UTF-8 string storage is counted even for literals, while unrelated static/external storage is not.

  • querydef getEnv(key string) ?string

    Returns value of the specified environment variable.

    Returns none when the variable is not defined.

  • querydef services() ServiceInfo[]

    Returns runtime information for all registered services.

  • querydef serviceInfo(name service) ?ServiceInfo

    Returns runtime information for the specified service.

    Returns none if the service is not registered with the runtime.

  • commitdef run(command string, input string = "") !ProcessResult

    Runs a command through the system shell with input as its standard input and returns what it printed and its exit code (128 + signal when killed, 127 when the shell could not start it). Needs adm.runtime.spawn. std.os.run and std.os.output wrap it.

    Fails when the policy denies it or the process could not be started, which the OS sandbox causes; a command that exited with an error is reported through the code.

  • commitdef setEnv(key string, value string) !none

    Sets value of the specified environment variable for the current process.

  • emitdef serviceStatusChanged(change ServiceStatusChange) ServiceStatusChange

    Emitted when runtime status of a registered service changes.

Scheduler

Cron, one-shot, and repeating schedules.

  • commitdef cron(cronExpression string, name string = "") !ScheduleId

    Adds a schedule that fires on the cron expression and returns its id.

  • commitdef runAt(timestamp time.Time, name string = "") !ScheduleId

    Adds a schedule that fires once at the given time and returns its id.

    The time must be in the future.

  • commitdef runAfter(dur duration, name string = "") !ScheduleId

    Adds a schedule that fires once after the duration and returns its id.

    The duration must be positive.

  • commitdef runEvery(interval duration, name string = "") !ScheduleId

    Adds a schedule that fires every interval and returns its id.

    The interval must be positive.

  • commitdef cancel(id ScheduleId) !none

    Removes the schedule.

    Fails when there is no such schedule.

  • commitdef pause(id ScheduleId) !none

    Pauses the schedule.

    Its timing is untouched; firings that fall due while it is paused are skipped.

    Fails when there is no such schedule.

  • commitdef resume(id ScheduleId) !none

    Resumes a paused schedule.

    It carries on with its original timing.

    Firings skipped while it was paused are not made up.

    Fails when there is no such schedule.

  • querydef list() Schedule[]

    Every schedule.

  • querydef get(id ScheduleId) ?Schedule

    The schedule with that id, or none.

  • querydef next(id ScheduleId) ?time.Time

    When the schedule next fires; none when there is no such schedule or it is paused.

  • emitdef trigger(id ScheduleId) ScheduleId

    Emitted when a schedule becomes due.

    The service only keeps time; an observer does the work.

Storage

Files, directories, disks, and I/O metrics.

  • commitdef open(path string, mode string) !int

    Open a file or folder at the given path with the specified mode.

  • emitdef fileOpened(path string) string

    Emitted after a file is opened.

  • commitdef close(fd int) !none

    Closes an open file handle.

  • commitdef write(fd int, data byte[]) !int

    Writes bytes at the handle's current position and returns how many were written.

  • commitdef read(fd int, data byte[]) !int

    Reads into the buffer from the handle's current position and returns how many bytes were read.

  • commitdef readFile(path string) !byte[]

    Reads a whole file into memory.

  • commitdef writeFile(path string, data byte[]) !none

    Writes the bytes to a file, replacing any existing content.

  • commitdef seek(fd int, offset int64, whence int) !int64

    Moves the handle's position and returns the new absolute offset.

    Whence follows the Whence enum: start, current, or end.

  • commitdef readAt(fd int, data byte[], offset int64) !int

    Reads into the buffer starting at an absolute offset, leaving the handle's position unchanged.

  • commitdef writeAt(fd int, data byte[], offset int64) !int

    Writes bytes at an absolute offset, leaving the handle's position unchanged.

  • commitdef truncate(fd int, size int64) !none

    Resizes the file to the given size, padding with zero bytes when it grows.

  • commitdef exists(path string) !bool

    Returns whether a file or directory exists at the path.

  • commitdef remove(path string) !none

    Removes a file.

  • commitdef rename(oldPath string, newPath string) !none

    Renames or moves a file or directory.

  • commitdef mkdir(path string) !none

    Creates a directory, including any missing parents.

  • commitdef rmdir(path string) !none

    Removes an empty directory.

  • querydef readDir(path string, depth int = 0) !os.DirEntry[]

    Lists the entries of a directory.

    Depth 0 lists the directory itself; a larger depth descends that many levels.

  • commitdef delete(path string) !none

    Delete a file or a folder at the given path

  • querydef stat(path string) !os.FileInfo

    Returns size, mode, and timestamps for a path.

  • querydef openedFiles()

    Return a list of opened file descriptors.

  • commitdef chmod(file string, mode int64) !none

    Changes a file's permission bits.

  • querydef metrics(fd ?int)

    Return read/write metrics for a file descriptor if a fd is provided or for all if not

  • querydef freeSpace(disk string)

    Get the free space on a specific disk.

  • querydef disks()

    List of all available disks.

Telemetry

Telemetry export.

Planned - no public methods yet.

UI

Windows, the renderer, and input events.

  • commitdef openWindow(cfg r.WindowConfig) !r.Window

    Opens a window on the configured renderer. The handle stays valid until the window closes.

  • commitdef openWindow<T: component>(root T, cfg r.WindowConfig) !r.Window

    Opens a window with root as the component it renders.

  • commitdef openDefaultWindow() !r.Window

    Opens a window with the `UIConfig.defaultWindow` settings.

  • commitdef openDefaultWindow<T: component>(root T) !r.Window

    Opens a window with the `UIConfig.defaultWindow` settings and root as the component it renders.

  • commitdef closeWindow(win r.Window) !none

    Closes the window.

  • commitdef setWindowTitle(win r.Window, title string) !none

    Sets a window's title.

  • commitdef setWindowIcon(win r.Window, icon image.Image) !none

    Sets a window's icon.

  • querydef windows() r.Window[]

    The open windows.

  • querydef pollPlatformEvents(win r.Window) !r.PlatformEvent[]

    Reads the raw platform events waiting on the window. Nothing is emitted; pumpEvents turns them into `std.ui` events.

  • commitasync def run<T: component>(root T, cfg r.WindowConfig) !none

    Opens a window for `root` and returns when the user closes it. The whole of a single-window application's main.

  • commitasync def run<T: component>(root T) !none

    Opens a window for `root` with the `UIConfig.defaultWindow` settings and returns when the user closes it.

  • commitdef pumpEvents(win r.Window) !r.PlatformEvent[]

    Reads the platform events waiting on the window and emits the `std.ui` event for each. Returns the raw events it consumed.

  • commitdef pumpAll() !none

    pumpEvents for every open window.

  • emitdef click(evt ui.ClickEvent) ui.ClickEvent

    Emitted for a click, resolved to the component under it.

  • emitdef mouseMove(evt ui.MouseMoveEvent) ui.MouseMoveEvent

    Emitted when the pointer moves, resolved to the component under it.

  • emitdef mouseWheel(evt ui.MouseWheelEvent) ui.MouseWheelEvent

    Emitted for a wheel or trackpad scroll.

  • emitdef resize(evt ui.ResizeEvent) ui.ResizeEvent

    Emitted when a window is resized.

  • emitdef close(evt ui.CloseEvent) ui.CloseEvent

    Emitted when the user asks to close a window.

  • emitdef keyDown(evt ui.KeyEvent) ui.KeyEvent

    Emitted when a key goes down.

  • emitdef keyUp(evt ui.KeyEvent) ui.KeyEvent

    Emitted when a key comes up.

  • emitdef textInput(evt ui.TextInputEvent) ui.TextInputEvent

    Emitted for typed text.

Vault

Encrypted storage for secrets.

Planned - no public methods yet.

Annotations

Each entry shows the annotation as it is written at a use site - the meta context parameter and any type parameter inferred from the target are not spelled out.

@migration

Application · targets functions of the application block

@migration(from string, to string = "")

Marks a step that upgrades the application's home folder from one version to another; see Application.home() and Application home & migrations.

from is the version whose data the step understands; to is the version it produces, or the next declared step's from when omitted. Steps run in ascending order, and only those newer than the version that last ran the folder. The annotated function takes the home folder path and returns !none; a failing step restores the snapshot taken before the first step.

migration.adm
application MyApp {
	@migration(from = "3.54", to = "4.0")
	def settingsToJson(home string) !none { ... }

	@migration(from = "4.0", to = "5.63")
	def splitCache(home string) !none { ... }
}

@allowDowngrade

Application · targets the application block

@allowDowngrade()

Lets the application open a home folder last written by a newer version of itself. Without it, a downgrade fails in Application.home().

downgrade.adm
@allowDowngrade()
application MyApp { ... }

@cache

Cache · targets methods

@cache(key string, ttl ?duration = none, idle ?duration = none, refresh = false)

Serves the method's result from the cache under key.

A live entry is returned and the body does not run; otherwise the body runs and its result is stored. With refresh the body always runs and replaces the entry.

ttl and idle go to Cache.set.

cache.adm
use std.services::(cache)

@cache("user.{email}", ttl = 5m)
def loadUser(email string) !User {
	return try db.fetchUser(email)
}

@cacheInvalidate

Cache · targets methods

@cacheInvalidate(key ...Glob)
@cacheInvalidate(key ...string)

Removes every key the selectors match once the method has run.

A pattern may interpolate the method's arguments.

cacheinvalidate.adm
@cacheInvalidate("user.{email}")
def renameUser(email string, name string) !none {
	return try db.rename(email, name)
}

@config planned

Config · targets variables, fields

@config(key string, defaultValue ?any = none)

Fills the variable from the configuration key.

The value is converted to the variable's type. An optional variable reads none when the key is missing; a non-optional one with no default makes configuration loading fail.

config.adm
use std.services::(config)

@config("server.port", 8080)
let port = 0

@trace planned

Debugger · targets functions, methods

@trace()

Records the function's calls while a trace is running.

Each call logs when it started, how long it took, who called it and what error it returned.

Tracing itself is started with Debugger.traceStart and stopped with Debugger.traceStop.

trace.adm
use std.services

@services.trace()
def handleRequest(id string) !none {
	return try route(id)
}

@noInline planned

Debugger · targets functions, methods

@noInline()

Keeps the compiler from inlining the function.

noinline.adm
@services.noInline()
def hotPath(n int) int {
	return n * 2
}

@noOptimize planned

Debugger · targets functions, methods

@noOptimize()

Compiles the function without optimisation.

It is not inlined either, so a debugger sees it as written.

nooptimize.adm
@services.noOptimize()
def underInvestigation(n int) int {
	return n * 2
}

@trackCaller

Debugger · targets functions, methods

@trackCaller()

Reports the caller's location instead of the function's own in diagnostics.

For helpers that fail on the caller's behalf, so the message points at the call, not at the helper.

trackcaller.adm
@services.trackCaller()
def logHere(message string) {
	println("{__file_name__}:{__line__} {message}")
}

@watch planned

Debugger · targets fields, variables

@watch(mode WatchMode = WatchMode.Write)

Emits Debugger.watched on every access to the field.

mode picks reads, writes or both.

Every access becomes a call, so leave it out of release builds.

watch.adm
type Session {
	@services.watch(WatchMode.Write)
	token string
}

@metric

Diagnostics · targets fields

@metric(name string)

Registers a metric using the annotated field's metric type and assigns the resulting metric handle to the field.

If a metric with the same name and type already exists, the existing metric is used. Registration fails if the name is already registered with a different metric type.

The field’s own type selects the metric kind - no type argument is written.

metric.adm
use std.services::(metric)
use std.metrics::(Counter, Gauge)

type Uploads {
	@metric("uploads.total")
	total Counter

	@metric("uploads.inflight")
	inflight Gauge
}

@measureCount

Diagnostics · targets methods

@measureCount(name string)

Tracks how many times the annotated method is invoked.

Registers a Counter under the specified metric name and increments it once for every method invocation.

measurecount.adm
@measureCount("uploads.calls")
def upload(data byte[]) !none {
	return try store(data)
}

@measureTime

Diagnostics · targets methods

@measureTime(name string)

Tracks the execution duration of the annotated method.

Registers a Histogram under the specified metric name and records the duration of every completed method invocation.

measuretime.adm
@measureTime("uploads.latency")
def upload(data byte[]) !none {
	return try store(data)
}

@measureErrors

Diagnostics · targets methods

@measureErrors(name string)

Tracks failed executions of the annotated method.

Registers a Counter under the specified metric name and increments it when the method returns an error. The original error is propagated unchanged.

measureerrors.adm
@measureErrors("uploads.failures")
def upload(data byte[]) !none {
	return try store(data)
}

@measureConcurrency

Diagnostics · targets methods

@measureConcurrency(name string)

Tracks the number of concurrently executing invocations of the annotated method.

Registers a Gauge under the specified metric name. The gauge is incremented when the method begins execution and decremented when the method completes, including when the method returns an error.

measureconcurrency.adm
@measureConcurrency("uploads.active")
def upload(data byte[]) !none {
	return try store(data)
}

@log planned

Logging · targets functions, methods

@log(level LogLevel = LogLevel.Debug)

Writes a log entry each time the function is called.

The arguments go in as fields.

log.adm
use std.services
use std.services::(LogLevel)

@services.log(LogLevel.Info)
def createOrder(id string) !none {
	return try persist(id)
}

@logContext planned

Logging · targets types, functions, methods

@logContext(fields map<string, any>)

Attaches fields to every log entry written from the type's methods.

A closer @logContext or a field passed to the call itself wins on the same key.

@sensitive planned

Logging · targets parameters, fields, properties

@sensitive()

Marks a value that must not show up in developer output.

Logs, traces, watches, crash reports and the IDE inspector print it redacted.

struct Credentials { username string @sensitive() password string }

@log() def login(username string, @sensitive password string) {}

sensitive.adm
def login(email string, @services.sensitive() password string) !Session {
	return try authenticate(email, password)
}

@requires planned

Policy · targets functions, methods

@requires(permissions string[])
requires.adm
@services.requires(["net.connect"])
def fetch(url string) !Response {
	return try http.get(url)
}

@cron planned

Scheduler · targets functions

@cron(cronExpression string, name string = "")

Calls the function whenever the cron expression fires.

cron.adm
use std.services::(cron)

@cron("0 3 * * *")
def nightlyCleanup() {
	purgeTempFiles()
}

@at planned

Scheduler · targets functions

@at(timestamp time.Time, name string = "")

Calls the function once, at the given time.

@after planned

Scheduler · targets functions

@after(interval duration, name string = "")

Calls the function once, after the duration.

after.adm
@after(30s)
def warmUp() {
	primeCaches()
}

@runEvery planned

Scheduler · targets functions

@runEvery(interval duration, name string = "")

Calls the function every interval.

runevery.adm
@runEvery(5m)
def heartbeat() {
	Logging.info("alive")
}