|
| 1 | +<!DOCTYPE html> |
| 2 | +<html lang="en"> |
| 3 | + <head> |
| 4 | + <meta charset="UTF-8" /> |
| 5 | + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| 6 | + <title>Decorators | Ingest</title> |
| 7 | + <meta name="description" content="The decorators module adds optional controller-style registration on top of Ingest's existing router APIs. It does not introduce automatic discovery, dependency injection, or a separate execution model." /> |
| 8 | + <link href="../assets/favicon.ico" rel="icon" sizes="any" /> |
| 9 | + <link href="../assets/site.css" rel="stylesheet" /> |
| 10 | + <script defer src="../assets/site.js"></script> |
| 11 | + </head> |
| 12 | + <body class="site-shell"> |
| 13 | + <div class="site-bg" aria-hidden="true"></div> |
| 14 | + <header class="topbar"> |
| 15 | + <a |
| 16 | + class="brand" |
| 17 | + href="../index.html" |
| 18 | + title="Go to the Ingest homepage"> |
| 19 | + <img alt="Ingest" class="brand-mark" src="../assets/ingest.png" /> |
| 20 | + <span class="brand-copy"> |
| 21 | + <strong>Ingest</strong> |
| 22 | + <span>Composable Server/less IO Framework</span> |
| 23 | + </span> |
| 24 | + </a> |
| 25 | + <div class="topbar-actions"> |
| 26 | + <button |
| 27 | + aria-label="Toggle color theme" |
| 28 | + class="theme-toggle" |
| 29 | + id="theme-toggle" |
| 30 | + type="button"> |
| 31 | + <span class="theme-toggle-label">Theme</span> |
| 32 | + </button> |
| 33 | + </div> |
| 34 | + <div class="topbar-meta"> |
| 35 | + <a |
| 36 | + class="repo-link" |
| 37 | + href="https://github.com/stackpress/ingest" |
| 38 | + title="Open the Ingest GitHub repository"> |
| 39 | + GitHub |
| 40 | + </a> |
| 41 | + </div> |
| 42 | + </header> |
| 43 | + <div class="page-grid "> |
| 44 | + <aside class="sidebar"> |
| 45 | + <div class="sidebar-panel"> |
| 46 | + <p class="sidebar-label">Reference Map</p> |
| 47 | + <nav class="sidebar-nav"><section class="nav-group"> |
| 48 | + <p class="nav-group-title">Overview</p> |
| 49 | + <ul class="nav-list"> |
| 50 | + <li> |
| 51 | + <a class="" href="../index.html" title="Home">Home</a> |
| 52 | + </li><li> |
| 53 | + <a class="" href="../overview.html" title="Overview">Overview</a> |
| 54 | + </li><li> |
| 55 | + <a class="" href="../examples.html" title="Examples">Examples</a> |
| 56 | + </li><li> |
| 57 | + <a class="" href="../plugin-development.html" title="Plugin Development">Plugin Development</a> |
| 58 | + </li> |
| 59 | + </ul> |
| 60 | +</section> |
| 61 | + |
| 62 | +<section class="nav-group"> |
| 63 | + <p class="nav-group-title">Concepts</p> |
| 64 | + <ul class="nav-list"> |
| 65 | + <li> |
| 66 | + <a class="" href="../concepts/index.html" title="Concepts">Concepts</a> |
| 67 | + </li><li> |
| 68 | + <a class="" href="../concepts/application-model.html" title="Application Model">Application Model</a> |
| 69 | + </li><li> |
| 70 | + <a class="" href="../concepts/data-surfaces.html" title="Data Surfaces">Data Surfaces</a> |
| 71 | + </li><li> |
| 72 | + <a class="" href="../concepts/request-lifecycle.html" title="Request Lifecycle">Request Lifecycle</a> |
| 73 | + </li><li> |
| 74 | + <a class="" href="../concepts/composition.html" title="Composition">Composition</a> |
| 75 | + </li><li> |
| 76 | + <a class="" href="../concepts/routing-patterns.html" title="Routing Patterns">Routing Patterns</a> |
| 77 | + </li><li> |
| 78 | + <a class="" href="../concepts/runtimes-and-tooling.html" title="Runtimes and Tooling">Runtimes and Tooling</a> |
| 79 | + </li> |
| 80 | + </ul> |
| 81 | +</section> |
| 82 | + |
| 83 | +<section class="nav-group"> |
| 84 | + <p class="nav-group-title">Guides</p> |
| 85 | + <ul class="nav-list"> |
| 86 | + <li> |
| 87 | + <a class="" href="../guides/index.html" title="Guides">Guides</a> |
| 88 | + </li><li> |
| 89 | + <a class="" href="../guides/create-a-server.html" title="Create a Server">Create a Server</a> |
| 90 | + </li><li> |
| 91 | + <a class="" href="../guides/use-decorators.html" title="Use Decorators">Use Decorators</a> |
| 92 | + </li><li> |
| 93 | + <a class="" href="../guides/add-a-plugin.html" title="Add a Plugin">Add a Plugin</a> |
| 94 | + </li><li> |
| 95 | + <a class="" href="../guides/lazy-load-routes.html" title="Lazy Load Routes">Lazy Load Routes</a> |
| 96 | + </li><li> |
| 97 | + <a class="" href="../guides/render-views.html" title="Render Views">Render Views</a> |
| 98 | + </li><li> |
| 99 | + <a class="" href="../guides/deploy.html" title="Deploy an App">Deploy an App</a> |
| 100 | + </li> |
| 101 | + </ul> |
| 102 | +</section> |
| 103 | + |
| 104 | +<section class="nav-group"> |
| 105 | + <p class="nav-group-title">API Reference</p> |
| 106 | + <ul class="nav-list"> |
| 107 | + <li> |
| 108 | + <a class="" href="index.html" title="API Reference">API Reference</a> |
| 109 | + </li><li> |
| 110 | + <a class="is-active" href="Decorators.html" title="Decorators">Decorators</a> |
| 111 | + </li><li> |
| 112 | + <a class="" href="Server.html" title="Server">Server</a> |
| 113 | + </li><li> |
| 114 | + <a class="" href="Router.html" title="Router">Router</a> |
| 115 | + </li><li> |
| 116 | + <a class="" href="Route.html" title="Route">Route</a> |
| 117 | + </li><li> |
| 118 | + <a class="" href="Request.html" title="Request">Request</a> |
| 119 | + </li><li> |
| 120 | + <a class="" href="Response.html" title="Response">Response</a> |
| 121 | + </li><li> |
| 122 | + <a class="" href="Exception.html" title="Exception">Exception</a> |
| 123 | + </li><li> |
| 124 | + <a class="" href="ActionRouter.html" title="ActionRouter">ActionRouter</a> |
| 125 | + </li><li> |
| 126 | + <a class="" href="EntryRouter.html" title="EntryRouter">EntryRouter</a> |
| 127 | + </li><li> |
| 128 | + <a class="" href="ImportRouter.html" title="ImportRouter">ImportRouter</a> |
| 129 | + </li><li> |
| 130 | + <a class="" href="ViewRouter.html" title="ViewRouter">ViewRouter</a> |
| 131 | + </li><li> |
| 132 | + <a class="" href="HttpAdapter.html" title="HttpAdapter">HttpAdapter</a> |
| 133 | + </li><li> |
| 134 | + <a class="" href="WhatwgAdapter.html" title="WhatwgAdapter">WhatwgAdapter</a> |
| 135 | + </li><li> |
| 136 | + <a class="" href="Loader.html" title="Loader">Loader</a> |
| 137 | + </li><li> |
| 138 | + <a class="" href="Nest.html" title="Nest">Nest</a> |
| 139 | + </li><li> |
| 140 | + <a class="" href="ExpressEmitter.html" title="ExpressEmitter">ExpressEmitter</a> |
| 141 | + </li> |
| 142 | + </ul> |
| 143 | +</section> |
| 144 | +</nav> |
| 145 | + </div> |
| 146 | + </aside> |
| 147 | + <main class="content "> |
| 148 | + <section class="hero"> |
| 149 | + <div class="hero-copy"> |
| 150 | + <p class="eyebrow">Reference Layer</p> |
| 151 | + <h1>Decorators</h1> |
| 152 | + <p class="hero-summary">The decorators module adds optional controller-style registration on top of Ingest's existing router APIs. It does not introduce automatic discovery, dependency injection, or a separate execution model.</p> |
| 153 | + <div class="hero-chip-row"> |
| 154 | + <span class="hero-chip">Class Reference</span><span class="hero-chip">Methods, Properties, Examples</span> |
| 155 | +</div> |
| 156 | + |
| 157 | + |
| 158 | + </div> |
| 159 | + </section> |
| 160 | + <section class="toc"> |
| 161 | + <div class="toc-header"> |
| 162 | + <p class="eyebrow">On This Page</p> |
| 163 | + <h2>Structural Map</h2> |
| 164 | + </div> |
| 165 | + <ol class="toc-list"> |
| 166 | + <li><a href="#1-exports" title="1. Exports">1. Exports</a></li><li><a href="#2-controller" title="2. Controller">2. Controller</a></li><li><a href="#3-route-decorators" title="3. Route Decorators">3. Route Decorators</a></li><li><a href="#4-event-decorator" title="4. Event Decorator">4. Event Decorator</a></li><li><a href="#5-mount-helper" title="5. Mount Helper">5. Mount Helper</a></li><li><a href="#6-integration-notes" title="6. Integration Notes">6. Integration Notes</a></li><li><a href="#related-links" title="Related links">Related links</a></li> |
| 167 | + </ol> |
| 168 | +</section> |
| 169 | + |
| 170 | + <article class="doc-frame"><div class="doc-ruler" aria-hidden="true"></div><div class="doc-body markdown"><p>The decorators module adds optional controller-style registration on top of Ingest's existing router APIs. It does not introduce automatic discovery, dependency injection, or a separate execution model.</p> |
| 171 | +<div class="code-shell"><div class="code-toolbar"><span class="code-language">TypeScript</span><button class="copy-button" type="button">copy</button></div><pre class="code-block" data-language="typescript"><code class="language-typescript">import { |
| 172 | + Controller, |
| 173 | + Get, |
| 174 | + On, |
| 175 | + mount |
| 176 | +} from '@stackpress/ingest/http';</code></pre></div> |
| 177 | +<p>You can import the same decorators from:</p> |
| 178 | +<ul><li><code>@stackpress/ingest</code></li><li><code>@stackpress/ingest/http</code></li><li><code>@stackpress/ingest/whatwg</code></li></ul> |
| 179 | +<ol><li><a href="#1-exports" title="Exports">Exports</a></li><li><a href="#2-controller" title="Controller">Controller</a></li><li><a href="#3-route-decorators" title="Route Decorators">Route Decorators</a></li><li><a href="#4-event-decorator" title="Event Decorator">Event Decorator</a></li><li><a href="#5-mount-helper" title="Mount Helper">Mount Helper</a></li><li><a href="#6-integration-notes" title="Integration Notes">Integration Notes</a></li></ol> |
| 180 | +<h2 id="1-exports">1. Exports</h2> |
| 181 | +<p>The decorators module exports:</p> |
| 182 | +<ul><li><code>Controller</code></li><li><code>All</code>, <code>Connect</code>, <code>Delete</code>, <code>Get</code>, <code>Head</code>, <code>Options</code>, <code>Patch</code>, <code>Post</code>, <code>Put</code>, <code>Trace</code></li><li><code>On</code></li><li><code>mount</code></li></ul> |
| 183 | +<h2 id="2-controller">2. Controller</h2> |
| 184 | +<p><code>Controller(basePath?)</code> records a base path on a controller class. Route decorators mounted from that class use the base path as a prefix.</p> |
| 185 | +<div class="code-shell"><div class="code-toolbar"><span class="code-language">TypeScript</span><button class="copy-button" type="button">copy</button></div><pre class="code-block" data-language="typescript"><code class="language-typescript">@Controller('/api') |
| 186 | +class UserController {}</code></pre></div> |
| 187 | +<p><strong>Parameters</strong></p> |
| 188 | +<div class="table-wrap"><table><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>basePath</code></td><td><code>string</code></td><td>Optional path prefix applied to route decorators on the class. Defaults to <code>''</code>.</td></tr></tbody></table></div> |
| 189 | +<p><strong>Returns</strong></p> |
| 190 | +<p>A class decorator.</p> |
| 191 | +<h2 id="3-route-decorators">3. Route Decorators</h2> |
| 192 | +<p>The route decorators register instance methods as router actions for a specific HTTP method.</p> |
| 193 | +<div class="code-shell"><div class="code-toolbar"><span class="code-language">TypeScript</span><button class="copy-button" type="button">copy</button></div><pre class="code-block" data-language="typescript"><code class="language-typescript">import { |
| 194 | + Controller, |
| 195 | + Get, |
| 196 | + Post, |
| 197 | + type HttpAction |
| 198 | +} from '@stackpress/ingest/http'; |
| 199 | + |
| 200 | +type HttpProps = Parameters<HttpAction>[0]; |
| 201 | + |
| 202 | +@Controller('/api') |
| 203 | +class UserController { |
| 204 | + @Get('/users') |
| 205 | + public list({ res }: HttpProps) { |
| 206 | + res.setJSON([{ id: 1 }]); |
| 207 | + } |
| 208 | + |
| 209 | + @Post('/users', 10) |
| 210 | + public create({ res }: HttpProps) { |
| 211 | + res.code = 201; |
| 212 | + } |
| 213 | +}</code></pre></div> |
| 214 | +<p>Supported route decorators:</p> |
| 215 | +<ul><li><code>All(path, priority?)</code></li><li><code>Connect(path, priority?)</code></li><li><code>Delete(path, priority?)</code></li><li><code>Get(path, priority?)</code></li><li><code>Head(path, priority?)</code></li><li><code>Options(path, priority?)</code></li><li><code>Patch(path, priority?)</code></li><li><code>Post(path, priority?)</code></li><li><code>Put(path, priority?)</code></li><li><code>Trace(path, priority?)</code></li></ul> |
| 216 | +<p><strong>Parameters</strong></p> |
| 217 | +<div class="table-wrap"><table><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>path</code></td><td><code>string</code></td><td>Route path segment for the decorated method.</td></tr><tr><td><code>priority</code></td><td><code>number</code></td><td>Optional route priority. Higher numbers run first. Defaults to <code>0</code>.</td></tr></tbody></table></div> |
| 218 | +<p><strong>Returns</strong></p> |
| 219 | +<p>A method decorator.</p> |
| 220 | +<h2 id="4-event-decorator">4. Event Decorator</h2> |
| 221 | +<p><code>On(event, priority?)</code> registers an instance method as a listener on the router event system.</p> |
| 222 | +<div class="code-shell"><div class="code-toolbar"><span class="code-language">TypeScript</span><button class="copy-button" type="button">copy</button></div><pre class="code-block" data-language="typescript"><code class="language-typescript">import { On, type HttpAction } from '@stackpress/ingest/http'; |
| 223 | + |
| 224 | +type HttpProps = Parameters<HttpAction>[0]; |
| 225 | + |
| 226 | +class AuditController { |
| 227 | + @On('GET /api/users', 10) |
| 228 | + public log({ req, res }: HttpProps) { |
| 229 | + res.headers.set('x-path', req.url.pathname); |
| 230 | + } |
| 231 | +}</code></pre></div> |
| 232 | +<p><strong>Parameters</strong></p> |
| 233 | +<div class="table-wrap"><table><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>event</code></td><td>`string \</td><td>RegExp`</td><td>Event name or event pattern to listen for.</td></tr><tr><td><code>priority</code></td><td><code>number</code></td><td>Optional listener priority. Higher numbers run first. Defaults to <code>0</code>.</td></tr></tbody></table></div> |
| 234 | +<p><strong>Returns</strong></p> |
| 235 | +<p>A method decorator.</p> |
| 236 | +<h2 id="5-mount-helper">5. Mount Helper</h2> |
| 237 | +<p><code>mount(router, ...controllers)</code> turns controller metadata into active routes and listeners on a <a href="Router.html" title="Router">Router</a> or <a href="Server.html" title="Server">Server</a>.</p> |
| 238 | +<div class="code-shell"><div class="code-toolbar"><span class="code-language">TypeScript</span><button class="copy-button" type="button">copy</button></div><pre class="code-block" data-language="typescript"><code class="language-typescript">import { |
| 239 | + Controller, |
| 240 | + Get, |
| 241 | + Router, |
| 242 | + mount, |
| 243 | + type HttpAction |
| 244 | +} from '@stackpress/ingest/http'; |
| 245 | + |
| 246 | +type HttpProps = Parameters<HttpAction>[0]; |
| 247 | + |
| 248 | +@Controller('/api') |
| 249 | +class UserController { |
| 250 | + @Get('/users') |
| 251 | + public list({ res }: HttpProps) { |
| 252 | + res.setBody('text/plain', 'list'); |
| 253 | + } |
| 254 | +} |
| 255 | + |
| 256 | +const router = new Router(); |
| 257 | +mount(router, UserController);</code></pre></div> |
| 258 | +<p><strong>Parameters</strong></p> |
| 259 | +<div class="table-wrap"><table><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>router</code></td><td><code>Router<any, any, any, any></code></td><td>Router or Server instance that should receive the registrations.</td></tr><tr><td><code>controllers</code></td><td><code>ControllerMountable[]</code></td><td>Controller classes or controller instances to mount.</td></tr></tbody></table></div> |
| 260 | +<p><strong>Returns</strong></p> |
| 261 | +<p>The same router instance for chaining.</p> |
| 262 | +<h2 id="6-integration-notes">6. Integration Notes</h2> |
| 263 | +<ul><li>Decorators are optional. They only register existing <code>route()</code> and <code>on()</code> calls for you.</li><li>Mounting is explicit. Ingest does not scan files or bootstrap controllers automatically.</li><li><code>ControllerMountable</code> accepts either a controller class or a controller instance.</li><li>Decorated methods should use explicit parameter types when destructuring props because decorators do not provide the same contextual typing as inline callbacks.</li><li>Parameter decorators such as <code>@Body()</code> or <code>@Param()</code> are not part of this feature.</li><li><code>reflect-metadata</code> is not required.</li></ul> |
| 264 | +<h2 id="related-links">Related links</h2> |
| 265 | +<ul><li><a href="../guides/use-decorators.html" title="Use Decorators">Use Decorators</a></li><li><a href="Router.html" title="Router">Router</a></li><li><a href="Server.html" title="Server">Server</a></li></ul></div></article> |
| 266 | + <footer class="footer"> |
| 267 | + <p>By the stackpress team</p> |
| 268 | + <div class="footer-links"> |
| 269 | + <a href="https://stackpress.io" target="_blank" rel="noreferrer">stackpress.io</a> |
| 270 | + <a href="https://github.com/stackpress/ingest" target="_blank" rel="noreferrer">GitHub</a> |
| 271 | + </div> |
| 272 | + </footer> |
| 273 | + </main> |
| 274 | + </div> |
| 275 | + </body> |
| 276 | +</html> |
0 commit comments