Low-level descriptors
Build immutable modules and Elysia controllers without decorator metadata.
Decorators are the default application API. Low-level descriptors are useful for platform adapters, integration libraries, or standalone containers.
Define a module
import {
defineModule,
provideValue,
createToken,
} from "@aponiajs/common";
const APP_NAME = createToken<string>("APP_NAME");
const AppModule = defineModule({
id: "AppModule",
providers: [provideValue(APP_NAME, "AponiaJS")],
exports: [APP_NAME],
});defineModule() freezes copied imports, controllers, providers, and exports.
Register routes directly
import { defineElysiaController } from "@aponiajs/platform-elysia";
class HealthController {
read() {
return { ok: true };
}
}
const healthController = defineElysiaController(HealthController, {
inject: [] as const,
path: "/health",
registerRoutes: (application, controller) => {
application.get("/health", () => controller.read());
},
});registerRoutes receives the root Elysia application after native plugin
modules mount. path is optional metadata used by route diagnostics. This form
avoids an intermediate controller plugin and is the target for future
build-time descriptor emitters.
Build an isolated controller plugin
The compatibility form lets a controller deliberately own a native plugin:
import { defineElysiaController } from "@aponiajs/platform-elysia";
import { Elysia } from "elysia";
const healthController = defineElysiaController(HealthController, {
inject: [] as const,
buildPlugin: (controller) =>
new Elysia().get("/health", () => controller.read()),
});The buildPlugin result must be an Elysia instance or bootstrap fails with
INVALID_CONTROLLER. The controller definition is frozen in either form.
Low-level controller definitions are platform-specific; module and provider
descriptors remain platform-neutral.
Static route types
A concrete buildPlugin return type contributes its routes to
AponiaFactory.createNative(). The direct registerRoutes callback is the
optimized runtime path, but its generic root-application parameter does not
describe new route generics to TypeScript today.
See Eden Treaty for the complete static inference boundary.