Skip to content
Agentmart
Submit a tool

decorators

Vovk.ts decorators — built-in (`@prefix`, `@operation`, `@get/@post/@put/@patch/@del`, `.auto()`) and custom via `createDecorator`.

Skill by finom

IndexedMIT★ 54
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/finom-decorators

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Vovk.ts decorators — built-in (`@prefix`, `@operation`, `@get/@post/@put/@patch/@del`, `.auto()`) and custom via `createDecorator`. Covers authorization / auth decorators, middleware-style wrapping (pre-handler + post-handler logic), `req.vovk.meta()` for cross-decorator state, stacking order, and the local (`.fn()`) vs HTTP context distinction. Use whenever the user asks to "write a custom decorator", "add auth middleware", "protect an endpoint", "build an authorization decorator", "createDecorator", "stack decorators", "share data between decorator and handler", "prefix all routes", "@auto", "decorator execution order". Does NOT cover procedure authoring → hand off to `procedure` skill. Does NOT cover `@operation` for OpenAPI beyond auth-related fields → hand off to `openapi` skill. Does NOT cover `@operation.x-tool` for tool derivation → hand off to `tools` skill.

Use cases: data, security, writing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/decorators

What's inside

Skill name
decorators
Description
Vovk.ts decorators — built-in (`@prefix`, `@operation`, `@get/@post/@put/@patch/@del`, `.auto()`) and custom via `createDecorator`. Covers authorization / auth decorators, middleware-style wrapping (pre-handler + post-handler logic), `req.vovk.meta()` for cross-decorator state, stacking order, and the local (`.fn()`) vs HTTP context distinction. Use whenever the user asks to "write a custom decorator", "add auth middleware", "protect an endpoint", "build an authorization decorator", "createDecorator", "stack decorators", "share data between decorator and handler", "prefix all routes", "@auto", "decorator execution order". Does NOT cover procedure authoring → hand off to `procedure` skill. Does NOT cover `@operation` for OpenAPI beyond auth-related fields → hand off to `openapi` skill. Does NOT cover `@operation.x-tool` for tool derivation → hand off to `tools` skill.
License
MIT
Instructions
272 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Vovk.ts decorators

Decorators wrap static methods on controllers. Three kinds:

- **HTTP decorators** (`@get`, `@post`, `@put`, `@patch`, `@del`) — mark procedure as HTTP route. See `procedure` skill.
- **Metadata decorators** (`@prefix`, `@operation`) — attach info, no behavior change.
- **Custom decorators** (`createDecorator`) — middleware wrapping handler. How auth, logging, feature flags attach.

One syntax: `@decorator`. `vovk init` enables `experimentalDecorators` in `tsconfig.json`; a webpack build (`next build --webpack`, Next.js 15's default) needs it, Turbopack (Next.js 16's default) compiles vovk's decorators either way.

## `@prefix`

Class-level route prefix:

```ts
import { prefix, get, procedure } from 'vovk';

@prefix('users')
export default class UserController {
  @get('{id}')
  static getUser = procedure({ /* ... */ }).handle(/* ... */);
}
// → GET /api/users/{id}
```

Root-level — `@prefix('')` or omit (same effect):

```ts
export default class RootController {
  @get()
  static ping = procedure().handle(() => ({ ok: true }));
}
// → GET /api
```

## `.auto()` — name-derived routes

Use method name instead of path:

```ts
@put.auto()
static doSomething = procedure().handle(/* ... */);
// → PUT /api/<prefix>/do-something
```

Method names → kebab-case. Works with every HTTP decorator (`@get.auto()`, `@post.auto()`, etc.), same options.

## HTTP decorator options

Second arg: response-header + CORS config.

```ts
@put('do-something', {
  headers: { 'x-hello': 'world' },
  cors: true,
})
static doSomething = procedure().handle(/* ... */);
```

- `headers` — merged into response.
- `cors: true` — permissive CORS for that route (`access-control-allow-origin: *`, preflight answered). Needs `OPTIONS` in segment's `initSegment()` exports — else Next.js answers the preflight itself (204 with `Allow`, no `Access-Control-*` headers), and the browser blocks the cross-origin call. Exact headers and CORS for every route → **`base`**.

## Custom decorators — `createDecorator`

Middleware-shaped: receive request + `next`, work before/after, return response. `next()` returns the handler's value (after the `output` check) or throws its error (validation errors included). What the decorator returns is the response: a value is sent as JSON with 200, a `Response` as it is — the way to set a status other than 200 or answer errors in another format (recipes in **`base`**).

```ts
import { createDecorator } from 'vovk';

const timingDecorator = createDecorator(async (req, next) => {
  const start = Date.now();
  const response = await next();
  console.log(`[${req.method}] ${req.url} — ${Date.now() - start}ms`);
  return response;
});
```

Stack it with the HTTP decorator (order below):

```ts
@get('{id}')
@timingDecorator()
static getUser = procedure({ /* ... */ }).handle(/* ... */);
```

### Auth decorator pattern

Gate access, pass user state to handler via `req.vovk.meta()`. **Always pass explicit generic to every `meta()` call** — both set + read — and share single type alias across every site touching auth metadata. `meta()`'s generic defaults to `Record<string, any>` → untyped call silently loses inference, sides drift apart.

```ts
// auth.ts — define once, import everywhere the auth decorator is used
import { createDecorator, HttpException, HttpStatus } from 'vovk';
import { headers } from 'next/headers';

export type AuthMeta = { user: User };

export const authGuard = createDecorator(async (req, next) => {
  const token = (await headers()).get('authorization');
  if (!token) {
    throw new HttpException(HttpStatus.UNAUTHORIZED, 'Missing token');
  }
  const user = await parseToken(token); // your auth logic — returns `User | null`
  if (!user) {
    throw new HttpException(HttpStatus.UNAUTHORIZED, 'Invalid or expired token');
  }
  req.vovk.meta<AuthMeta>({ user });
  return next();
});
```

Reading the token via `next/headers` (not `req.headers`) makes the guard work over HTTP and under `.fn()`. See **Local vs HTTP context** below.

Consume in handler — same `AuthMeta`:

```ts
import { authGuard, type AuthMeta } from './auth';

@get('{id}')
@authGuard()

From finom/vovk, MIT.

More from finom/vovk

Signals

Stars
54
Forks
0
Open issues
0
Last commit (this folder)
Oct 13, 2026 (14 days ago)
Last release
Oct 22, 2026 (5 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
Website
vovk.dev
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from finom

Cite this page

decorators skill. Agent Mart. https://agentmart.dev/skills/finom-decorators (last updated 2026-10-24)