johankit-runtime
v0.7.0
Published
A pluggable runtime for any back-end
Readme
Johankit Runtime
Johankit Runtime is a modular, event-driven execution runtime built around packages, events, routes, tools, and conditions.
It is not a framework in the traditional sense. It is an execution model designed to let systems grow by composition instead of coupling.
Why Johankit
Most back-end systems evolve by accumulating:
- integrations
- adapters
- glue code
- shared abstractions
Johankit approaches this differently:
- Everything is a package
- Everything meaningful is an event, route, or tool
- There is no central registry
- There are no hard dependencies between packages
Packages declare behavior explicitly and are discovered automatically at runtime.
Installation
npm install johankit-runtimeBasic Usage
import { bootstrap, dispatchEvent } from 'johankit-runtime'
await bootstrap({
workspace: './packages',
http: { enabled: true },
mcp: { enabled: true }
})
await dispatchEvent('user_created', { id: 1 })Core Concepts
Packages
A package is an isolated unit of behavior located inside the workspace directory.
A package may declare:
- event hooks
- HTTP routes
- tools (callable actions)
- predicates
- middleware
- startup logic
- commands (CLI)
Anything not explicitly declared is ignored.
Discovery
At startup, the runtime:
- Resolves the workspace path
- Scans all package folders
- Loads JavaScript files
- Registers only annotated functions
There is no manual wiring.
Declarative Annotations
Behavior is declared using JSDoc-style annotations.
Important rule: Annotations must be inside the function body.
Example:
function example() {
/**
* @register_hook user_created
*/
}Annotations outside the function are intentionally ignored.
Events (Hooks)
Events represent something that happened.
function enrich(payload) {
/**
* @register_hook user_created
*/
return { ...payload, enriched: true }
}Characteristics:
- Hooks run sequentially
- Returned values replace the payload
nullorundefinedare ignored- Failures do not stop execution
Events act as data pipelines, not notifications.
Routes
Routes expose HTTP handlers automatically.
function status() {
/**
* @register_router status
* @method GET
*/
return { ok: true }
}Routes are automatically namespaced by package name:
/your-package/statusTools
Tools are structured, callable actions.
function calculate() {
/**
* @register_tool calculate
* @description Performs a calculation
* @param {number} x - first value
* @param {number?} y - optional value
*/
}Tools:
- expose input schemas
- can be listed dynamically
- can be invoked programmatically
- can be exposed via MCP or HTTP
They are ideal for automation and orchestration.
Commands (CLI)
Commands are executable actions exposed via the Johankit CLI.
function migrate(args, context) {
/**
* @register_command migrate
*/
}Commands are namespaced by package and executed using:
johankit <package>:<command> [--key value | --params json]Examples:
johankit users:migratejohankit users:migrate --force truejohankit users:migrate --params '{"force": true, "dryRun": false}'Characteristics:
- Commands run inside the same runtime context
- Predicates and conditions apply
- Middlewares are executed
- Commands can be safely composed with the rest of the system
Predicates
Predicates are named boolean checks.
function isAdmin() {
/**
* @register_predicate is_admin
*/
return true
}They enable conditional behavior elsewhere in the system.
Middleware
Middleware can be conditionally enabled using predicates.
function guard() {
/**
* @register_middleware access_guard
* @predicate is_admin
*/
}Only predicates that evaluate to true activate the middleware.
Conditions
Many declarations support optional conditions:
@only web@never mobile@when authenticated
Conditions are metadata, not enforcement rules.
They enable higher-level orchestration without hardcoding logic.
MCP (Tool Control Interface)
Johankit can expose tools through an MCP-style control interface.
Capabilities:
- list tools
- inspect schemas
- invoke tools dynamically
This makes the runtime suitable for:
- automation systems
- agents
- orchestration layers
- external controllers
Bootstrapping
bootstrap({
workspace: './packages',
http: { enabled: true, port: 5040 },
mcp: { enabled: true }
})The bootstrap process:
- loads all packages
- initializes routes
- enables MCP interfaces
- starts HTTP servers if configured
Design Principles
- Explicit behavior over magic
- Composition over inheritance
- Isolation between packages
- Protocol-agnostic core
- Graceful failure handling
Project Status
Early-stage and evolving through real usage.
APIs are intentionally minimal and may evolve as patterns emerge.
