npm package: @t8n/kit
Description: The standard decorator extension for TitanPL
Latest version: 0.0.3

# @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/lib` for 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:

```bash
npm i @t8n/kit
```

Recommended flow:

1. Create your TitanPL app or server from the TitanPL docs.
2. Install `@t8n/kit`.
3. Add controllers and route decorators.
4. Run `npm run dev` in 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:

```ts
import t from "@titanpl/route";

t.start(5100, "Titan Running!");
```

When your decorated controller files are imported, `@t8n/kit` can insert lines
like:

```ts
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`:

```json
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
```

```json
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}
```

## How It Works

1. You create controller classes and decorate methods with route decorators.
2. You import those controller files somewhere in your app or action files.
3. `@t8n/kit` collects the route metadata.
4. 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:

```bash
npm run dev
```

Run 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.

```ts
import { Controller, Post } from "@t8n/kit";

@Controller("/user")
class UserController {
  @Post("/login", "action", "login")
  login() {}
}
```

This becomes:

```ts
t.post("/user/login").action("login");
```

You can also use `@Controller` without a base path:

```ts
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

```ts
import { Controller, Post } from "@t8n/kit";

@Controller("/auth")
class AuthController {
  @Post("/login", "action", "login")
  login() {}
}
```

Generated route:

```ts
t.post("/auth/login").action("login");
```

### Reply route

```ts
import { Get } from "@t8n/kit";

class PublicRoutes {
  @Get("/health", "reply", "ok")
  health() {}
}
```

Generated route:

```ts
t.get("/health").reply("ok");
```

### `reply` with objects

```ts
import { Get } from "@t8n/kit";

class MetaController {
  @Get("/meta", "reply", { name: "kit", ready: true })
  meta() {}
}
```

Generated route:

```ts
t.get("/meta").reply({ "name": "kit", "ready": true });
```

### Full controller example

```ts
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:

```ts
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`](https://github.com/t8nlab/kit/blob/main/test/app/app.ts):

```ts
t.post("/user/login").action("login");
```

The action implementation can then call the controller method, like in
[`test/app/actions/login.ts`](https://github.com/t8nlab/kit/blob/main/test/app/actions/login.ts):

```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`:

```ts
import "app/controllers/user";
```

## Recommended Usage Pattern

For the current release, this pattern works best:

1. Create controllers in `app/controllers`.
2. Decorate methods with `@Get`, `@Post`, `@Put`, or `@Delete`.
3. Import the controller file from an action file or another loaded module.
4. Keep `app/app.ts` present in your TitanPL app.
5. Let `@t8n/kit` write the route entries there.

## API Reference

### `Controller`

```ts
Controller(target: Function): void
Controller(basePath: string): ClassDecorator
```

### Method decorators

```ts
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

```ts
import { joinPath, normalizePath, removeRoute, writeRoute } from "@t8n/kit/lib";
```

Example:

```ts
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

```txt
app/
  actions/
    login.ts
    getuser.ts
  controllers/
    user.ts
  app.ts
```

## Import Patterns

### Import a controller for side effects

Useful when you only want decorators to register routes:

```ts
import "app/controllers/user";
```

### Import a controller class directly

Useful when an action wants to call controller methods:

```ts
import UserController from "app/controllers/user";

const controller = new UserController();
```

## Stability Notice

`@t8n/kit@0.0.1-alfa` 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