@t8n/kit
v0.0.3
Published
The standard decorator extension for TitanPL
Downloads
37
Readme
@t8n/kit
The standard decorator extension for TitanPL, built to bring a NestJS-like developer experience to TitanPL apps, with routes now and more decorators coming soon.
@t8n/kit lets you define TitanPL routes with TypeScript classes and route
decorators, then writes the matching route entries into your app/app.ts file
automatically.
This package is currently in 0.0.1-alfa.
Important:
- This is an early testing release.
- Only route decorators are available right now.
- Not all decorators are implemented yet.
- The goal is to make TitanPL feel more like a decorator-first framework similar to NestJS.
- More decorator-based features are coming soon.
- APIs and behavior may change at any time while the package is being tested.
- If you try it and hit any issue, please report it at
https://github.com/t8nlab/kit.
Current Features
@Controller()to group routes under a shared base path@Get()@Post()@Put()@Delete()"action"routes for TitanPL actions"reply"routes for direct static replies- Helpers exported from
@t8n/kit/libfor low-level route writing:normalizePath()joinPath()writeRoute()removeRoute()
Installation
First, create a TitanPL app by following the official docs:
https://titanpl.vercel.app/docs
After your TitanPL app is ready, install the extension:
npm i @t8n/kitRecommended flow:
- Create your TitanPL app or server from the TitanPL docs.
- Install
@t8n/kit. - Add controllers and route decorators.
- Run
npm run devin your TitanPL server once to let everything wire up and verify routes.
Project Setup
Your TitanPL app will have an app/app.ts entry file. @t8n/kit writes route
lines into that file.
Minimal example:
import t from "@titanpl/route";
t.start(5100, "Titan Running!");When your decorated controller files are imported, @t8n/kit can insert lines
like:
t.post("/user/login").action("login");TypeScript Notes
Because this package is decorator-based, your TypeScript app should enable decorators.
Add in tsconfig.json at compilerOptions:
"experimentalDecorators": true,
"emitDecoratorMetadata": true,{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}How It Works
- You create controller classes and decorate methods with route decorators.
- You import those controller files somewhere in your app or action files.
@t8n/kitcollects the route metadata.- It writes matching TitanPL route definitions into
app/app.ts.
Build And Production Behavior
@t8n/kit is based on route generation logic, not live runtime route mutation
in production.
- In development, when your decorated files are loaded, the route lines are
written into
app/app.ts. - During build, TitanPL uses the generated route file output that already exists.
- In production, the server does not keep creating or changing routes after the app has been built.
- This is similar to TitanPL actions: after build, if you add new actions or new decorated routes, you need to rebuild the app for those changes to be included.
Recommended check:
npm run devRun that once in your TitanPL server after adding or changing decorators so the route output can be checked during development.
Route Decorators
@Controller(basePath)
Adds a shared base path to every decorated route in the class.
import { Controller, Post } from "@t8n/kit";
@Controller("/user")
class UserController {
@Post("/login", "action", "login")
login() {}
}This becomes:
t.post("/user/login").action("login");You can also use @Controller without a base path:
import { Controller, Get } from "@t8n/kit";
@Controller
class PublicController {
@Get("/health", "reply", "ok")
health() {}
}HTTP method decorators
Available decorators:
Get(path, type, value)Post(path, type, value)Put(path, type, value)Delete(path, type, value)
Supported route types:
"action": maps the route to a TitanPL action name"reply": returns a direct reply value
Usage Examples
Action route
import { Controller, Post } from "@t8n/kit";
@Controller("/auth")
class AuthController {
@Post("/login", "action", "login")
login() {}
}Generated route:
t.post("/auth/login").action("login");Reply route
import { Get } from "@t8n/kit";
class PublicRoutes {
@Get("/health", "reply", "ok")
health() {}
}Generated route:
t.get("/health").reply("ok");reply with objects
import { Get } from "@t8n/kit";
class MetaController {
@Get("/meta", "reply", { name: "kit", ready: true })
meta() {}
}Generated route:
t.get("/meta").reply({ "name": "kit", "ready": true });Full controller example
import { Controller, Delete, Get, Post, Put } from "@t8n/kit";
@Controller("/users")
class UsersController {
@Get("/", "action", "getUsers")
list() {}
@Get("/:id", "action", "getUser")
get() {}
@Post("/", "action", "createUser")
create() {}
@Put("/:id", "action", "updateUser")
update() {}
@Delete("/:id", "action", "deleteUser")
remove() {}
}Real Example
Based on test/app/controllers/user.ts](https://github.com/t8nlab/kit/blob/main/test/app/controllers/user.ts), this controller:
import { Controller, Post } from "@t8n/kit";
@Controller("/user")
class UserController {
@Post("/login", "action", "login")
login(req: any) {
return { ok: true };
}
}produces this route entry in test/app/app.ts:
t.post("/user/login").action("login");The action implementation can then call the controller method, like in
test/app/actions/login.ts:
import { defineAction } from "@titanpl/native";
import UserController from "app/controllers/user";
export default defineAction((req) => {
const controller = new UserController();
return controller.login(req);
});Also note just imports the controller file so route
decorators can run multi time import never make bugs:
import "app/controllers/user";Recommended Usage Pattern
For the current release, this pattern works best:
- Create controllers in
app/controllers. - Decorate methods with
@Get,@Post,@Put, or@Delete. - Import the controller file from an action file or another loaded module.
- Keep
app/app.tspresent in your TitanPL app. - Let
@t8n/kitwrite the route entries there.
API Reference
Controller
Controller(target: Function): void
Controller(basePath: string): ClassDecoratorMethod decorators
Get(path: string, type: "action", actionName: string)
Get(path: string, type: "reply", replyValue?: unknown)
Post(path: string, type: "action", actionName: string)
Post(path: string, type: "reply", replyValue?: unknown)
Put(path: string, type: "action", actionName: string)
Put(path: string, type: "reply", replyValue?: unknown)
Delete(path: string, type: "action", actionName: string)
Delete(path: string, type: "reply", replyValue?: unknown)Low-level helpers
import { joinPath, normalizePath, removeRoute, writeRoute } from "@t8n/kit/lib";Example:
writeRoute({
method: "GET",
path: "/hello",
type: "reply",
value: "world",
});Notes And Limitations
- Only route decorators are implemented right now.
- Decorators run when the file is imported.
- Route generation is intended for development/build flow, not post-build production mutation.
- Early APIs may change without notice between test releases.
Example App Structure
app/
actions/
login.ts
getuser.ts
controllers/
user.ts
app.tsImport Patterns
Import a controller for side effects
Useful when you only want decorators to register routes:
import "app/controllers/user";Import a controller class directly
Useful when an action wants to call controller methods:
import UserController from "app/controllers/user";
const controller = new UserController();Stability Notice
@t8n/[email protected] is experimental.
- Only the route decorator layer exists today.
- The package is designed as the base for a broader TitanPL decorator system.
- More decorators may be added later.
- Existing APIs may be renamed, expanded, or removed.
- Use it for testing and feedback, not for assuming final stable behavior.
Issues And Feedback
If you find a bug, unexpected route output, or decorator issue, please open an issue in the repo:
https://github.com/t8nlab/kit/issues
Repository:
https://github.com/t8nlab/kit
License
MIT
