@theokit/http 0.5.4 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/LICENSE +201 -0
  2. package/dist/app.d.ts +16 -0
  3. package/dist/app.js +3 -3
  4. package/dist/{chunk-34KOKJ5M.js → chunk-CMPP4ULU.js} +3 -3
  5. package/dist/{chunk-U46H4CGF.js → chunk-ELCXHPAD.js} +2 -2
  6. package/dist/{chunk-NDD7ANXZ.js → chunk-GXTGOPRU.js} +124 -6
  7. package/dist/chunk-GXTGOPRU.js.map +1 -0
  8. package/dist/{chunk-QGB5YC4T.js → chunk-JQMJK47T.js} +31 -4
  9. package/dist/chunk-JQMJK47T.js.map +1 -0
  10. package/dist/{chunk-3PGQVQWG.js → chunk-KPC7AIVC.js} +3 -1
  11. package/dist/chunk-KPC7AIVC.js.map +1 -0
  12. package/dist/{chunk-LKNI6QEP.js → chunk-MQAJWR3K.js} +1 -1
  13. package/dist/chunk-MQAJWR3K.js.map +1 -0
  14. package/dist/chunk-OBHHOS6E.js +257 -0
  15. package/dist/chunk-OBHHOS6E.js.map +1 -0
  16. package/dist/exception-filter-chain-V2MFO4WV.js +10 -0
  17. package/dist/index.d.ts +343 -8
  18. package/dist/index.js +230 -23
  19. package/dist/index.js.map +1 -1
  20. package/dist/interceptor-chain-ELSL6KZT.js +9 -0
  21. package/dist/{middleware-consumer-ljxK1fU_.d.ts → middleware-consumer-DcaksawH.d.ts} +1 -1
  22. package/dist/theokit-plugin.d.ts +1 -1
  23. package/dist/theokit-plugin.js +7 -167
  24. package/dist/theokit-plugin.js.map +1 -1
  25. package/package.json +19 -17
  26. package/dist/chunk-3PGQVQWG.js.map +0 -1
  27. package/dist/chunk-LKNI6QEP.js.map +0 -1
  28. package/dist/chunk-LWCNTZN6.js +0 -87
  29. package/dist/chunk-LWCNTZN6.js.map +0 -1
  30. package/dist/chunk-NDD7ANXZ.js.map +0 -1
  31. package/dist/chunk-QGB5YC4T.js.map +0 -1
  32. package/dist/exception-filter-chain-BCSQ3MZ2.js +0 -10
  33. package/dist/interceptor-chain-6S3PUV7J.js +0 -9
  34. /package/dist/{chunk-34KOKJ5M.js.map → chunk-CMPP4ULU.js.map} +0 -0
  35. /package/dist/{chunk-U46H4CGF.js.map → chunk-ELCXHPAD.js.map} +0 -0
  36. /package/dist/{exception-filter-chain-BCSQ3MZ2.js.map → exception-filter-chain-V2MFO4WV.js.map} +0 -0
  37. /package/dist/{interceptor-chain-6S3PUV7J.js.map → interceptor-chain-ELSL6KZT.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { z } from 'zod';
2
- import { D as DiContainer, M as MiddlewareConsumerImpl } from './middleware-consumer-ljxK1fU_.js';
3
- export { a as MiddlewareConfigProxy, b as MiddlewareFn, N as NestMiddleware, R as ResolvedMiddleware, m as middlewareMatchesPath, r as resolveOrNew, c as runMiddleware } from './middleware-consumer-ljxK1fU_.js';
2
+ import { D as DiContainer, M as MiddlewareConsumerImpl } from './middleware-consumer-DcaksawH.js';
3
+ export { a as MiddlewareConfigProxy, b as MiddlewareFn, N as NestMiddleware, R as ResolvedMiddleware, m as middlewareMatchesPath, r as resolveOrNew, c as runMiddleware } from './middleware-consumer-DcaksawH.js';
4
4
  import { S as ServerHandle } from './types-CGthbcon.js';
5
5
  export { ReadinessCheck, TheoApp, TheoAppOptions } from './app.js';
6
+ import * as ReactTypes from 'react';
6
7
 
7
8
  interface ControllerOptions {
8
9
  host?: string;
@@ -69,6 +70,50 @@ declare function Res(opts?: {
69
70
  passthrough?: boolean;
70
71
  }): ParameterDecorator;
71
72
 
73
+ /**
74
+ * M47 (ADR-M47-1) — `@Expose(agent, opts?)` binds a SEPARATELY-BUILT agent (a pure `agent()…build()` from
75
+ * `agents/<name>.ts`) to a controller PROPERTY, making the exposure (route, auth via `@UseGuards`, streaming)
76
+ * visible in one code review. It mirrors the #122 verb decorators (`@Post`) — storing metadata via the same
77
+ * `Symbol.for()` seam — but records the agent instead of an HTTP verb, so the controller walker turns the
78
+ * property into an agent-serving route (`POST <prefix>/<property>`) delegated to the ONE runtime
79
+ * (`mountAgent`), never a JSON handler. It is a new AUTHORING surface over the existing runtime, not a
80
+ * parallel runtime (G2). CSRF is enforced once at the controller-dispatch boundary. Interceptors do NOT run
81
+ * for agent routes (the dispatcher delegates straight to `mountAgent`); guards DO (G5). The served path is
82
+ * the controller prefix + property name — keep it equal to the agent's convention route (`/api/agents/<name>`
83
+ * for a property named `<name>` under `@Controller('api/agents')`) so the generated `useAgent(handle)` path
84
+ * lines up.
85
+ */
86
+ /**
87
+ * Per-binding options for an exposed agent. Reserved for forward-compat — no options are wired yet.
88
+ *
89
+ * Two candidate fields were removed before shipping (M47 review): `path` (a route override) would let the
90
+ * served URL diverge from the generated handle's path — the codegen derives the handle from the agent's
91
+ * convention route (`/api/agents/<name>`), so an overridden route would make `useAgent(handle)` hit the
92
+ * wrong URL. And `csrf` was a no-op — CSRF is enforced exactly once at the controller-dispatch boundary
93
+ * regardless. Both return only when they can be wired end-to-end (codegen reads `@Expose` metadata / a
94
+ * per-route CSRF opt-out threads through the dispatcher). Until then, `@Expose(agent)` is the shape, and the
95
+ * exposure's path MUST be the convention route — put `@Expose` on a property named after the agent under
96
+ * `@Controller('api/agents')` (e.g. `chat` for `agents/chat.ts` → `/api/agents/chat`).
97
+ */
98
+ type ExposeOptions = Record<string, never>;
99
+ /** Metadata recorded per `@Expose`-decorated controller member. */
100
+ interface ExposeEntry {
101
+ /** The separately-built agent module bound to this member. */
102
+ agent: unknown;
103
+ /** The per-binding options (defaulted to `{}`). */
104
+ opts: ExposeOptions;
105
+ /** The controller member the binding is attached to. */
106
+ propertyKey: string | symbol;
107
+ }
108
+ /**
109
+ * Bind an agent to a controller PROPERTY. Accumulates one {@link ExposeEntry} per member under the
110
+ * `EXPOSE_AGENT` metadata key on the controller constructor — the same accumulation shape `@Post` uses for
111
+ * `ROUTE_METHODS`, so `walkControllerMetadata` reads both alongside each other. Typed as `PropertyDecorator`
112
+ * (the exposure is declared as a property, e.g. `@Expose(chatAgent) chat!: typeof chatAgent`); the agent's
113
+ * behavior lives in its own `agents/<name>.ts`, never in a controller method body.
114
+ */
115
+ declare function Expose(agent: unknown, opts?: ExposeOptions): PropertyDecorator;
116
+
72
117
  declare function HttpCode(status: number): MethodDecorator;
73
118
  declare function Header(name: string, value: string): MethodDecorator;
74
119
  interface RedirectMeta {
@@ -77,7 +122,7 @@ interface RedirectMeta {
77
122
  }
78
123
  declare function Redirect(url: string, status?: number): MethodDecorator;
79
124
 
80
- declare function UseGuards(...guards: Function[]): ClassDecorator & MethodDecorator;
125
+ declare function UseGuards(...guards: Function[]): ClassDecorator & MethodDecorator & PropertyDecorator;
81
126
  declare function UseInterceptors(...interceptors: Function[]): ClassDecorator & MethodDecorator;
82
127
  declare function UseFilters(...filters: Function[]): ClassDecorator & MethodDecorator;
83
128
  /** @Catch(ExceptionType, ...) — marks which exception types an ExceptionFilter handles.
@@ -222,6 +267,7 @@ declare const USE_GUARDS: unique symbol;
222
267
  declare const USE_INTERCEPTORS: unique symbol;
223
268
  declare const USE_FILTERS: unique symbol;
224
269
  declare const CATCH_EXCEPTIONS: unique symbol;
270
+ declare const EXPOSE_AGENT: unique symbol;
225
271
 
226
272
  /**
227
273
  * Typed facade over Reflect.defineMetadata / Reflect.getMetadata.
@@ -342,6 +388,14 @@ interface WalkResult {
342
388
  guards: Function[];
343
389
  interceptors: Function[];
344
390
  filters: Function[];
391
+ /**
392
+ * M47 — set when the member is bound via `@Expose(agent, opts)`. The dispatcher delegates such routes to
393
+ * the agent runtime (`mountAgent`) instead of invoking a JSON handler. `undefined` for normal verb routes.
394
+ */
395
+ agent?: {
396
+ module: unknown;
397
+ opts: ExposeOptions;
398
+ };
345
399
  }
346
400
  /**
347
401
  * Normalize a joined path: strip doubles, trim trailing, ensure leading.
@@ -354,6 +408,63 @@ declare function joinPath(prefix: string, path: string): string;
354
408
  */
355
409
  declare function walkControllerMetadata(ControllerClass: Function): WalkResult[];
356
410
 
411
+ /**
412
+ * SWC-powered module loader for controller files with parameter decorators.
413
+ *
414
+ * esbuild (used by tsx/Vite SSR) fundamentally cannot parse TypeScript
415
+ * parameter decorators (`@Body()`, `@Param()`, `@Query()`). This loader
416
+ * uses @swc/core to transform controller files with full decorator support
417
+ * (legacyDecorator + decoratorMetadata), then imports them via a temp .mjs
418
+ * file written in the SAME directory (preserving relative import resolution).
419
+ *
420
+ * Pattern: follows Next.js's approach (read tsconfig → configure SWC)
421
+ * but scoped to the http-decorators package, not the framework core.
422
+ *
423
+ * @see references/next.js/packages/next/src/build/swc/options.ts
424
+ */
425
+
426
+ interface SwcCore {
427
+ transformSync: (src: string, opts: unknown) => {
428
+ code: string;
429
+ };
430
+ }
431
+ /**
432
+ * Transform TypeScript controller SOURCE (with parameter decorators) into
433
+ * ESM code, emitting the `design:paramtypes` / decorator metadata that esbuild
434
+ * cannot produce. Pure code→code — no file I/O, no module load — so it is
435
+ * reusable both by {@link loadControllerWithSwc} (which then temp-writes +
436
+ * imports) and by a build-tool transform hook that returns `{ code }` directly.
437
+ *
438
+ * The `@swc/core` loader is injectable (`loadSwc`) for testability; it defaults
439
+ * to the cached singleton.
440
+ *
441
+ * @throws HttpDecoratorsConfigError when @swc/core is unavailable.
442
+ */
443
+ declare function transformControllerSource(source: string, filename: string, loadSwc?: () => Promise<SwcCore | null>): Promise<string>;
444
+ /**
445
+ * Load a TypeScript controller file using @swc/core for decorator support.
446
+ *
447
+ * Strategy:
448
+ * 1. Read source .ts file
449
+ * 2. Transform via {@link transformControllerSource} (legacyDecorator + metadata)
450
+ * 3. Write temp .mjs in SAME directory (relative imports resolve correctly)
451
+ * 4. Dynamic import() the .mjs — transitive .ts imports go through
452
+ * tsx/Vite's global hook (they don't have parameter decorators)
453
+ * 5. Cleanup temp file
454
+ */
455
+ declare function loadControllerWithSwc(absoluteFilePath: string): Promise<Record<string, unknown>>;
456
+ /**
457
+ * Scan a glob pattern for controller files and load them all via SWC.
458
+ * Returns an array of controller class constructors found.
459
+ */
460
+ declare function loadControllersFromGlob(rootDir: string, pattern: string): Promise<Function[]>;
461
+ /**
462
+ * Check if a function has @Controller metadata.
463
+ * Uses Symbol.for() global registry key — same Symbol instance across
464
+ * module boundaries (SWC-loaded controllers share the global registry).
465
+ */
466
+ declare function isControllerClass(fn: Function): boolean;
467
+
357
468
  interface RouteRegistration {
358
469
  verb: HttpVerb;
359
470
  fullPath: string;
@@ -369,14 +480,40 @@ interface RouteRegistration {
369
480
  declare function registerControllers(controllers: Function[]): RouteRegistration[];
370
481
 
371
482
  /**
372
- * Creates a real HTTP server from decorated controller classes.
373
- * Uses Web Standard Request/Response internally; Node adapter at the boundary.
483
+ * M47 serves an `@Expose`-bound agent route. http is agent-runtime agnostic (G1/G2): it invokes this
484
+ * injected callback (theo supplies a `mountAgent`-backed impl) instead of calling a controller method.
374
485
  */
486
+ type ServeAgent = (agent: unknown, request: Request, opts: ExposeOptions) => Promise<Response>;
375
487
  interface CreateDecoratorServerOptions {
376
488
  controllers: Function[];
377
489
  container?: DiContainer;
378
490
  configure?: (consumer: MiddlewareConsumerImpl) => void;
491
+ /** M47 — required when any controller `@Expose`-binds an agent; serves the agent route. */
492
+ serveAgent?: ServeAgent;
493
+ }
494
+ /**
495
+ * A pure Web-Standard controller handler: callable as `(request) => Response | null`
496
+ * plus a non-executing `matches(method, pathname)` route probe (so a host can gate
497
+ * — e.g. CSRF — before dispatch runs a handler).
498
+ */
499
+ interface DecoratorHandler {
500
+ (request: Request): Promise<Response | null>;
501
+ /** True when a controller route owns `method` + `pathname` (no handler executed). */
502
+ matches(method: string, pathname: string): boolean;
379
503
  }
504
+ /**
505
+ * Build a pure Web-Standard request handler from decorated controller classes,
506
+ * WITHOUT binding a network listener. Returns a {@link DecoratorHandler} whose
507
+ * call returns `null` when no controller route matched — the caller decides the
508
+ * miss (a standalone server answers 404; a host middleware falls through to its
509
+ * own routing). This is the reusable dispatch seam consumed by the framework's
510
+ * controller dispatch (#122) so it never re-implements match/bind/validate.
511
+ */
512
+ declare function createDecoratorHandler(controllersOrOpts: Function[] | CreateDecoratorServerOptions): DecoratorHandler;
513
+ /**
514
+ * Creates a real HTTP server from decorated controller classes.
515
+ * Uses Web Standard Request/Response internally; Node adapter at the boundary.
516
+ */
380
517
  declare function createDecoratorServer(controllersOrOpts: Function[] | CreateDecoratorServerOptions): ServerHandle;
381
518
 
382
519
  /**
@@ -998,10 +1135,10 @@ type InferResponse<D> = D extends {
998
1135
  response: infer R;
999
1136
  } ? R : unknown;
1000
1137
  interface TypedClient<M extends RouteMap> {
1001
- get<P extends string & keyof M>(path: P, opts?: {
1138
+ get<P extends string>(path: P, opts?: {
1002
1139
  query?: Record<string, string>;
1003
1140
  headers?: Record<string, string>;
1004
- }): Promise<InferResponse<M[`GET ${P}`] extends never ? M[P] : M[`GET ${P}`]>>;
1141
+ }): Promise<InferResponse<M[`GET ${P}`]>>;
1005
1142
  post<P extends string>(path: P, body?: InferBody<M[`POST ${P}`]>, opts?: {
1006
1143
  headers?: Record<string, string>;
1007
1144
  }): Promise<InferResponse<M[`POST ${P}`]>>;
@@ -1091,4 +1228,202 @@ declare function isSafePath(pathname: string): boolean;
1091
1228
  */
1092
1229
  declare function createStaticHandler(options?: StaticOptions): (request: Request) => Promise<Response | null>;
1093
1230
 
1094
- export { All, type ArgumentsHost, BadGatewayException, BadRequestException, Body, CATCH_EXCEPTIONS, CONTROLLER_PREFIX, type CanActivate, Catch, ConflictException, Controller, type ControllerMeta, type ControllerOptions, Delete, DiContainer, type ExceptionFilter, type ExecutionContext, ForbiddenException, GatewayTimeoutException, Get, GoneException, Head, Header, Headers, HostParam, HttpCode, HttpDecoratorsConfigError, HttpException, type HttpExceptionOptions, HttpStatus, type HttpStatusCode, type HttpVerb, HttpVersionNotSupportedException, ImATeapotException, type Interceptor, InternalServerErrorException, Ip, type MetadataKey, MethodNotAllowedException, MiddlewareConsumerImpl, NotAcceptableException, NotFoundException, NotImplementedException, Options, Param, type ParamEntry, type ParamSource, Patch, PayloadTooLargeException, Post, PreconditionFailedException, Put, Query, ROUTE_HEADERS, ROUTE_METHODS, ROUTE_PARAMS, ROUTE_REDIRECT, ROUTE_STATUS, Redirect, type RedirectMeta, Reflector, Req, RequestTimeoutException, Res, type RouteDefinition, type RouteMap, type RouteMethodEntry, type RouteRegistration, ServiceUnavailableException, Session, SetMetadata, SkipThrottle, type StaticOptions, Throttle, type ThrottleOptions, TooManyRequestsException, type TypedClient, TypedClientError, USE_FILTERS, USE_GUARDS, USE_INTERCEPTORS, UnauthorizedException, UnprocessableEntityException, UnsupportedMediaTypeException, UseFilters, UseGuards, UseInterceptors, type WalkResult, contract, createDecorator, createDecoratorServer, createExecutionContext, createStaticHandler, createTypedClient, getMeta, getMimeType, getThrottleOptions, isSafePath, isThrottleSkipped, joinPath, registerControllers, resolveDtoSchema, runExceptionFilters, runInterceptors, setMeta, walkControllerMetadata };
1231
+ interface TheoRequestContext {
1232
+ /** The raw Web Standard Request object. */
1233
+ request: Request;
1234
+ /** URL pathname (e.g., '/api/tasks'). */
1235
+ pathname: string;
1236
+ /** HTTP method (e.g., 'GET', 'POST'). */
1237
+ method: string;
1238
+ /** Route params extracted from URL (e.g., { id: '42' }). */
1239
+ params: Record<string, string>;
1240
+ /** Matched controller or agent class name (if resolved). */
1241
+ handler?: string;
1242
+ /** Request start time (ms). */
1243
+ startedAt: number;
1244
+ }
1245
+ /**
1246
+ * Get the current request context.
1247
+ *
1248
+ * @throws Error if called outside a request (e.g., at module load time).
1249
+ *
1250
+ * @example
1251
+ * ```typescript
1252
+ * import { getRequestContext } from '@theokit/http'
1253
+ *
1254
+ * class AuthGuard {
1255
+ * canActivate() {
1256
+ * const { request } = getRequestContext()
1257
+ * return request.headers.get('authorization') !== null
1258
+ * }
1259
+ * }
1260
+ * ```
1261
+ */
1262
+ declare function getRequestContext(): TheoRequestContext;
1263
+ /**
1264
+ * Try to get the current request context, or null if not in a request.
1265
+ * Useful for code that may run both inside and outside requests.
1266
+ */
1267
+ declare function tryGetRequestContext(): TheoRequestContext | null;
1268
+
1269
+ /**
1270
+ * Error digestion — converts any thrown value into a stable hash + context.
1271
+ *
1272
+ * Inspired by Next.js `create-error-handler.tsx`. Produces a deterministic
1273
+ * digest ID suitable for logging and client-safe error references without
1274
+ * leaking stack traces in production.
1275
+ *
1276
+ * Uses djb2 hash (sync, no crypto dependency) per ADR D3.
1277
+ */
1278
+ interface ErrorContext {
1279
+ route?: string;
1280
+ phase?: 'guard' | 'interceptor' | 'handler' | 'filter' | 'agent';
1281
+ source?: string;
1282
+ }
1283
+ interface DigestedError {
1284
+ digest: string;
1285
+ message: string;
1286
+ status: number;
1287
+ context: ErrorContext;
1288
+ stack?: string;
1289
+ }
1290
+ /**
1291
+ * Converts any thrown value into a structured {@link DigestedError}.
1292
+ *
1293
+ * - Sync (never async) — safe to call inside catch blocks.
1294
+ * - Stack trace stripped when `process.env.NODE_ENV === 'production'`.
1295
+ * - Preserves {@link HttpException} status codes.
1296
+ * - Handles non-Error throws (string, number, object).
1297
+ */
1298
+ declare function digestError(err: unknown, context?: ErrorContext): DigestedError;
1299
+
1300
+ /**
1301
+ * Component tree composition — recursive wrapping of file-convention
1302
+ * components (layout, page, loading, error, not-found) into a React
1303
+ * element tree with Suspense and error boundaries.
1304
+ *
1305
+ * Inspired by Next.js `create-component-tree.tsx`.
1306
+ *
1307
+ * React is loaded via dynamic `import('react')` because it is an
1308
+ * optional peerDep of @theokit/http (EC-2).
1309
+ */
1310
+
1311
+ interface RouteTree {
1312
+ layout?: ReactTypes.ComponentType<{
1313
+ children: ReactTypes.ReactNode;
1314
+ }>;
1315
+ page?: ReactTypes.ComponentType;
1316
+ loading?: ReactTypes.ComponentType;
1317
+ error?: ReactTypes.ComponentType;
1318
+ notFound?: ReactTypes.ComponentType;
1319
+ children?: Record<string, RouteTree>;
1320
+ }
1321
+ /**
1322
+ * Composes a {@link RouteTree} into a nested React element tree.
1323
+ *
1324
+ * Wrapping order (outermost → innermost):
1325
+ * layout → ErrorBoundary(error) → Suspense(loading) → page
1326
+ *
1327
+ * Returns `null` when no `page` component is found in the tree.
1328
+ *
1329
+ * @param tree - The route tree describing file conventions found.
1330
+ * @returns A React element or `null`.
1331
+ */
1332
+ declare function composeComponentTree(tree: RouteTree): Promise<ReactTypes.ReactElement | null>;
1333
+
1334
+ /**
1335
+ * Streaming SSR — renders a React element tree to a `ReadableStream<Uint8Array>`.
1336
+ *
1337
+ * Inspired by Next.js `stream-ops.ts`. Uses Web Standard `renderToReadableStream`
1338
+ * (works on Node 18+, Bun, Deno). Falls back to `renderToString` wrapped in a
1339
+ * ReadableStream when `renderToReadableStream` is not available (React 17 — EC-4).
1340
+ *
1341
+ * React is loaded via dynamic `import('react-dom/server')` because react-dom
1342
+ * is an optional peerDep of @theokit/http (ADR D2).
1343
+ */
1344
+
1345
+ interface StreamRenderOptions {
1346
+ /** React element to render */
1347
+ root: ReactTypes.ReactElement;
1348
+ /** Whether to wait for all Suspense to resolve (default: false — stream immediately) */
1349
+ waitForAll?: boolean;
1350
+ }
1351
+ interface StreamRenderResult {
1352
+ /** The HTML stream */
1353
+ stream: ReadableStream<Uint8Array>;
1354
+ /** Promise that resolves when all content has been flushed */
1355
+ allReady: Promise<void>;
1356
+ }
1357
+ /**
1358
+ * Renders a React element to a `ReadableStream<Uint8Array>` (Web Standard).
1359
+ *
1360
+ * 1. Tries `renderToReadableStream` first (React 18+ — Web Standard API).
1361
+ * 2. Falls back to `renderToString` wrapped in a ReadableStream when
1362
+ * `renderToReadableStream` is not available (React 17 compat — EC-4).
1363
+ * 3. Prepends `<!DOCTYPE html>` to the stream.
1364
+ *
1365
+ * **EC-7 — Streaming error handling:** In streaming mode, errors thrown inside
1366
+ * Suspense boundaries are caught by React's streaming error handler and result
1367
+ * in a client-side error boundary activation (the shell is already sent). In
1368
+ * string mode (`renderToString`), errors throw synchronously before any bytes
1369
+ * are sent, allowing a full 500 error page. Choose streaming when you want
1370
+ * progressive rendering; choose string mode when you want atomic error handling.
1371
+ */
1372
+ declare function renderToStream(options: StreamRenderOptions): Promise<StreamRenderResult>;
1373
+ /**
1374
+ * Converts a {@link StreamRenderResult} into a Web Standard `Response`.
1375
+ *
1376
+ * Convenience wrapper for use in request handlers:
1377
+ * ```ts
1378
+ * const result = await renderToStream({ root: <App /> })
1379
+ * return streamToResponse(result)
1380
+ * ```
1381
+ */
1382
+ declare function streamToResponse(result: StreamRenderResult): Response;
1383
+
1384
+ interface RevalidationSignal {
1385
+ kind: 'tag' | 'path';
1386
+ value: string;
1387
+ timestamp: number;
1388
+ }
1389
+ /**
1390
+ * Signal that a cache tag should be revalidated.
1391
+ *
1392
+ * Safe to call from any request handler (controller, agent, action).
1393
+ * Signals are accumulated per-request and consumed by the cache engine.
1394
+ *
1395
+ * @example
1396
+ * ```typescript
1397
+ * import { revalidateTag } from '@theokit/http'
1398
+ *
1399
+ * @Post()
1400
+ * async createTask(@Body(schema) body) {
1401
+ * const task = await db.tasks.create(body)
1402
+ * revalidateTag('tasks') // invalidate cached task lists
1403
+ * return task
1404
+ * }
1405
+ * ```
1406
+ */
1407
+ declare function revalidateTag(tag: string): void;
1408
+ /**
1409
+ * Signal that a cached path should be revalidated.
1410
+ *
1411
+ * @example
1412
+ * ```typescript
1413
+ * import { revalidatePath } from '@theokit/http'
1414
+ *
1415
+ * @Delete(':id')
1416
+ * async removeTask(@Param('id') id: string) {
1417
+ * await db.tasks.delete(id)
1418
+ * revalidatePath('/api/tasks')
1419
+ * }
1420
+ * ```
1421
+ */
1422
+ declare function revalidatePath(path: string): void;
1423
+ /**
1424
+ * Get all revalidation signals collected during the current request.
1425
+ * Called by the cache engine after the handler completes.
1426
+ */
1427
+ declare function getRevalidationSignals(): RevalidationSignal[];
1428
+
1429
+ export { All, type ArgumentsHost, BadGatewayException, BadRequestException, Body, CATCH_EXCEPTIONS, CONTROLLER_PREFIX, type CanActivate, Catch, ConflictException, Controller, type ControllerMeta, type ControllerOptions, type CreateDecoratorServerOptions, type DecoratorHandler, Delete, DiContainer, type DigestedError, EXPOSE_AGENT, type ErrorContext, type ExceptionFilter, type ExecutionContext, Expose, type ExposeEntry, type ExposeOptions, ForbiddenException, GatewayTimeoutException, Get, GoneException, Head, Header, Headers, HostParam, HttpCode, HttpDecoratorsConfigError, HttpException, type HttpExceptionOptions, HttpStatus, type HttpStatusCode, type HttpVerb, HttpVersionNotSupportedException, ImATeapotException, type Interceptor, InternalServerErrorException, Ip, type MetadataKey, MethodNotAllowedException, MiddlewareConsumerImpl, NotAcceptableException, NotFoundException, NotImplementedException, Options, Param, type ParamEntry, type ParamSource, Patch, PayloadTooLargeException, Post, PreconditionFailedException, Put, Query, ROUTE_HEADERS, ROUTE_METHODS, ROUTE_PARAMS, ROUTE_REDIRECT, ROUTE_STATUS, Redirect, type RedirectMeta, Reflector, Req, RequestTimeoutException, Res, type RevalidationSignal, type RouteDefinition, type RouteMap, type RouteMethodEntry, type RouteRegistration, type RouteTree, type ServeAgent, ServiceUnavailableException, Session, SetMetadata, SkipThrottle, type StaticOptions, type StreamRenderOptions, type StreamRenderResult, type SwcCore, type TheoRequestContext, Throttle, type ThrottleOptions, TooManyRequestsException, type TypedClient, TypedClientError, USE_FILTERS, USE_GUARDS, USE_INTERCEPTORS, UnauthorizedException, UnprocessableEntityException, UnsupportedMediaTypeException, UseFilters, UseGuards, UseInterceptors, type WalkResult, composeComponentTree, contract, createDecorator, createDecoratorHandler, createDecoratorServer, createExecutionContext, createStaticHandler, createTypedClient, digestError, getMeta, getMimeType, getRequestContext, getRevalidationSignals, getThrottleOptions, isControllerClass, isSafePath, isThrottleSkipped, joinPath, loadControllerWithSwc, loadControllersFromGlob, registerControllers, renderToStream, resolveDtoSchema, revalidatePath, revalidateTag, runExceptionFilters, runInterceptors, setMeta, streamToResponse, transformControllerSource, tryGetRequestContext, walkControllerMetadata };