Skip to content

Adding a command

Place one command in src/api/handlers/<resource>/<command>.osl and keep it a thin protocol adapter.

*schema.Schema schemaWidgetGet = schema.object({
id: schema.string().trim().minLen(1)
})
def handleWidgetGet(*ws.Connection conn, object msg) object[] (
string command = "widget_get"
auto err = (string text) object[] -> objErr(text, command)
auto res = schemaWidgetGet.safeParse(msg)
if res.isErr() (
return err(res.unwrapErr().message)
)
object widget = widgetPublic(msg.id)
if widget.len == 0 (
return err("Widget not found")
)
return [{cmd: command, widget}]
)

Validate types before assertions. Allowlist partial updates with pick. Normalize once, then pass trusted values down. Return client errors with objErr; do not throw for invalid input.

  • Sibling handlers sharing a rule should call an API helper.
  • Permission and public serialization logic belong in helpers.
  • Reads/writes and rollback behavior belong under src/db/.
  • Split loaders, management, permissions, and storage when a resource grows.

Persist successfully before returning an event. Administrative mutations call auditRecord; channel metadata mutations call refreshChannels.

Import the handler group in src/api/index.osl if it is new, then add one switch case. If clients can discover or use the feature, add its string to handshakeCapabilities().

If an event must reach other clients, include global: true and channel. The transport removes the marker and filters recipients by canUserViewChannel. Do not implement custom listener copying or broadcast loops in the handler.

Terminal window
cd src
osl fmt .
osl compile main.osl -o ../originchats-osl

Review formatter changes, exercise success and validation failures, verify permission denial, confirm disk state, and check that a broadcast is neither leaked nor duplicated. Update the capabilities and protocol documentation with request/response examples.