Utilities
The cross-cutting helpers every extension shares: config files, structured logging, request events, and payload signing.
These helpers are available to every building block through this.kora.
Config files
Extensions can keep their own config, namespaced under the extension so it never collides with Kora's.
Register it in onStartup() by passing your extension name, a file name, and
the default shape.
onStartup() {
this.kora.config.initialize(this.getName(), "settings", {
SETTINGS: {
ENABLED: true,
MODE: this.kora.config.validator.enum("basic", "advanced"),
LIMITS: { MAX: 10 }
}
});
}This creates config/my-extension/settings.json from the defaults on first run. Read it anywhere with
this.kora.config.get(this.extension, "settings").SETTINGS. Config files are self-healing: missing
keys are added back with their defaults and unreadable files are rebuilt, so users cannot break your
extension by editing them. Use this.kora.config.validator.enum(...) for a value that must be one of a
fixed set (the first entry is the default).
Logging
Log through this.kora.console so your output matches Kora's format and respects the user's console
settings. Pick a level from this.kora.console.levels:
this.kora.console.log(this.kora.console.levels.info, "Something happened.");| Level | Use it for |
|---|---|
info | general information |
success | an operation completed |
warning | something recoverable that deserves attention |
error | a failure |
debug | detail shown only when KORA.CONSOLE.DEBUG is on |
startup | boot-time messages |
cli | output from a CLI command |
Request events
Kora exposes a shared Node EventEmitter at this.kora.events.
Subscribe to it in onStartup() to react to things happening across the whole
instance, then unsubscribe in onShutdown() if your listener holds onto anything.
The built-in api.request event fires once for every request to a
route, after the response has been fully sent, whatever the outcome
(success, an auth failure, a rate limit, or a handler error). It is a convenient hook for analytics,
auditing, or usage tracking.
onStartup() {
this.kora.events.on("api.request", event => {
this.kora.console.log(this.kora.console.levels.debug, `${event.method} ${event.path} => ${event.status} (${event.duration}ms)`);
});
}The event payload is:
| Field | Description |
|---|---|
method | The HTTP method (GET, POST, ...). |
path | The route's path. |
status | The HTTP status code that was sent. |
duration | How long the request took, in milliseconds. |
key | The name of the API key used, or null for public routes. |
ip | The caller's IP address, or null if it could not be determined. |
agent | The request's User-Agent header, or null. |
Signing payloads
this.kora.backend.signature creates and checks HMAC signatures: useful for signing an outgoing webhook
or verifying that an incoming request really came from a trusted source. Strings are signed as-is; objects
are hashed with stably sorted keys, so the same data always produces the same signature regardless of key
order.
const signature = this.kora.backend.signature.sign(payload, secret);
const trusted = this.kora.backend.signature.verify(payload, secret, signature);sign(data, secret, algorithm = "sha256")returns a hex signature fordata.verify(data, secret, signature, algorithm = "sha256")returnstrueonly when the signature matches, using a constant‑time comparison that is safe against timing attacks.

