@theokit/http 0.5.0 → 0.5.2
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.
- package/dist/app.d.ts +3 -0
- package/dist/app.js +1 -1
- package/dist/{chunk-AHG3RGIP.js → chunk-6LKZR4NZ.js} +191 -1
- package/dist/chunk-6LKZR4NZ.js.map +1 -0
- package/dist/index.d.ts +33 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-AHG3RGIP.js.map +0 -1
package/dist/app.d.ts
CHANGED
|
@@ -29,6 +29,8 @@ interface TheoAppOptions {
|
|
|
29
29
|
agentStreamFactory?: (walk: unknown, tools: unknown[], apiKey: string, model?: string) => (message: string, sessionId: string) => AsyncIterable<unknown>;
|
|
30
30
|
/** HTML string to serve at GET / (inline frontend). */
|
|
31
31
|
html?: string;
|
|
32
|
+
/** Directory for static file serving (default: 'public', false to disable). */
|
|
33
|
+
staticDir?: string | false;
|
|
32
34
|
/** Readiness checks for GET /__theo/ready (K8s readiness probe). */
|
|
33
35
|
readinessChecks?: ReadinessCheck[];
|
|
34
36
|
/** Custom health endpoint path (default: '/__theo/health'). */
|
|
@@ -40,6 +42,7 @@ declare class TheoApp {
|
|
|
40
42
|
private serverHandle;
|
|
41
43
|
private readonly routes;
|
|
42
44
|
private frontendHtml?;
|
|
45
|
+
private staticHandler?;
|
|
43
46
|
private readonly startTime;
|
|
44
47
|
private readonly healthPath;
|
|
45
48
|
private readonly readyPath;
|
package/dist/app.js
CHANGED
|
@@ -15,6 +15,183 @@ import {
|
|
|
15
15
|
|
|
16
16
|
// src/app.ts
|
|
17
17
|
import "reflect-metadata";
|
|
18
|
+
|
|
19
|
+
// src/static.ts
|
|
20
|
+
var MIME_TYPES = {
|
|
21
|
+
// Text
|
|
22
|
+
".html": "text/html; charset=utf-8",
|
|
23
|
+
".htm": "text/html; charset=utf-8",
|
|
24
|
+
".css": "text/css; charset=utf-8",
|
|
25
|
+
".js": "text/javascript; charset=utf-8",
|
|
26
|
+
".mjs": "text/javascript; charset=utf-8",
|
|
27
|
+
".json": "application/json; charset=utf-8",
|
|
28
|
+
".xml": "application/xml; charset=utf-8",
|
|
29
|
+
".txt": "text/plain; charset=utf-8",
|
|
30
|
+
".csv": "text/csv; charset=utf-8",
|
|
31
|
+
".md": "text/markdown; charset=utf-8",
|
|
32
|
+
".yaml": "text/yaml; charset=utf-8",
|
|
33
|
+
".yml": "text/yaml; charset=utf-8",
|
|
34
|
+
".ts": "text/typescript; charset=utf-8",
|
|
35
|
+
".tsx": "text/tsx; charset=utf-8",
|
|
36
|
+
".jsx": "text/jsx; charset=utf-8",
|
|
37
|
+
// Images
|
|
38
|
+
".png": "image/png",
|
|
39
|
+
".jpg": "image/jpeg",
|
|
40
|
+
".jpeg": "image/jpeg",
|
|
41
|
+
".gif": "image/gif",
|
|
42
|
+
".svg": "image/svg+xml",
|
|
43
|
+
".ico": "image/x-icon",
|
|
44
|
+
".webp": "image/webp",
|
|
45
|
+
".avif": "image/avif",
|
|
46
|
+
".bmp": "image/bmp",
|
|
47
|
+
".tiff": "image/tiff",
|
|
48
|
+
".tif": "image/tiff",
|
|
49
|
+
// Fonts
|
|
50
|
+
".woff": "font/woff",
|
|
51
|
+
".woff2": "font/woff2",
|
|
52
|
+
".ttf": "font/ttf",
|
|
53
|
+
".otf": "font/otf",
|
|
54
|
+
".eot": "application/vnd.ms-fontobject",
|
|
55
|
+
// Media
|
|
56
|
+
".mp3": "audio/mpeg",
|
|
57
|
+
".wav": "audio/wav",
|
|
58
|
+
".ogg": "audio/ogg",
|
|
59
|
+
".mp4": "video/mp4",
|
|
60
|
+
".webm": "video/webm",
|
|
61
|
+
".avi": "video/x-msvideo",
|
|
62
|
+
// Documents
|
|
63
|
+
".pdf": "application/pdf",
|
|
64
|
+
".zip": "application/zip",
|
|
65
|
+
".gz": "application/gzip",
|
|
66
|
+
".tar": "application/x-tar",
|
|
67
|
+
".wasm": "application/wasm",
|
|
68
|
+
// Misc
|
|
69
|
+
".map": "application/json; charset=utf-8",
|
|
70
|
+
".jsonld": "application/ld+json; charset=utf-8",
|
|
71
|
+
".manifest": "application/manifest+json; charset=utf-8",
|
|
72
|
+
".webmanifest": "application/manifest+json; charset=utf-8"
|
|
73
|
+
};
|
|
74
|
+
var UNSAFE_PATH_RE = /(?:^|[/\\])\.{1,2}(?:$|[/\\])|[/\\]{2,}/;
|
|
75
|
+
function getMimeType(filePath) {
|
|
76
|
+
const dot = filePath.lastIndexOf(".");
|
|
77
|
+
if (dot === -1) return "application/octet-stream";
|
|
78
|
+
const ext = filePath.slice(dot).toLowerCase();
|
|
79
|
+
return MIME_TYPES[ext] ?? "application/octet-stream";
|
|
80
|
+
}
|
|
81
|
+
__name(getMimeType, "getMimeType");
|
|
82
|
+
function isSafePath(pathname) {
|
|
83
|
+
return !UNSAFE_PATH_RE.test(pathname);
|
|
84
|
+
}
|
|
85
|
+
__name(isSafePath, "isSafePath");
|
|
86
|
+
async function readFileBun(fullPath) {
|
|
87
|
+
const g = globalThis;
|
|
88
|
+
const BunRT = g.Bun;
|
|
89
|
+
const file = BunRT.file(fullPath);
|
|
90
|
+
if (!await file.exists()) return null;
|
|
91
|
+
const buf = await file.arrayBuffer();
|
|
92
|
+
return {
|
|
93
|
+
content: new Uint8Array(buf),
|
|
94
|
+
size: file.size
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
__name(readFileBun, "readFileBun");
|
|
98
|
+
async function readFileDeno(fullPath) {
|
|
99
|
+
const g = globalThis;
|
|
100
|
+
const DenoRT = g.Deno;
|
|
101
|
+
try {
|
|
102
|
+
const stat = await DenoRT.stat(fullPath);
|
|
103
|
+
if (stat.isDirectory) return null;
|
|
104
|
+
const content = await DenoRT.readFile(fullPath);
|
|
105
|
+
return {
|
|
106
|
+
content,
|
|
107
|
+
size: content.byteLength
|
|
108
|
+
};
|
|
109
|
+
} catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
__name(readFileDeno, "readFileDeno");
|
|
114
|
+
async function readFileNode(fullPath) {
|
|
115
|
+
try {
|
|
116
|
+
const fs = await import("fs/promises");
|
|
117
|
+
const stat = await fs.stat(fullPath);
|
|
118
|
+
if (stat.isDirectory()) return null;
|
|
119
|
+
const content = await fs.readFile(fullPath);
|
|
120
|
+
return {
|
|
121
|
+
content: new Uint8Array(content),
|
|
122
|
+
size: stat.size
|
|
123
|
+
};
|
|
124
|
+
} catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
__name(readFileNode, "readFileNode");
|
|
129
|
+
async function readFile(fullPath) {
|
|
130
|
+
const g = globalThis;
|
|
131
|
+
if (g.Bun) return readFileBun(fullPath);
|
|
132
|
+
if (g.Deno) return readFileDeno(fullPath);
|
|
133
|
+
return readFileNode(fullPath);
|
|
134
|
+
}
|
|
135
|
+
__name(readFile, "readFile");
|
|
136
|
+
async function resolveRoot(root) {
|
|
137
|
+
const g = globalThis;
|
|
138
|
+
if (g.Deno) {
|
|
139
|
+
const DenoRT = g.Deno;
|
|
140
|
+
const { join } = await import("path");
|
|
141
|
+
return join(DenoRT.cwd(), root);
|
|
142
|
+
}
|
|
143
|
+
const { resolve } = await import("path");
|
|
144
|
+
return resolve(root);
|
|
145
|
+
}
|
|
146
|
+
__name(resolveRoot, "resolveRoot");
|
|
147
|
+
function createStaticHandler(options) {
|
|
148
|
+
const root = options?.root ?? "public";
|
|
149
|
+
const maxAge = options?.maxAge ?? 0;
|
|
150
|
+
let resolvedRoot;
|
|
151
|
+
return async (request) => {
|
|
152
|
+
const method = request.method.toUpperCase();
|
|
153
|
+
if (method !== "GET" && method !== "HEAD") return null;
|
|
154
|
+
const url = new URL(request.url);
|
|
155
|
+
let pathname;
|
|
156
|
+
try {
|
|
157
|
+
pathname = decodeURIComponent(url.pathname);
|
|
158
|
+
} catch {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
if (pathname.startsWith("/api/") || pathname.startsWith("/@theo/")) return null;
|
|
162
|
+
if (!isSafePath(pathname)) return null;
|
|
163
|
+
resolvedRoot ??= await resolveRoot(root);
|
|
164
|
+
const { join } = await import("path");
|
|
165
|
+
let fullPath = join(resolvedRoot, pathname);
|
|
166
|
+
let result = await readFile(fullPath);
|
|
167
|
+
if (!result && (pathname.endsWith("/") || !pathname.includes("."))) {
|
|
168
|
+
fullPath = join(fullPath, "index.html");
|
|
169
|
+
result = await readFile(fullPath);
|
|
170
|
+
}
|
|
171
|
+
if (!result) return null;
|
|
172
|
+
const contentType = getMimeType(fullPath);
|
|
173
|
+
const headers = {
|
|
174
|
+
"content-type": contentType,
|
|
175
|
+
"content-length": String(result.size)
|
|
176
|
+
};
|
|
177
|
+
if (maxAge > 0) {
|
|
178
|
+
headers["cache-control"] = `public, max-age=${String(maxAge)}`;
|
|
179
|
+
}
|
|
180
|
+
if (method === "HEAD") {
|
|
181
|
+
return new Response(null, {
|
|
182
|
+
status: 200,
|
|
183
|
+
headers
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return new Response(result.content, {
|
|
187
|
+
status: 200,
|
|
188
|
+
headers
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
__name(createStaticHandler, "createStaticHandler");
|
|
193
|
+
|
|
194
|
+
// src/app.ts
|
|
18
195
|
var TheoApp = class _TheoApp {
|
|
19
196
|
static {
|
|
20
197
|
__name(this, "TheoApp");
|
|
@@ -22,6 +199,7 @@ var TheoApp = class _TheoApp {
|
|
|
22
199
|
serverHandle;
|
|
23
200
|
routes = [];
|
|
24
201
|
frontendHtml;
|
|
202
|
+
staticHandler;
|
|
25
203
|
startTime = Date.now();
|
|
26
204
|
healthPath;
|
|
27
205
|
readyPath;
|
|
@@ -111,6 +289,11 @@ var TheoApp = class _TheoApp {
|
|
|
111
289
|
entry.needsBody = entry.walk.paramEntries.some((p) => p.source === "body");
|
|
112
290
|
}
|
|
113
291
|
if (opts.html) app.frontendHtml = opts.html;
|
|
292
|
+
if (opts.staticDir !== false) {
|
|
293
|
+
app.staticHandler = createStaticHandler({
|
|
294
|
+
root: opts.staticDir ?? "public"
|
|
295
|
+
});
|
|
296
|
+
}
|
|
114
297
|
if (opts.agents?.length) {
|
|
115
298
|
await app.autoWireAgents(opts.agents, registry, opts);
|
|
116
299
|
}
|
|
@@ -291,6 +474,10 @@ var TheoApp = class _TheoApp {
|
|
|
291
474
|
});
|
|
292
475
|
}
|
|
293
476
|
}
|
|
477
|
+
if (this.staticHandler && (request.method === "GET" || request.method === "HEAD")) {
|
|
478
|
+
const staticResponse = await this.staticHandler(request);
|
|
479
|
+
if (staticResponse) return staticResponse;
|
|
480
|
+
}
|
|
294
481
|
for (const route of this.agentRoutes) {
|
|
295
482
|
if (request.method.toUpperCase() === route.method && route.pattern.test(pathname)) {
|
|
296
483
|
if (route.guards.length > 0) {
|
|
@@ -472,6 +659,9 @@ function buildResponse(result, walk, method) {
|
|
|
472
659
|
__name(buildResponse, "buildResponse");
|
|
473
660
|
|
|
474
661
|
export {
|
|
662
|
+
getMimeType,
|
|
663
|
+
isSafePath,
|
|
664
|
+
createStaticHandler,
|
|
475
665
|
TheoApp
|
|
476
666
|
};
|
|
477
|
-
//# sourceMappingURL=chunk-
|
|
667
|
+
//# sourceMappingURL=chunk-6LKZR4NZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/app.ts","../src/static.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-regexp, complexity, sonarjs/cognitive-complexity, max-depth, sonarjs/no-collapsible-if, max-lines, max-lines-per-function */\nimport 'reflect-metadata'\n\nimport { createExecutionContext, type CanActivate } from './bridge/execution-context.js'\nimport { createNodeAdapter } from './bridge/runtime/node.js'\nimport type { ServerHandle } from './bridge/runtime/types.js'\nimport { walkControllerMetadata, type WalkResult } from './bridge/walk-metadata.js'\nimport type { ParamEntry } from './decorators/params.js'\nimport { ForbiddenException, HttpException } from './exceptions/http-exception.js'\nimport { createStaticHandler } from './static.js'\n\n/**\n * TheoApp — NestJS/Spring Boot-style application bootstrap.\n *\n * Internally uses Web Standard Request/Response pipeline.\n * Node adapter converts at the HTTP server boundary.\n */\n\n/** Readiness check — async function returning health status. */\nexport type ReadinessCheck = () => Promise<{ name: string; healthy: boolean; message?: string }>\n\nexport interface TheoAppOptions {\n /** Controller classes decorated with @Controller. */\n controllers: Function[]\n /** Agent classes decorated with @Agent — auto-wired with routes + SSE + tools. */\n agents?: Function[]\n /** @Module class for structured DI. */\n module?: Function\n /** Provider/toolbox classes — instantiated and injected into controllers + agents. */\n providers?: Function[]\n /** LLM API key for agent execution (reads OPENROUTER_API_KEY env if not set). */\n llmApiKey?: string\n /** LLM model override (default: from @Agent({ model }) metadata). */\n llmModel?: string\n /** Agent stream factory override (for testing or custom SDK wiring). */\n agentStreamFactory?: (\n walk: unknown,\n tools: unknown[],\n apiKey: string,\n model?: string,\n ) => (message: string, sessionId: string) => AsyncIterable<unknown>\n /** HTML string to serve at GET / (inline frontend). */\n html?: string\n /** Directory for static file serving (default: 'public', false to disable). */\n staticDir?: string | false\n /** Readiness checks for GET /__theo/ready (K8s readiness probe). */\n readinessChecks?: ReadinessCheck[]\n /** Custom health endpoint path (default: '/__theo/health'). */\n healthPath?: string\n /** Custom readiness endpoint path (default: '/__theo/ready'). */\n readyPath?: string\n}\n\ninterface RouteEntry {\n walk: WalkResult\n instance: object\n /** Pre-compiled regex + param names (Elysia-inspired: compile once at create, not per-request). */\n compiledPattern?: RegExp\n compiledParamNames?: string[]\n /** Whether handler needs body parsing (skip for GET/DELETE without @Body). */\n needsBody?: boolean\n}\n\nexport class TheoApp {\n private serverHandle: ServerHandle\n private readonly routes: RouteEntry[] = []\n private frontendHtml?: string\n private staticHandler?: (request: Request) => Promise<Response | null>\n private readonly startTime = Date.now()\n private readonly healthPath: string\n private readonly readyPath: string\n private readonly readinessChecks: ReadinessCheck[]\n\n private constructor(opts?: Pick<TheoAppOptions, 'readinessChecks' | 'healthPath' | 'readyPath'>) {\n const hp = opts?.healthPath ?? '/__theo/health'\n const rp = opts?.readyPath ?? '/__theo/ready'\n // Security: prevent health paths from colliding with user API routes\n if (hp.startsWith('/api/'))\n throw new Error(\n `[TheoApp] healthPath \"${hp}\" must not start with /api/ — would collide with user routes`,\n )\n if (rp.startsWith('/api/'))\n throw new Error(\n `[TheoApp] readyPath \"${rp}\" must not start with /api/ — would collide with user routes`,\n )\n this.healthPath = hp\n this.readyPath = rp\n this.readinessChecks = opts?.readinessChecks ?? []\n const adapter = createNodeAdapter()\n this.serverHandle = adapter.createServer((request) => this.handleRequest(request))\n }\n\n /**\n * Create a TheoKit application with Spring Boot-style DI.\n *\n * EC-7: async because Container may resolve async factories (Agent.create).\n * EC-2: Registration order guaranteed: providers → controllers → agents.\n */\n static async create(opts: TheoAppOptions): Promise<TheoApp> {\n const app = new TheoApp(opts)\n\n // ── DI Container (replaces manual Map<Function, object>) ──\n // Uses @theokit/di Container for: scopes, lifecycle, async, typed errors.\n // Fallback to manual resolution when @theokit/di is not available.\n const registry = new Map<Function, object>()\n\n // 1. Module resolution (@Module metadata)\n if (opts.module) {\n const moduleMeta = Reflect.getMetadata('usetheo:di:module', opts.module)\n if (moduleMeta) {\n const allModules = [opts.module, ...(moduleMeta.imports ?? [])]\n for (const Mod of allModules) {\n const meta = Reflect.getMetadata('usetheo:di:module', Mod)\n if (!meta) continue\n for (const Prov of (meta.providers ?? []) as Function[]) {\n if (!registry.has(Prov)) {\n registry.set(Prov, new (Prov as new () => object)())\n }\n }\n }\n }\n }\n\n // 2. Inline providers (EC-2: BEFORE controllers and agents)\n if (opts.providers) {\n for (const Prov of opts.providers) {\n if (!registry.has(Prov)) {\n registry.set(Prov, new (Prov as new () => object)())\n }\n }\n }\n\n // 3. Controllers with DI\n for (const Controller of opts.controllers) {\n const paramTypes: Function[] = Reflect.getMetadata('design:paramtypes', Controller) ?? []\n const args = paramTypes.map((pt: Function) => {\n const dep = registry.get(pt)\n if (!dep) {\n throw new Error(\n `[TheoApp] Cannot resolve ${pt.name} for ${Controller.name}. ` +\n `Add ${pt.name} to providers (or to @Module({ providers: [...] })).`,\n )\n }\n return dep\n })\n const instance = new (Controller as new (...a: unknown[]) => object)(...args)\n\n // Lifecycle: call @PostConstruct if present\n const postConstruct = Reflect.getMetadata('usetheo:di:post-construct', Controller)\n if (\n postConstruct &&\n typeof (instance as Record<string, Function>)[postConstruct] === 'function'\n ) {\n const result = (instance as Record<string, Function>)[postConstruct]()\n if (result instanceof Promise) await result // EC-1: await async PostConstruct\n }\n\n const walks = walkControllerMetadata(Controller)\n for (const w of walks) {\n app.routes.push({ walk: w, instance })\n }\n }\n\n // Sort: static before parameterized\n app.routes.sort((a, b) => {\n const aP = a.walk.fullPath.includes(':')\n const bP = b.walk.fullPath.includes(':')\n if (aP !== bP) return aP ? 1 : -1\n return 0\n })\n\n // Pre-compile route patterns (Elysia-inspired: regex built once, not per-request)\n for (const entry of app.routes) {\n const paramNames: string[] = []\n const regexStr = entry.walk.fullPath.replace(/:(\\w+)/g, (_m, name: string) => {\n paramNames.push(name)\n return '([^/]+)'\n })\n entry.compiledPattern = new RegExp(`^${regexStr}$`)\n entry.compiledParamNames = paramNames\n // Determine if handler needs body parsing (skip if no @Body decorator)\n entry.needsBody = entry.walk.paramEntries.some((p) => p.source === 'body')\n }\n\n // Bug #8: Store frontend HTML\n if (opts.html) app.frontendHtml = opts.html\n\n // Static file serving from public/ (default: enabled)\n if (opts.staticDir !== false) {\n app.staticHandler = createStaticHandler({ root: opts.staticDir ?? 'public' })\n }\n\n // 4. Auto-wire agents (EC-2: AFTER providers and controllers)\n // The framework handles EVERYTHING — walk, compile, mount, stream.\n // Consumer writes: agents: [MyAgent] — and that's it.\n if (opts.agents?.length) {\n await app.autoWireAgents(opts.agents, registry, opts)\n }\n\n return app\n }\n\n async listen(port: number): Promise<void> {\n return new Promise((resolve) => {\n this.serverHandle.listen(port, () => {\n console.log(`TheoKit app listening on http://localhost:${port}`)\n resolve()\n })\n })\n }\n\n getServerHandle(): ServerHandle {\n return this.serverHandle\n }\n\n async close(): Promise<void> {\n return new Promise((resolve) => {\n this.serverHandle.close(() => {\n resolve()\n })\n })\n }\n\n // ── Auto-wire agents (the \"SpringApplication.run()\" moment) ──\n\n private agentRoutes: {\n method: string\n pattern: RegExp\n paramNames: string[]\n handler: (request: Request) => Promise<Response>\n guards: Function[]\n agentClass: Function\n methodName: string | symbol\n }[] = []\n\n private async autoWireAgents(\n agentClasses: Function[],\n registry: Map<Function, object>,\n opts: TheoAppOptions,\n ) {\n // Dynamic import — @theokit/agents is optional peer dependency\n // SECURITY: new Function used for dynamic import of optional peer dep.\n // Argument is HARDCODED ('@theokit/agents'), never user input. Safe.\n // eslint-disable-next-line @typescript-eslint/no-implied-eval -- dynamic import avoids compile-time dependency on optional peer\n const importFn = new Function('specifier', 'return import(specifier)') as (\n s: string,\n ) => Promise<Record<string, Function>>\n let walkAgentMetadata: Function,\n compileAgent: Function,\n generateAgentRoutes: Function,\n getMixins: Function,\n createSdkAgentStreamFn: Function\n try {\n const mod = await importFn('@theokit/agents')\n walkAgentMetadata = mod.walkAgentMetadata\n compileAgent = mod.compileAgent\n generateAgentRoutes = mod.generateAgentRoutes\n getMixins = mod.getMixins\n createSdkAgentStreamFn = mod.createSdkAgentStream\n } catch {\n throw new Error(\n '[TheoApp] @theokit/agents is required when agents[] is provided. Install: npm install @theokit/agents',\n )\n }\n\n const apiKey = opts.llmApiKey ?? process.env.OPENROUTER_API_KEY ?? ''\n\n for (const AgentClass of agentClasses) {\n // 1. Walk metadata (decorators → structured data)\n const mixins = getMixins(AgentClass)\n const allToolboxes = [...mixins]\n\n // Also check providers for @Toolbox classes\n for (const [Cls] of registry) {\n if (Reflect.getMetadata(Symbol.for('theokit:agents:toolbox'), Cls)) {\n if (!allToolboxes.includes(Cls)) allToolboxes.push(Cls)\n }\n }\n\n const walk = walkAgentMetadata(AgentClass, allToolboxes)\n\n // 2. Resolve toolbox instances from registry (DI)\n const toolboxInstances = new Map<Function, object>()\n for (const tb of walk.toolboxes) {\n let instance = registry.get(tb.class)\n if (!instance) {\n instance = new (tb.class as new () => object)()\n registry.set(tb.class, instance)\n }\n toolboxInstances.set(tb.class, instance)\n }\n\n // 3. Compile tools (decorator metadata → defineTool-compatible)\n const compiled = compileAgent(walk, toolboxInstances)\n\n // 4. Create SDK agent stream factory\n let createRun: (message: string, sessionId: string) => AsyncIterable<unknown>\n\n if (opts.agentStreamFactory) {\n createRun = opts.agentStreamFactory(walk, compiled.tools, apiKey, opts.llmModel)\n } else if (apiKey) {\n // SDK adapter: bridges @theokit/agents decorators → @theokit/sdk runtime\n createRun = createSdkAgentStreamFn(walk, compiled.tools, apiKey, opts.llmModel) as (\n m: string,\n s: string,\n ) => AsyncIterable<unknown>\n } else {\n createRun = this.createFallbackStream(walk.agentConfig.name, apiKey)\n }\n\n // 5. Generate routes (POST /chat, GET /runs/:id)\n const routes = generateAgentRoutes({\n walkResult: walk,\n compiledOptions: compiled,\n createRun: createRun as (\n message: string,\n sessionId: string,\n ) => AsyncIterable<{ type: string; [k: string]: unknown }>,\n })\n\n // 6. Mount routes\n for (const route of routes) {\n const paramNames: string[] = []\n const regexStr = route.path.replace(/:(\\w+)/g, (_m: string, name: string) => {\n paramNames.push(name)\n return '([^/]+)'\n })\n this.agentRoutes.push({\n method: route.method,\n pattern: new RegExp(`^${regexStr}$`),\n paramNames,\n handler: route.handler,\n guards: walk.guards ?? [],\n agentClass: AgentClass,\n methodName: walk.mainLoop?.propertyKey ?? 'run',\n })\n }\n\n console.log(\n ` 🤖 Agent \"${walk.agentConfig.name}\" mounted at ${walk.route}/chat (${compiled.tools.length} tools)`,\n )\n }\n }\n\n private async handleReadinessCheck(): Promise<Response> {\n if (this.readinessChecks.length === 0) {\n return jsonResponse(200, { status: 'ready', checks: [] })\n }\n const results = await Promise.all(\n this.readinessChecks.map(async (check) => {\n try {\n return await Promise.race([\n check(),\n new Promise<{ name: string; healthy: boolean; message?: string }>((resolve) =>\n setTimeout(\n () =>\n resolve({\n name: 'unknown',\n healthy: false,\n message: 'Readiness check timed out (5s)',\n }),\n 5000,\n ),\n ),\n ])\n } catch (err) {\n return {\n name: 'unknown',\n healthy: false,\n message: err instanceof Error ? err.message : 'Check failed',\n }\n }\n }),\n )\n const allHealthy = results.every((r) => r.healthy)\n return jsonResponse(allHealthy ? 200 : 503, {\n status: allHealthy ? 'ready' : 'not_ready',\n checks: results,\n })\n }\n\n private createFallbackStream(agentName: string, apiKey: string) {\n const msg = !apiKey\n ? 'Set OPENROUTER_API_KEY environment variable or pass llmApiKey to TheoApp.create()'\n : 'Pass agentStreamFactory to TheoApp.create() to connect your LLM provider'\n return (_message: string, _sessionId: string) => {\n const events = [\n { type: 'run_started', runId: `run-${Date.now()}`, agentName },\n { type: 'error', code: 'AGENT_NOT_WIRED', message: msg, retryable: false },\n ]\n return {\n [Symbol.asyncIterator]: () => {\n let i = 0\n return {\n next: () =>\n Promise.resolve(\n i < events.length\n ? { value: events[i++], done: false as const }\n : { value: undefined, done: true as const },\n ),\n }\n },\n }\n }\n }\n\n // ── Web Standard request handler ──────────────────\n\n private async handleRequest(request: Request): Promise<Response> {\n const pathname = new URL(request.url).pathname\n\n // ── Health & Readiness probes (bypass guards/interceptors) ──\n if (request.method === 'GET') {\n if (pathname === this.healthPath) {\n return jsonResponse(200, {\n status: 'ok',\n uptime: (Date.now() - this.startTime) / 1000,\n timestamp: Date.now(),\n })\n }\n if (pathname === this.readyPath) {\n return this.handleReadinessCheck()\n }\n }\n\n // Bug #8: Serve frontend HTML at GET /\n if (request.method === 'GET') {\n if ((pathname === '/' || pathname === '/index.html') && this.frontendHtml) {\n return new Response(this.frontendHtml, {\n status: 200,\n headers: { 'content-type': 'text/html; charset=utf-8' },\n })\n }\n }\n\n // Static files from public/ (runtime-agnostic — Node/Bun/Deno)\n if (this.staticHandler && (request.method === 'GET' || request.method === 'HEAD')) {\n const staticResponse = await this.staticHandler(request)\n if (staticResponse) return staticResponse\n }\n\n // Agent routes (auto-wired — checked first, with guard enforcement per Bug #4)\n for (const route of this.agentRoutes) {\n if (request.method.toUpperCase() === route.method && route.pattern.test(pathname)) {\n // Bug #4 fix: enforce @UseGuards on agent routes (same pipeline as controllers)\n if (route.guards.length > 0) {\n const ctx = createExecutionContext(request, route.agentClass, route.methodName)\n for (const GuardCtor of route.guards) {\n const guard = new (GuardCtor as new () => CanActivate)()\n if (!(await guard.canActivate(ctx))) {\n const ex = new ForbiddenException('Forbidden resource')\n return jsonResponse(ex.statusCode, ex.toJSON())\n }\n }\n }\n return route.handler(request)\n }\n }\n\n const url = new URL(request.url)\n const method = request.method.toUpperCase()\n\n const match = this.findRoute(method, url.pathname)\n if (!match) {\n return jsonResponse(404, {\n error: { code: 'NOT_FOUND', message: `No route for ${method} ${url.pathname}` },\n })\n }\n\n const { entry, params } = match\n\n try {\n // Guards\n const ctx = createExecutionContext(\n request,\n entry.instance.constructor,\n entry.walk.propertyKey,\n )\n for (const GuardCtor of entry.walk.guards) {\n const guard = new (GuardCtor as new () => CanActivate)()\n if (!(await guard.canActivate(ctx))) {\n const ex = new ForbiddenException('Forbidden resource')\n return jsonResponse(ex.statusCode, ex.toJSON())\n }\n }\n\n // Body — skip parsing entirely if handler has no @Body decorator (Elysia-inspired lazy parsing)\n let body: unknown\n if (entry.needsBody && ['POST', 'PUT', 'PATCH'].includes(method)) {\n try {\n const text = await request.text()\n body = text ? JSON.parse(text) : undefined\n } catch {\n body = undefined\n }\n\n if (entry.walk.bodySchema && body !== undefined) {\n const result = entry.walk.bodySchema.safeParse(body)\n if (!result.success) {\n return jsonResponse(422, {\n error: { code: 'VALIDATION_ERROR', issues: result.error.issues },\n })\n }\n body = result.data\n }\n }\n\n // Args\n const args = this.buildArgs(\n entry.walk.paramEntries,\n request,\n body,\n params,\n Object.fromEntries(url.searchParams),\n )\n\n // Redirect\n if (entry.walk.redirect) {\n return new Response(null, {\n status: entry.walk.redirect.status,\n headers: { location: entry.walk.redirect.url },\n })\n }\n\n // Handler — wrapped by interceptor chain (Bug #2 fix)\n const handlerFn = (entry.instance as Record<string | symbol, Function>)[\n entry.walk.propertyKey\n ]\n\n let result: unknown\n if (entry.walk.interceptors.length > 0) {\n // Import runInterceptors dynamically to avoid circular dep\n const { runInterceptors } = await import('./bridge/interceptor-chain.js')\n result = await runInterceptors(\n entry.walk.interceptors,\n () => handlerFn.apply(entry.instance, args) as Promise<unknown>,\n request,\n )\n } else {\n result = await handlerFn.apply(entry.instance, args)\n }\n\n return buildResponse(result, entry.walk, method)\n } catch (err) {\n // Exception filters (Bug #2 fix — filters also wired)\n if (entry.walk.filters.length > 0) {\n const { runExceptionFilters } = await import('./bridge/exception-filter-chain.js')\n return runExceptionFilters(err, entry.walk.filters, request)\n }\n // Fallback: HttpException subclasses (Bug #3 fix)\n if (err instanceof HttpException) {\n return jsonResponse(err.statusCode, err.toJSON())\n }\n // Security: never leak raw error messages to clients\n console.error('[theokit] Internal error:', err instanceof Error ? err.message : err)\n return jsonResponse(500, {\n error: { code: 'INTERNAL_SERVER_ERROR', message: 'Internal Server Error' },\n })\n }\n }\n\n private findRoute(method: string, pathname: string) {\n for (const entry of this.routes) {\n if (entry.walk.verb !== 'ALL' && entry.walk.verb !== method) continue\n // Use pre-compiled regex (built once at create time, not per-request)\n const match = entry.compiledPattern!.exec(pathname)\n if (!match) continue\n const params: Record<string, string> = {}\n entry.compiledParamNames!.forEach((name, i) => {\n params[name] = match[i + 1]\n })\n return { entry, params }\n }\n return null\n }\n\n private buildArgs(\n entries: ParamEntry[],\n request: Request,\n body: unknown,\n params: Record<string, string>,\n query: Record<string, string>,\n ): unknown[] {\n if (entries.length === 0) return []\n const max = Math.max(...entries.map((p) => p.index))\n const args: unknown[] = Array.from({ length: max + 1 }, () => undefined)\n for (const p of entries) {\n switch (p.source) {\n case 'req':\n args[p.index] = request\n break\n case 'body':\n args[p.index] = p.key ? (body as Record<string, unknown>)[p.key] : body\n break\n case 'param':\n args[p.index] = p.key ? params[p.key] : params\n break\n case 'query':\n args[p.index] = p.key ? query[p.key] : query\n break\n case 'headers':\n args[p.index] = p.key\n ? request.headers.get(p.key.toLowerCase())\n : Object.fromEntries(request.headers.entries())\n break\n case 'ip':\n args[p.index] = request.headers.get('x-forwarded-for') ?? '127.0.0.1'\n break\n default:\n args[p.index] = undefined\n }\n }\n return args\n }\n}\n\nfunction jsonResponse(status: number, body: unknown): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n\nfunction buildResponse(result: unknown, walk: WalkResult, method: string): Response {\n const status = walk.status ?? (method === 'POST' ? 201 : 200)\n const headers: Record<string, string> = { 'content-type': 'application/json' }\n for (const [n, v] of walk.headers) headers[n.toLowerCase()] = v\n\n if (result === undefined || result === null) {\n return new Response(null, { status: status === 200 ? 204 : status, headers })\n }\n if (typeof result === 'string') {\n headers['content-type'] = 'text/plain'\n return new Response(result, { status, headers })\n }\n return new Response(JSON.stringify(result), { status, headers })\n}\n","/**\n * Static file handler — runtime-agnostic (Node/Bun/Deno).\n *\n * Serves files from a root directory (default: `public/`).\n * Derived from Hono's serve-static middleware pattern:\n * - MIME type detection from extension\n * - Path traversal prevention via regex guard\n * - Runtime-agnostic file reading (Bun.file / Deno.readFile / node:fs)\n */\n\n// ── MIME type map (50+ types) ──────────────────────────\n\nconst MIME_TYPES: Record<string, string> = {\n // Text\n '.html': 'text/html; charset=utf-8',\n '.htm': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.xml': 'application/xml; charset=utf-8',\n '.txt': 'text/plain; charset=utf-8',\n '.csv': 'text/csv; charset=utf-8',\n '.md': 'text/markdown; charset=utf-8',\n '.yaml': 'text/yaml; charset=utf-8',\n '.yml': 'text/yaml; charset=utf-8',\n '.ts': 'text/typescript; charset=utf-8',\n '.tsx': 'text/tsx; charset=utf-8',\n '.jsx': 'text/jsx; charset=utf-8',\n\n // Images\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.webp': 'image/webp',\n '.avif': 'image/avif',\n '.bmp': 'image/bmp',\n '.tiff': 'image/tiff',\n '.tif': 'image/tiff',\n\n // Fonts\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.otf': 'font/otf',\n '.eot': 'application/vnd.ms-fontobject',\n\n // Media\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.ogg': 'audio/ogg',\n '.mp4': 'video/mp4',\n '.webm': 'video/webm',\n '.avi': 'video/x-msvideo',\n\n // Documents\n '.pdf': 'application/pdf',\n '.zip': 'application/zip',\n '.gz': 'application/gzip',\n '.tar': 'application/x-tar',\n '.wasm': 'application/wasm',\n\n // Misc\n '.map': 'application/json; charset=utf-8',\n '.jsonld': 'application/ld+json; charset=utf-8',\n '.manifest': 'application/manifest+json; charset=utf-8',\n '.webmanifest': 'application/manifest+json; charset=utf-8',\n}\n\n// ── Path traversal guard (Hono-derived regex) ──────────\n\n/**\n * Regex that catches path traversal attacks:\n * - `..` segments (beginning, middle, or end of path)\n * - Double slashes `//`\n * - Backslash sequences `\\\\`\n */\nconst UNSAFE_PATH_RE = /(?:^|[/\\\\])\\.{1,2}(?:$|[/\\\\])|[/\\\\]{2,}/\n\n// ── Public API ─────────────────────────────────────────\n\nexport interface StaticOptions {\n /** Root directory to serve from (default: 'public'). */\n root?: string\n /** Cache-Control max-age in seconds (default: 0 — no caching). */\n maxAge?: number\n}\n\n/**\n * Returns the MIME type for a given file path based on its extension.\n * Falls back to 'application/octet-stream' for unknown extensions.\n */\nexport function getMimeType(filePath: string): string {\n const dot = filePath.lastIndexOf('.')\n if (dot === -1) return 'application/octet-stream'\n const ext = filePath.slice(dot).toLowerCase()\n return MIME_TYPES[ext] ?? 'application/octet-stream'\n}\n\n/**\n * Returns true when the path is safe (no traversal, no double slashes).\n */\nexport function isSafePath(pathname: string): boolean {\n return !UNSAFE_PATH_RE.test(pathname)\n}\n\n// ── Runtime-agnostic file reader ───────────────────────\n\ninterface FileResult {\n content: Uint8Array\n size: number\n}\n\nasync function readFileBun(fullPath: string): Promise<FileResult | null> {\n const g = globalThis as Record<string, unknown>\n const BunRT = g.Bun as {\n file: (path: string) => {\n exists: () => Promise<boolean>\n arrayBuffer: () => Promise<ArrayBuffer>\n size: number\n }\n }\n const file = BunRT.file(fullPath)\n if (!(await file.exists())) return null\n const buf = await file.arrayBuffer()\n return { content: new Uint8Array(buf), size: file.size }\n}\n\nasync function readFileDeno(fullPath: string): Promise<FileResult | null> {\n const g = globalThis as Record<string, unknown>\n const DenoRT = g.Deno as {\n readFile: (path: string) => Promise<Uint8Array>\n stat: (path: string) => Promise<{ isDirectory: boolean }>\n }\n try {\n const stat = await DenoRT.stat(fullPath)\n if (stat.isDirectory) return null\n const content = await DenoRT.readFile(fullPath)\n return { content, size: content.byteLength }\n } catch {\n return null\n }\n}\n\nasync function readFileNode(fullPath: string): Promise<FileResult | null> {\n try {\n const fs = await import('node:fs/promises')\n const stat = await fs.stat(fullPath)\n if (stat.isDirectory()) return null\n const content = await fs.readFile(fullPath)\n return { content: new Uint8Array(content), size: stat.size }\n } catch {\n return null\n }\n}\n\nasync function readFile(fullPath: string): Promise<FileResult | null> {\n const g = globalThis as Record<string, unknown>\n if (g.Bun) return readFileBun(fullPath)\n if (g.Deno) return readFileDeno(fullPath)\n return readFileNode(fullPath)\n}\n\n// ── Resolve root to absolute path ──────────────────────\n\nasync function resolveRoot(root: string): Promise<string> {\n const g = globalThis as Record<string, unknown>\n if (g.Deno) {\n const DenoRT = g.Deno as { cwd: () => string }\n const { join } = await import('node:path')\n return join(DenoRT.cwd(), root)\n }\n const { resolve } = await import('node:path')\n return resolve(root)\n}\n\n// ── Factory ────────────────────────────────────────────\n\n/**\n * Creates a static file handler that serves files from `root` directory.\n *\n * Returns `null` when the request does not match a static file (allowing\n * the caller to fall through to the next handler).\n */\nexport function createStaticHandler(\n options?: StaticOptions,\n): (request: Request) => Promise<Response | null> {\n const root = options?.root ?? 'public'\n const maxAge = options?.maxAge ?? 0\n\n let resolvedRoot: string | undefined\n\n return async (request: Request): Promise<Response | null> => {\n // Only serve GET and HEAD\n const method = request.method.toUpperCase()\n if (method !== 'GET' && method !== 'HEAD') return null\n\n // Extract pathname, strip query params\n const url = new URL(request.url)\n let pathname: string\n try {\n pathname = decodeURIComponent(url.pathname)\n } catch {\n return null // Malformed URL encoding\n }\n\n // Skip framework-reserved paths\n if (pathname.startsWith('/api/') || pathname.startsWith('/@theo/')) return null\n\n // Path traversal guard\n if (!isSafePath(pathname)) return null\n\n // Lazy-resolve root to absolute path (once per handler lifetime)\n resolvedRoot ??= await resolveRoot(root)\n\n // Build full file path\n const { join } = await import('node:path')\n let fullPath = join(resolvedRoot, pathname)\n\n // Directory → try index.html\n let result = await readFile(fullPath)\n if (!result && (pathname.endsWith('/') || !pathname.includes('.'))) {\n fullPath = join(fullPath, 'index.html')\n result = await readFile(fullPath)\n }\n\n if (!result) return null\n\n // Build response headers\n const contentType = getMimeType(fullPath)\n const headers: Record<string, string> = {\n 'content-type': contentType,\n 'content-length': String(result.size),\n }\n if (maxAge > 0) {\n headers['cache-control'] = `public, max-age=${String(maxAge)}`\n }\n\n // HEAD: headers only, no body\n if (method === 'HEAD') {\n return new Response(null, { status: 200, headers })\n }\n\n return new Response(result.content as unknown as BodyInit, { status: 200, headers })\n }\n}\n"],"mappings":"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","names":["MIME_TYPES","UNSAFE_PATH_RE","getMimeType","filePath","dot","lastIndexOf","ext","slice","toLowerCase","isSafePath","pathname","test","readFileBun","fullPath","g","globalThis","BunRT","Bun","file","exists","buf","arrayBuffer","content","Uint8Array","size","readFileDeno","DenoRT","Deno","stat","isDirectory","readFile","byteLength","readFileNode","fs","resolveRoot","root","join","cwd","resolve","createStaticHandler","options","maxAge","resolvedRoot","request","method","toUpperCase","url","URL","decodeURIComponent","startsWith","result","endsWith","includes","contentType","headers","String","Response","status","TheoApp","serverHandle","routes","frontendHtml","staticHandler","startTime","Date","now","healthPath","readyPath","readinessChecks","opts","hp","rp","startsWith","Error","adapter","createNodeAdapter","createServer","request","handleRequest","create","app","registry","Map","module","moduleMeta","Reflect","getMetadata","allModules","imports","Mod","meta","Prov","providers","has","set","Controller","controllers","paramTypes","args","map","pt","dep","get","name","instance","postConstruct","result","Promise","walks","walkControllerMetadata","w","push","walk","sort","a","b","aP","fullPath","includes","bP","entry","paramNames","regexStr","replace","_m","compiledPattern","RegExp","compiledParamNames","needsBody","paramEntries","some","p","source","html","staticDir","createStaticHandler","root","agents","length","autoWireAgents","listen","port","resolve","console","log","getServerHandle","close","agentRoutes","agentClasses","importFn","Function","walkAgentMetadata","compileAgent","generateAgentRoutes","getMixins","createSdkAgentStreamFn","mod","createSdkAgentStream","apiKey","llmApiKey","process","env","OPENROUTER_API_KEY","AgentClass","mixins","allToolboxes","Cls","Symbol","for","toolboxInstances","tb","toolboxes","class","compiled","createRun","agentStreamFactory","tools","llmModel","createFallbackStream","agentConfig","walkResult","compiledOptions","route","path","method","pattern","handler","guards","agentClass","methodName","mainLoop","propertyKey","handleReadinessCheck","jsonResponse","status","checks","results","all","check","race","setTimeout","healthy","message","err","allHealthy","every","r","agentName","msg","_message","_sessionId","events","type","runId","code","retryable","asyncIterator","i","next","value","done","undefined","pathname","URL","url","uptime","timestamp","Response","headers","staticResponse","toUpperCase","test","ctx","createExecutionContext","GuardCtor","guard","canActivate","ex","ForbiddenException","statusCode","toJSON","match","findRoute","error","params","body","text","JSON","parse","bodySchema","safeParse","success","issues","data","buildArgs","Object","fromEntries","searchParams","redirect","location","handlerFn","interceptors","runInterceptors","apply","buildResponse","filters","runExceptionFilters","HttpException","verb","exec","forEach","entries","query","max","Math","index","Array","from","key","toLowerCase","stringify","n","v"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1059,4 +1059,36 @@ declare class TypedClientError extends Error {
|
|
|
1059
1059
|
*/
|
|
1060
1060
|
declare function contract<T extends RouteMap>(routes: T): T;
|
|
1061
1061
|
|
|
1062
|
-
|
|
1062
|
+
/**
|
|
1063
|
+
* Static file handler — runtime-agnostic (Node/Bun/Deno).
|
|
1064
|
+
*
|
|
1065
|
+
* Serves files from a root directory (default: `public/`).
|
|
1066
|
+
* Derived from Hono's serve-static middleware pattern:
|
|
1067
|
+
* - MIME type detection from extension
|
|
1068
|
+
* - Path traversal prevention via regex guard
|
|
1069
|
+
* - Runtime-agnostic file reading (Bun.file / Deno.readFile / node:fs)
|
|
1070
|
+
*/
|
|
1071
|
+
interface StaticOptions {
|
|
1072
|
+
/** Root directory to serve from (default: 'public'). */
|
|
1073
|
+
root?: string;
|
|
1074
|
+
/** Cache-Control max-age in seconds (default: 0 — no caching). */
|
|
1075
|
+
maxAge?: number;
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Returns the MIME type for a given file path based on its extension.
|
|
1079
|
+
* Falls back to 'application/octet-stream' for unknown extensions.
|
|
1080
|
+
*/
|
|
1081
|
+
declare function getMimeType(filePath: string): string;
|
|
1082
|
+
/**
|
|
1083
|
+
* Returns true when the path is safe (no traversal, no double slashes).
|
|
1084
|
+
*/
|
|
1085
|
+
declare function isSafePath(pathname: string): boolean;
|
|
1086
|
+
/**
|
|
1087
|
+
* Creates a static file handler that serves files from `root` directory.
|
|
1088
|
+
*
|
|
1089
|
+
* Returns `null` when the request does not match a static file (allowing
|
|
1090
|
+
* the caller to fall through to the next handler).
|
|
1091
|
+
*/
|
|
1092
|
+
declare function createStaticHandler(options?: StaticOptions): (request: Request) => Promise<Response | null>;
|
|
1093
|
+
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
TheoApp
|
|
3
|
-
|
|
2
|
+
TheoApp,
|
|
3
|
+
createStaticHandler,
|
|
4
|
+
getMimeType,
|
|
5
|
+
isSafePath
|
|
6
|
+
} from "./chunk-6LKZR4NZ.js";
|
|
4
7
|
import {
|
|
5
8
|
MiddlewareConsumerImpl,
|
|
6
9
|
middlewareMatchesPath,
|
|
@@ -758,9 +761,12 @@ export {
|
|
|
758
761
|
createDecorator,
|
|
759
762
|
createDecoratorServer,
|
|
760
763
|
createExecutionContext,
|
|
764
|
+
createStaticHandler,
|
|
761
765
|
createTypedClient,
|
|
762
766
|
getMeta,
|
|
767
|
+
getMimeType,
|
|
763
768
|
getThrottleOptions,
|
|
769
|
+
isSafePath,
|
|
764
770
|
isThrottleSkipped,
|
|
765
771
|
joinPath,
|
|
766
772
|
middlewareMatchesPath,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/decorators/controller.ts","../src/decorators/methods.ts","../src/decorators/params.ts","../src/decorators/response.ts","../src/decorators/middleware.ts","../src/decorators/set-metadata.ts","../src/decorators/throttle.ts","../src/bridge/register-controllers.ts","../src/bridge/create-server.ts","../src/typed-client.ts","../src/contract.ts"],"sourcesContent":["import { setMeta, CONTROLLER_PREFIX } from '../metadata/index.js'\n\nexport interface ControllerOptions {\n host?: string\n}\n\nexport interface ControllerMeta {\n prefix: string\n host?: string\n}\n\n/**\n * Infer route prefix from class name (Rails-style convention naming).\n *\n * UsersController → api/users\n * TasksController → api/tasks\n * AuthController → api/auth\n * HealthCheckController → api/health-check\n *\n * Strips \"Controller\" suffix, converts PascalCase to kebab-case,\n * prepends \"api/\".\n */\nfunction inferPrefix(className: string): string {\n const stripped = className.replace(/Controller$/, '')\n const kebab = stripped\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')\n .toLowerCase()\n return `api/${kebab}`\n}\n\n/**\n * Class decorator that declares a route-prefix scope.\n *\n * Convention over configuration:\n * @Controller() → prefix inferred from class name\n * @Controller('api/users') → explicit prefix\n *\n * @example\n * ```ts\n * // Convention: UsersController → /api/users (zero config)\n * @Controller()\n * class UsersController { ... }\n *\n * // Explicit: override when convention doesn't fit\n * @Controller('api/v2/users')\n * class UsersController { ... }\n * ```\n */\nexport function Controller(prefix?: string, opts?: ControllerOptions): ClassDecorator\nexport function Controller(opts?: ControllerOptions): ClassDecorator\nexport function Controller(\n prefixOrOpts?: string | ControllerOptions,\n maybeOpts?: ControllerOptions,\n): ClassDecorator {\n return (target) => {\n let prefix: string\n let opts: ControllerOptions\n\n if (typeof prefixOrOpts === 'string') {\n prefix = prefixOrOpts\n opts = maybeOpts ?? {}\n } else {\n // Convention naming: infer from class name\n prefix = inferPrefix(target.name)\n opts = prefixOrOpts ?? {}\n }\n\n setMeta<ControllerMeta>(CONTROLLER_PREFIX, target, {\n prefix,\n host: opts.host,\n })\n }\n}\n","import { setMeta, getMeta, ROUTE_METHODS } from '../metadata/index.js'\n\nexport type HttpVerb = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'ALL'\n\nexport interface RouteMethodEntry {\n verb: HttpVerb\n path: string\n propertyKey: string | symbol\n}\n\nfunction makeVerbDecorator(verb: HttpVerb) {\n return function (path = ''): MethodDecorator {\n return (target, propertyKey) => {\n const existing = getMeta<RouteMethodEntry[]>(ROUTE_METHODS, target.constructor) ?? []\n existing.push({ verb, path, propertyKey })\n setMeta(ROUTE_METHODS, target.constructor, existing)\n }\n }\n}\n\nexport const Get = makeVerbDecorator('GET')\nexport const Post = makeVerbDecorator('POST')\nexport const Put = makeVerbDecorator('PUT')\nexport const Patch = makeVerbDecorator('PATCH')\nexport const Delete = makeVerbDecorator('DELETE')\nexport const Options = makeVerbDecorator('OPTIONS')\nexport const Head = makeVerbDecorator('HEAD')\nexport const All = makeVerbDecorator('ALL')\n","import type { z } from 'zod'\n\nimport { setMeta, getMeta, ROUTE_PARAMS } from '../metadata/index.js'\n\nexport type ParamSource =\n | 'req'\n | 'res'\n | 'body'\n | 'param'\n | 'query'\n | 'headers'\n | 'session'\n | 'ip'\n | 'host'\n\nexport interface ParamEntry {\n source: ParamSource\n key?: string\n index: number\n passthrough?: boolean\n /** Explicit Zod schema — when set, bypasses design:paramtypes + DTO resolution.\n * Preferred path: `@Body(zMySchema)` works without emitDecoratorMetadata. */\n schema?: z.ZodType\n}\n\n/** Detect whether a value is a Zod schema (has `.safeParse()` method). */\nfunction isZodSchema(v: unknown): v is z.ZodType {\n return (\n v !== null &&\n v !== undefined &&\n typeof v === 'object' &&\n typeof (v as Record<string, unknown>).safeParse === 'function'\n )\n}\n\nfunction makeParamDecorator(source: ParamSource) {\n /**\n * Overloaded parameter decorator:\n * - `@Body()` / `@Param()` / `@Query()` — whole-object extraction\n * - `@Body('key')` / `@Param('key')` — named-field extraction\n * - `@Body(zodSchema)` — whole-object with explicit Zod validation\n * (works WITHOUT emitDecoratorMetadata — TheoKit \"Zod is SSoT\" alignment)\n */\n return function (keyOrSchema?: string | z.ZodType): ParameterDecorator {\n return (target, propertyKey, parameterIndex) => {\n if (propertyKey === undefined) return\n const map =\n getMeta<Map<string | symbol, ParamEntry[]>>(ROUTE_PARAMS, target.constructor) ?? new Map()\n const entries = map.get(propertyKey) ?? []\n\n const entry: ParamEntry = { source, index: parameterIndex }\n if (typeof keyOrSchema === 'string') {\n entry.key = keyOrSchema\n } else if (isZodSchema(keyOrSchema)) {\n entry.schema = keyOrSchema\n }\n\n entries.push(entry)\n map.set(propertyKey, entries)\n setMeta(ROUTE_PARAMS, target.constructor, map)\n }\n }\n}\n\nexport const Req = makeParamDecorator('req')\nexport const Body = makeParamDecorator('body')\nexport const Param = makeParamDecorator('param')\nexport const Query = makeParamDecorator('query')\nexport const Headers = makeParamDecorator('headers')\nexport const Session = makeParamDecorator('session')\nexport const Ip = makeParamDecorator('ip')\nexport const HostParam = makeParamDecorator('host')\n\nexport function Res(opts?: { passthrough?: boolean }): ParameterDecorator {\n return (target, propertyKey, parameterIndex) => {\n if (propertyKey === undefined) return\n const map =\n getMeta<Map<string | symbol, ParamEntry[]>>(ROUTE_PARAMS, target.constructor) ?? new Map()\n const entries = map.get(propertyKey) ?? []\n entries.push({\n source: 'res',\n index: parameterIndex,\n passthrough: opts?.passthrough,\n })\n map.set(propertyKey, entries)\n setMeta(ROUTE_PARAMS, target.constructor, map)\n }\n}\n","import { setMeta, getMeta, ROUTE_STATUS, ROUTE_HEADERS, ROUTE_REDIRECT } from '../metadata/index.js'\n\nexport function HttpCode(status: number): MethodDecorator {\n return (target, propertyKey) => {\n setMeta(ROUTE_STATUS, target.constructor, status, propertyKey as string)\n }\n}\n\nexport function Header(name: string, value: string): MethodDecorator {\n return (target, propertyKey) => {\n const existing =\n getMeta<[string, string][]>(ROUTE_HEADERS, target.constructor, propertyKey) ?? []\n existing.push([name, value])\n setMeta(ROUTE_HEADERS, target.constructor, existing, propertyKey as string)\n }\n}\n\nexport interface RedirectMeta {\n url: string\n status: number\n}\n\nexport function Redirect(url: string, status = 302): MethodDecorator {\n return (target, propertyKey) => {\n setMeta<RedirectMeta>(ROUTE_REDIRECT, target.constructor, { url, status }, propertyKey)\n }\n}\n","import {\n setMeta,\n getMeta,\n USE_GUARDS,\n USE_INTERCEPTORS,\n USE_FILTERS,\n CATCH_EXCEPTIONS,\n} from '../metadata/index.js'\n\nexport function UseGuards(...guards: Function[]): ClassDecorator & MethodDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const actualTarget = propertyKey ? target.constructor : target\n const existing = getMeta<Function[]>(USE_GUARDS, actualTarget, propertyKey) ?? []\n setMeta(USE_GUARDS, actualTarget, [...existing, ...guards], propertyKey)\n }\n}\n\nexport function UseInterceptors(...interceptors: Function[]): ClassDecorator & MethodDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const actualTarget = propertyKey ? target.constructor : target\n const existing = getMeta<Function[]>(USE_INTERCEPTORS, actualTarget, propertyKey) ?? []\n setMeta(USE_INTERCEPTORS, actualTarget, [...existing, ...interceptors], propertyKey)\n }\n}\n\nexport function UseFilters(...filters: Function[]): ClassDecorator & MethodDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const actualTarget = propertyKey ? target.constructor : target\n const existing = getMeta<Function[]>(USE_FILTERS, actualTarget, propertyKey) ?? []\n setMeta(USE_FILTERS, actualTarget, [...existing, ...filters], propertyKey)\n }\n}\n\n/** @Catch(ExceptionType, ...) — marks which exception types an ExceptionFilter handles.\n * Empty args = catch-all filter. */\nexport function Catch(...exceptions: Function[]): ClassDecorator {\n return (target: object) => {\n setMeta(CATCH_EXCEPTIONS, target, exceptions)\n }\n}\n","/**\n * @SetMetadata + Reflector — NestJS-style custom metadata for guards.\n *\n * Enables role-based auth pattern:\n * const Roles = createDecorator<string[]>()\n * @Roles(['admin']) → guard reads via reflector.get(Roles, handler)\n */\nimport 'reflect-metadata'\n\n/** Unique key type for type-safe metadata decorators. */\nexport type MetadataKey<T> = symbol & { __type?: T }\n\n/**\n * Create a typed decorator that attaches metadata to a handler or class.\n * NestJS equivalent: `Reflector.createDecorator<T>()`.\n *\n * @example\n * ```ts\n * const Roles = createDecorator<string[]>()\n *\n * @Controller('cats')\n * class CatsController {\n * @Post()\n * @Roles(['admin'])\n * create() { ... }\n * }\n * ```\n */\n/** Monotonic counter for unique decorator keys — deterministic, no randomness. */\nlet decoratorKeyCounter = 0\n\nexport function createDecorator<T>(): (value: T) => MethodDecorator & ClassDecorator {\n const key = Symbol.for(`theokit:custom:${++decoratorKeyCounter}`) as MetadataKey<T>\n\n const decorator = (value: T): MethodDecorator & ClassDecorator => {\n return (target: object, propertyKey?: string | symbol) => {\n const metaTarget = propertyKey !== undefined ? target.constructor : target\n Reflect.defineMetadata(key, value, metaTarget, propertyKey as string)\n }\n }\n\n // Attach the key so Reflector can read it\n ;(decorator as unknown as { key: MetadataKey<T> }).key = key\n return decorator\n}\n\n/**\n * Low-level @SetMetadata decorator — attaches arbitrary metadata.\n * NestJS equivalent: `@SetMetadata(key, value)`.\n *\n * Prefer `createDecorator<T>()` for type-safe metadata.\n */\nexport function SetMetadata<T>(\n metaKey: string | symbol,\n value: T,\n): MethodDecorator & ClassDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const metaTarget = propertyKey !== undefined ? target.constructor : target\n Reflect.defineMetadata(metaKey, value, metaTarget, propertyKey as string)\n }\n}\n\n/**\n * Reflector — reads metadata set by createDecorator or @SetMetadata.\n * NestJS-compatible Reflector with getAllAndOverride/getAllAndMerge.\n * HTTP-only per ADR D1.\n */\nexport class Reflector {\n /**\n * Read metadata set by a typed decorator created via createDecorator<T>().\n *\n * @example\n * ```ts\n * const Roles = createDecorator<string[]>()\n * const reflector = new Reflector()\n * const roles = reflector.get(Roles, handlerFn) // string[] | undefined\n * ```\n */\n get<T>(\n decorator: (value: T) => MethodDecorator & ClassDecorator,\n target: Function,\n propertyKey?: string | symbol,\n ): T | undefined {\n const key = (decorator as { key?: MetadataKey<T> }).key\n if (!key) return undefined\n if (propertyKey !== undefined) {\n return Reflect.getMetadata(key, target, propertyKey) as T | undefined\n }\n return Reflect.getMetadata(key, target) as T | undefined\n }\n\n /**\n * Read metadata set by @SetMetadata(key, value).\n */\n getByKey<T>(\n key: string | symbol,\n target: Function,\n propertyKey?: string | symbol,\n ): T | undefined {\n if (propertyKey !== undefined) {\n return Reflect.getMetadata(key, target, propertyKey) as T | undefined\n }\n return Reflect.getMetadata(key, target) as T | undefined\n }\n\n /**\n * Read metadata checking method-level first, then class-level.\n * Returns the first non-undefined value found.\n *\n * NestJS equivalent: `reflector.getAllAndOverride(ROLES_KEY, [context.getHandler(), context.getClass()])`\n *\n * @example\n * ```ts\n * const Roles = createDecorator<string[]>()\n * // In a guard:\n * const roles = reflector.getAllAndOverride(Roles, context.getClass(), context.getMethodName())\n * // Checks method-level @Roles first, falls back to class-level @Roles\n * ```\n */\n getAllAndOverride<T>(\n decorator: (value: T) => MethodDecorator & ClassDecorator,\n target: Function,\n propertyKey?: string | symbol,\n ): T | undefined {\n if (propertyKey !== undefined) {\n const methodLevel = this.get(decorator, target, propertyKey)\n if (methodLevel !== undefined) return methodLevel\n }\n return this.get(decorator, target)\n }\n\n /**\n * Read metadata checking method-level first, then class-level, by raw key.\n * Returns the first non-undefined value found.\n */\n getAllAndOverrideByKey<T>(\n key: string | symbol,\n target: Function,\n propertyKey?: string | symbol,\n ): T | undefined {\n if (propertyKey !== undefined) {\n const methodLevel = this.getByKey<T>(key, target, propertyKey)\n if (methodLevel !== undefined) return methodLevel\n }\n return this.getByKey<T>(key, target)\n }\n\n /**\n * Read metadata from both method-level and class-level, merging arrays.\n * Returns all found values as a flat array.\n *\n * NestJS equivalent: `reflector.getAllAndMerge(ROLES_KEY, [context.getHandler(), context.getClass()])`\n *\n * @example\n * ```ts\n * const Tags = createDecorator<string[]>()\n *\n * @Tags(['api'])\n * @Controller('cats')\n * class CatsCtrl {\n * @Tags(['read'])\n * @Get()\n * findAll() {}\n * }\n *\n * reflector.getAllAndMerge(Tags, CatsCtrl, 'findAll')\n * // → ['read', 'api'] (method + class merged)\n * ```\n */\n getAllAndMerge<T>(\n decorator: (value: T) => MethodDecorator & ClassDecorator,\n target: Function,\n propertyKey?: string | symbol,\n ): T extends (infer U)[] ? U[] : T[] {\n const result: unknown[] = []\n if (propertyKey !== undefined) {\n const methodLevel = this.get(decorator, target, propertyKey)\n if (methodLevel !== undefined) {\n if (Array.isArray(methodLevel)) result.push(...methodLevel)\n else result.push(methodLevel)\n }\n }\n const classLevel = this.get(decorator, target)\n if (classLevel !== undefined) {\n if (Array.isArray(classLevel)) result.push(...classLevel)\n else result.push(classLevel)\n }\n return result as T extends (infer U)[] ? U[] : T[]\n }\n}\n","/**\n * @Throttle() + @SkipThrottle() — NestJS-style rate limiting decorators.\n *\n * Thin bridge over @theokit/plugin-rate-limit. These decorators store\n * metadata that the rate-limit plugin reads at request time to override\n * or skip the global throttle config per route/controller.\n *\n * Usage:\n * ```ts\n * @Controller('api/tasks')\n * @Throttle({ limit: 100, ttl: 60_000 }) // 100 req/min for all routes\n * class TasksController {\n * @Get()\n * @SkipThrottle() // no rate limit on this route\n * health() { return { ok: true } }\n *\n * @Post()\n * @Throttle({ limit: 5, ttl: 60_000 }) // stricter: 5 req/min\n * create(@Body(schema) body) { ... }\n * }\n * ```\n */\nimport { setMeta, getMeta } from '../metadata/index.js'\n\nconst THROTTLE_KEY = Symbol.for('theokit:http-decorators:throttle')\nconst SKIP_THROTTLE_KEY = Symbol.for('theokit:http-decorators:skip-throttle')\n\nexport interface ThrottleOptions {\n /** Maximum requests within the TTL window. */\n limit: number\n /** Time-to-live in milliseconds. */\n ttl: number\n /** Optional throttle set name (for multiple throttler definitions). */\n name?: string\n}\n\n/**\n * Override the global rate limit for a controller or specific route.\n * NestJS equivalent: `@Throttle({ default: { limit, ttl } })`.\n */\nexport function Throttle(options: ThrottleOptions): ClassDecorator & MethodDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const actualTarget = propertyKey !== undefined ? target.constructor : target\n setMeta(THROTTLE_KEY, actualTarget, options, propertyKey)\n }\n}\n\n/**\n * Skip rate limiting for a controller or specific route.\n * NestJS equivalent: `@SkipThrottle()`.\n *\n * @param skip — defaults to `true`. Pass `false` to re-enable on a\n * specific route inside a skipped controller.\n */\nexport function SkipThrottle(skip = true): ClassDecorator & MethodDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const actualTarget = propertyKey !== undefined ? target.constructor : target\n setMeta(SKIP_THROTTLE_KEY, actualTarget, skip, propertyKey)\n }\n}\n\n/**\n * Read throttle metadata for a given class or method.\n * Used by the rate-limit plugin to resolve per-route overrides.\n */\nexport function getThrottleOptions(\n target: Function,\n propertyKey?: string | symbol,\n): ThrottleOptions | undefined {\n return getMeta<ThrottleOptions>(THROTTLE_KEY, target, propertyKey)\n}\n\n/**\n * Check if throttling is skipped for a given class or method.\n */\nexport function isThrottleSkipped(target: Function, propertyKey?: string | symbol): boolean {\n return getMeta<boolean>(SKIP_THROTTLE_KEY, target, propertyKey) ?? false\n}\n","import type { HttpVerb } from '../decorators/methods.js'\n\nimport { walkControllerMetadata, type WalkResult } from './walk-metadata.js'\n\nexport interface RouteRegistration {\n verb: HttpVerb\n fullPath: string\n walkResult: WalkResult\n}\n\n/**\n * Low-level API: walks decorator metadata per controller class and returns\n * structured route descriptors. Used internally by the Vite plugin (ADR D7)\n * and available to advanced consumers who don't use Vite.\n *\n * EC-5: deduplicates by class reference; warns on duplicates.\n */\nexport function registerControllers(controllers: Function[]): RouteRegistration[] {\n const seen = new Set<Function>()\n const unique: Function[] = []\n for (const Ctor of controllers) {\n if (seen.has(Ctor)) {\n console.warn(\n `[@theokit/http] Controller ${Ctor.name} registered multiple times — dropping duplicate`,\n )\n continue\n }\n seen.add(Ctor)\n unique.push(Ctor)\n }\n return unique.flatMap((Ctor) => {\n const walks = walkControllerMetadata(Ctor)\n return walks.map((w) => ({\n verb: w.verb,\n fullPath: w.fullPath,\n walkResult: w,\n }))\n })\n}\n","/* eslint-disable security/detect-non-literal-regexp --\n * Route patterns like /cats/:id are converted to regex at startup —\n * NOT from user HTTP input. The patterns come from decorator metadata\n * authored by the developer. No injection vector.\n */\nimport 'reflect-metadata'\n\nimport type { ParamEntry } from '../decorators/params.js'\nimport { ForbiddenException } from '../exceptions/http-exception.js'\n\nimport { resolveOrNew, type DiContainer } from './di-resolve.js'\nimport { runExceptionFilters } from './exception-filter-chain.js'\nimport { createExecutionContext, type CanActivate, type ExecutionContext } from './execution-context.js'\nimport { runInterceptors } from './interceptor-chain.js'\nimport {\n MiddlewareConsumerImpl,\n runMiddleware,\n type ResolvedMiddleware,\n} from './middleware-consumer.js'\nimport { createNodeAdapter } from './runtime/node.js'\nimport { walkControllerMetadata, type WalkResult } from './walk-metadata.js'\n\n/**\n * Creates a real HTTP server from decorated controller classes.\n * Uses Web Standard Request/Response internally; Node adapter at the boundary.\n */\nexport interface CreateDecoratorServerOptions {\n controllers: Function[]\n container?: DiContainer\n configure?: (consumer: MiddlewareConsumerImpl) => void\n}\n\nexport function createDecoratorServer(\n controllersOrOpts: Function[] | CreateDecoratorServerOptions,\n) {\n const { controllers, container, configure } = Array.isArray(controllersOrOpts)\n ? { controllers: controllersOrOpts, container: undefined, configure: undefined }\n : controllersOrOpts\n\n // Collect middleware\n const middlewareConsumer = new MiddlewareConsumerImpl(container)\n if (configure) configure(middlewareConsumer)\n const middlewareEntries = middlewareConsumer.getEntries()\n\n // Dedupe controllers (EC-5)\n const seen = new Set<Function>()\n const unique: Function[] = []\n for (const Ctor of controllers) {\n if (seen.has(Ctor)) continue\n seen.add(Ctor)\n unique.push(Ctor)\n }\n\n // Walk metadata\n const routes: { walk: WalkResult; instance: object }[] = []\n for (const Ctor of unique) {\n const instance = resolveOrNew(Ctor, container)\n const walks = walkControllerMetadata(Ctor)\n for (const w of walks) {\n routes.push({ walk: w, instance })\n }\n }\n\n // Sort: static routes first\n routes.sort((a, b) => {\n const aP = a.walk.fullPath.includes(':')\n const bP = b.walk.fullPath.includes(':')\n if (aP !== bP) return aP ? 1 : -1\n return 0\n })\n\n // Create Web Standard handler + Node adapter\n const adapter = createNodeAdapter()\n const handler = (request: Request) => handleRequest(routes, request, container, middlewareEntries)\n return adapter.createServer(handler)\n}\n\n// ─── Web Standard request handler ────────────────────────────\n\nasync function handleRequest(\n routes: { walk: WalkResult; instance: object }[],\n request: Request,\n container?: DiContainer,\n middlewareEntries: ResolvedMiddleware[] = [],\n): Promise<Response> {\n const url = new URL(request.url)\n const method = request.method.toUpperCase()\n const pathname = url.pathname\n\n const match = findRoute(routes, method, pathname)\n if (!match) {\n return jsonResponse(404, { error: { code: 'NOT_FOUND', message: `No route for ${method} ${pathname}` } })\n }\n\n const { walk, instance, params } = match\n\n try {\n // Middleware\n const mwResponse = await runMiddleware(middlewareEntries, request, pathname)\n if (mwResponse) return mwResponse\n\n // Guards\n const ctx = createExecutionContext(request, instance.constructor, walk.propertyKey)\n const guardResponse = await runGuards(walk.guards, ctx, container)\n if (guardResponse) return guardResponse\n\n // Body\n const body = await resolveBody(method, request, walk)\n if (body instanceof Response) return body // validation error response\n\n // Build args\n const args = buildArgs(walk.paramEntries, { request, body, params, query: Object.fromEntries(url.searchParams) })\n\n // Redirect\n if (walk.redirect) {\n return new Response(null, { status: walk.redirect.status, headers: { location: walk.redirect.url } })\n }\n\n const handlerFn = (instance as Record<string | symbol, Function>)[walk.propertyKey]\n\n // Interceptors wrap handler\n const result = await runInterceptors(\n walk.interceptors,\n () => handlerFn.apply(instance, args) as Promise<unknown>,\n request,\n container,\n )\n\n return buildResponse(result, walk, method)\n } catch (err) {\n return runExceptionFilters(err, walk.filters, request, container)\n }\n}\n\n// ─── Guards (return Response on rejection, null on pass) ─────\n\nasync function runGuards(\n guards: Function[],\n context: ExecutionContext,\n container?: DiContainer,\n): Promise<Response | null> {\n for (const GuardCtor of guards) {\n const guard = resolveOrNew(GuardCtor, container) as CanActivate\n const allowed = await guard.canActivate(context)\n if (!allowed) {\n const ex = new ForbiddenException('Forbidden resource')\n return jsonResponse(ex.statusCode, ex.toJSON())\n }\n }\n return null\n}\n\n// ─── Body resolution ─────────────────────────────────────────\n\nasync function resolveBody(method: string, request: Request, walk: WalkResult): Promise<unknown> {\n if (!['POST', 'PUT', 'PATCH'].includes(method)) return undefined\n\n let body: unknown\n try {\n const text = await request.text()\n body = text ? JSON.parse(text) : undefined\n } catch {\n body = undefined\n }\n\n if (walk.bodySchema && body !== undefined) {\n const result = walk.bodySchema.safeParse(body)\n if (!result.success) {\n return jsonResponse(422, { error: { code: 'VALIDATION_ERROR', issues: result.error.issues } })\n }\n body = result.data\n }\n return body\n}\n\n// ─── Response builder ────────────────────────────────────────\n\nfunction buildResponse(result: unknown, walk: WalkResult, method: string): Response {\n const status = walk.status ?? (method === 'POST' ? 201 : 200)\n const headers: Record<string, string> = { 'content-type': 'application/json' }\n for (const [name, value] of walk.headers) {\n headers[name.toLowerCase()] = value\n }\n\n if (result === undefined || result === null) {\n return new Response(null, { status: status === 200 ? 204 : status, headers })\n }\n\n if (typeof result === 'string') {\n headers['content-type'] = 'text/plain'\n return new Response(result, { status, headers })\n }\n\n return new Response(JSON.stringify(result), { status, headers })\n}\n\nfunction jsonResponse(status: number, body: unknown): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n// ─── Route matching ──────────────────────────────────────────\n\ninterface RouteMatch {\n walk: WalkResult\n instance: object\n params: Record<string, string>\n}\n\nfunction findRoute(\n routes: { walk: WalkResult; instance: object }[],\n method: string,\n pathname: string,\n): RouteMatch | null {\n for (const { walk, instance } of routes) {\n if (walk.verb !== 'ALL' && walk.verb !== method) continue\n const params = matchPath(walk.fullPath, pathname)\n if (params !== null) return { walk, instance, params }\n }\n return null\n}\n\nfunction matchPath(pattern: string, pathname: string): Record<string, string> | null {\n const paramNames: string[] = []\n const regexStr = pattern.replace(/:(\\w+)/g, (_m, name: string) => {\n paramNames.push(name)\n return '([^/]+)'\n })\n const match = new RegExp(`^${regexStr}$`).exec(pathname)\n if (!match) return null\n const params: Record<string, string> = {}\n paramNames.forEach((name, i) => { params[name] = match[i + 1] })\n return params\n}\n\n// ─── Argument builder ────────────────────────────────────────\n\ninterface ArgContext {\n request: Request\n body: unknown\n params: Record<string, string>\n query: Record<string, string>\n}\n\nfunction buildArgs(paramEntries: ParamEntry[], ctx: ArgContext): unknown[] {\n if (paramEntries.length === 0) return []\n const maxIndex = Math.max(...paramEntries.map((p) => p.index))\n const args: unknown[] = Array.from({ length: maxIndex + 1 }, () => undefined)\n for (const p of paramEntries) {\n switch (p.source) {\n case 'req':\n args[p.index] = ctx.request\n break\n case 'body':\n args[p.index] = p.key ? (ctx.body as Record<string, unknown>)[p.key] : ctx.body\n break\n case 'param':\n args[p.index] = p.key ? ctx.params[p.key] : ctx.params\n break\n case 'query':\n args[p.index] = p.key ? ctx.query[p.key] : ctx.query\n break\n case 'headers':\n args[p.index] = p.key ? ctx.request.headers.get(p.key.toLowerCase()) : Object.fromEntries(ctx.request.headers.entries())\n break\n case 'ip':\n args[p.index] = ctx.request.headers.get('x-forwarded-for') ?? '127.0.0.1'\n break\n case 'session':\n args[p.index] = undefined\n break\n default:\n args[p.index] = undefined\n }\n }\n return args\n}\n","/**\n * Typed Client — end-to-end type inference from route contracts.\n *\n * Zero codegen, zero runtime overhead on types. The developer defines\n * a route map using `contract()`, and `createTypedClient<T>()` infers\n * request body + response types automatically.\n */\nimport type { z } from 'zod'\n\n// ── Route Map types ──\n\nexport interface RouteDefinition {\n body?: z.ZodType\n params?: Record<string, 'string' | 'number'>\n query?: Record<string, 'string' | 'number' | 'boolean'>\n response: unknown\n}\n\nexport type RouteMap = Record<string, RouteDefinition>\n\n// ── Type extraction ──\n\ntype InferBody<D> = D extends { body: z.ZodType } ? z.infer<D['body']> : never\ntype InferResponse<D> = D extends { response: infer R } ? R : unknown\n\n// ── Client interface (simplified — works with strict DTS) ──\n\nexport interface TypedClient<M extends RouteMap> {\n get<P extends string & keyof M>(\n path: P,\n opts?: { query?: Record<string, string>; headers?: Record<string, string> },\n ): Promise<InferResponse<M[`GET ${P}`] extends never ? M[P] : M[`GET ${P}`]>>\n\n post<P extends string>(\n path: P,\n body?: InferBody<M[`POST ${P}`]>,\n opts?: { headers?: Record<string, string> },\n ): Promise<InferResponse<M[`POST ${P}`]>>\n\n put<P extends string>(\n path: P,\n body?: InferBody<M[`PUT ${P}`]>,\n opts?: { headers?: Record<string, string> },\n ): Promise<InferResponse<M[`PUT ${P}`]>>\n\n delete<P extends string>(\n path: P,\n opts?: { headers?: Record<string, string> },\n ): Promise<InferResponse<M[`DELETE ${P}`]>>\n}\n\n// ── Client factory ──\n\nexport function createTypedClient<M extends RouteMap>(\n baseUrl: string,\n defaultHeaders?: Record<string, string>,\n): TypedClient<M> {\n async function request(\n method: string,\n path: string,\n body?: unknown,\n opts?: { headers?: Record<string, string>; query?: Record<string, string> },\n ) {\n const url = new URL(path, baseUrl)\n if (opts?.query) {\n for (const [k, v] of Object.entries(opts.query)) url.searchParams.set(k, v)\n }\n const headers: Record<string, string> = { ...defaultHeaders, ...opts?.headers }\n if (body !== undefined) headers['content-type'] = 'application/json'\n\n const res = await fetch(url.toString(), {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n\n if (!res.ok) {\n const error = await res.json().catch(() => ({ message: res.statusText }))\n throw new TypedClientError(res.status, error as Record<string, unknown>)\n }\n\n if (res.status === 204) return undefined\n return res.json()\n }\n\n return {\n get: (path: string, opts?: Record<string, unknown>) => request('GET', path, undefined, opts),\n post: (path: string, body?: unknown, opts?: Record<string, unknown>) =>\n request('POST', path, body, opts),\n put: (path: string, body?: unknown, opts?: Record<string, unknown>) =>\n request('PUT', path, body, opts),\n delete: (path: string, opts?: Record<string, unknown>) =>\n request('DELETE', path, undefined, opts),\n } as TypedClient<M>\n}\n\nexport class TypedClientError extends Error {\n constructor(\n public readonly status: number,\n public readonly body: Record<string, unknown>,\n ) {\n super(`HTTP ${status}: ${JSON.stringify(body)}`)\n this.name = 'TypedClientError'\n }\n}\n","/**\n * Route Contract — type-level bridge between @Controller and TypedClient.\n *\n * The developer defines a contract object mapping routes to their types.\n * This object is the single source of truth for both server validation\n * and client type inference.\n *\n * @example\n * ```ts\n * // server/contracts.ts — shared between server and client\n * import { z } from 'zod'\n * import { contract } from '@theokit/http'\n *\n * export const zCreateTask = z.object({\n * title: z.string().min(3),\n * priority: z.enum(['low', 'medium', 'high']).default('medium'),\n * })\n *\n * export interface Task { id: number; title: string; priority: string; done: boolean }\n *\n * export const routes = contract({\n * 'GET /api/tasks': { response: [] as Task[] },\n * 'GET /api/tasks/:id': { response: {} as Task },\n * 'POST /api/tasks': { body: zCreateTask, response: {} as Task },\n * 'PUT /api/tasks/:id': { body: z.object({ done: z.boolean() }), response: {} as Task },\n * 'DELETE /api/tasks/:id': { response: undefined as void },\n * })\n * export type AppRoutes = typeof routes\n * ```\n *\n * The `contract()` function is identity at runtime (zero overhead) but\n * enforces the RouteMap type at the type level, enabling full inference.\n */\nimport type { RouteMap } from './typed-client.js'\n\n/**\n * Identity function that enforces RouteMap type constraint.\n * Zero runtime overhead — exists only for type inference.\n */\nexport function contract<T extends RouteMap>(routes: T): T {\n return routes\n}\n"],"mappings":"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","names":["inferPrefix","className","stripped","replace","kebab","toLowerCase","Controller","prefixOrOpts","maybeOpts","target","prefix","opts","name","setMeta","CONTROLLER_PREFIX","host","makeVerbDecorator","verb","path","target","propertyKey","existing","getMeta","ROUTE_METHODS","push","setMeta","Get","Post","Put","Patch","Delete","Options","Head","All","isZodSchema","v","undefined","safeParse","makeParamDecorator","source","keyOrSchema","target","propertyKey","parameterIndex","map","getMeta","ROUTE_PARAMS","Map","entries","get","entry","index","key","schema","push","set","setMeta","Req","Body","Param","Query","Headers","Session","Ip","HostParam","Res","opts","passthrough","HttpCode","status","target","propertyKey","setMeta","ROUTE_STATUS","Header","name","value","existing","getMeta","ROUTE_HEADERS","push","Redirect","url","ROUTE_REDIRECT","UseGuards","guards","target","propertyKey","actualTarget","existing","getMeta","USE_GUARDS","setMeta","UseInterceptors","interceptors","USE_INTERCEPTORS","UseFilters","filters","USE_FILTERS","Catch","exceptions","CATCH_EXCEPTIONS","decoratorKeyCounter","createDecorator","key","Symbol","for","decorator","value","target","propertyKey","metaTarget","undefined","Reflect","defineMetadata","SetMetadata","metaKey","Reflector","get","getMetadata","getByKey","getAllAndOverride","methodLevel","getAllAndOverrideByKey","getAllAndMerge","result","Array","isArray","push","classLevel","THROTTLE_KEY","Symbol","for","SKIP_THROTTLE_KEY","Throttle","options","target","propertyKey","actualTarget","undefined","setMeta","SkipThrottle","skip","getThrottleOptions","getMeta","isThrottleSkipped","registerControllers","controllers","seen","Set","unique","Ctor","has","console","warn","name","add","push","flatMap","walks","walkControllerMetadata","map","w","verb","fullPath","walkResult","createDecoratorServer","controllersOrOpts","controllers","container","configure","Array","isArray","undefined","middlewareConsumer","MiddlewareConsumerImpl","middlewareEntries","getEntries","seen","Set","unique","Ctor","has","add","push","routes","instance","resolveOrNew","walks","walkControllerMetadata","w","walk","sort","a","b","aP","fullPath","includes","bP","adapter","createNodeAdapter","handler","request","handleRequest","createServer","url","URL","method","toUpperCase","pathname","match","findRoute","jsonResponse","error","code","message","params","mwResponse","runMiddleware","ctx","createExecutionContext","propertyKey","guardResponse","runGuards","guards","body","resolveBody","Response","args","buildArgs","paramEntries","query","Object","fromEntries","searchParams","redirect","status","headers","location","handlerFn","result","runInterceptors","interceptors","apply","buildResponse","err","runExceptionFilters","filters","context","GuardCtor","guard","allowed","canActivate","ex","ForbiddenException","statusCode","toJSON","text","JSON","parse","bodySchema","safeParse","success","issues","data","name","value","toLowerCase","stringify","verb","matchPath","pattern","paramNames","regexStr","replace","_m","RegExp","exec","forEach","i","length","maxIndex","Math","max","map","p","index","from","source","key","get","entries","createTypedClient","baseUrl","defaultHeaders","request","method","path","body","opts","url","URL","query","k","v","Object","entries","searchParams","set","headers","undefined","res","fetch","toString","JSON","stringify","ok","error","json","catch","message","statusText","TypedClientError","status","get","post","put","delete","Error","name","contract","routes"]}
|
|
1
|
+
{"version":3,"sources":["../src/decorators/controller.ts","../src/decorators/methods.ts","../src/decorators/params.ts","../src/decorators/response.ts","../src/decorators/middleware.ts","../src/decorators/set-metadata.ts","../src/decorators/throttle.ts","../src/bridge/register-controllers.ts","../src/bridge/create-server.ts","../src/typed-client.ts","../src/contract.ts"],"sourcesContent":["import { setMeta, CONTROLLER_PREFIX } from '../metadata/index.js'\n\nexport interface ControllerOptions {\n host?: string\n}\n\nexport interface ControllerMeta {\n prefix: string\n host?: string\n}\n\n/**\n * Infer route prefix from class name (Rails-style convention naming).\n *\n * UsersController → api/users\n * TasksController → api/tasks\n * AuthController → api/auth\n * HealthCheckController → api/health-check\n *\n * Strips \"Controller\" suffix, converts PascalCase to kebab-case,\n * prepends \"api/\".\n */\nfunction inferPrefix(className: string): string {\n const stripped = className.replace(/Controller$/, '')\n const kebab = stripped\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')\n .toLowerCase()\n return `api/${kebab}`\n}\n\n/**\n * Class decorator that declares a route-prefix scope.\n *\n * Convention over configuration:\n * @Controller() → prefix inferred from class name\n * @Controller('api/users') → explicit prefix\n *\n * @example\n * ```ts\n * // Convention: UsersController → /api/users (zero config)\n * @Controller()\n * class UsersController { ... }\n *\n * // Explicit: override when convention doesn't fit\n * @Controller('api/v2/users')\n * class UsersController { ... }\n * ```\n */\nexport function Controller(prefix?: string, opts?: ControllerOptions): ClassDecorator\nexport function Controller(opts?: ControllerOptions): ClassDecorator\nexport function Controller(\n prefixOrOpts?: string | ControllerOptions,\n maybeOpts?: ControllerOptions,\n): ClassDecorator {\n return (target) => {\n let prefix: string\n let opts: ControllerOptions\n\n if (typeof prefixOrOpts === 'string') {\n prefix = prefixOrOpts\n opts = maybeOpts ?? {}\n } else {\n // Convention naming: infer from class name\n prefix = inferPrefix(target.name)\n opts = prefixOrOpts ?? {}\n }\n\n setMeta<ControllerMeta>(CONTROLLER_PREFIX, target, {\n prefix,\n host: opts.host,\n })\n }\n}\n","import { setMeta, getMeta, ROUTE_METHODS } from '../metadata/index.js'\n\nexport type HttpVerb = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'ALL'\n\nexport interface RouteMethodEntry {\n verb: HttpVerb\n path: string\n propertyKey: string | symbol\n}\n\nfunction makeVerbDecorator(verb: HttpVerb) {\n return function (path = ''): MethodDecorator {\n return (target, propertyKey) => {\n const existing = getMeta<RouteMethodEntry[]>(ROUTE_METHODS, target.constructor) ?? []\n existing.push({ verb, path, propertyKey })\n setMeta(ROUTE_METHODS, target.constructor, existing)\n }\n }\n}\n\nexport const Get = makeVerbDecorator('GET')\nexport const Post = makeVerbDecorator('POST')\nexport const Put = makeVerbDecorator('PUT')\nexport const Patch = makeVerbDecorator('PATCH')\nexport const Delete = makeVerbDecorator('DELETE')\nexport const Options = makeVerbDecorator('OPTIONS')\nexport const Head = makeVerbDecorator('HEAD')\nexport const All = makeVerbDecorator('ALL')\n","import type { z } from 'zod'\n\nimport { setMeta, getMeta, ROUTE_PARAMS } from '../metadata/index.js'\n\nexport type ParamSource =\n | 'req'\n | 'res'\n | 'body'\n | 'param'\n | 'query'\n | 'headers'\n | 'session'\n | 'ip'\n | 'host'\n\nexport interface ParamEntry {\n source: ParamSource\n key?: string\n index: number\n passthrough?: boolean\n /** Explicit Zod schema — when set, bypasses design:paramtypes + DTO resolution.\n * Preferred path: `@Body(zMySchema)` works without emitDecoratorMetadata. */\n schema?: z.ZodType\n}\n\n/** Detect whether a value is a Zod schema (has `.safeParse()` method). */\nfunction isZodSchema(v: unknown): v is z.ZodType {\n return (\n v !== null &&\n v !== undefined &&\n typeof v === 'object' &&\n typeof (v as Record<string, unknown>).safeParse === 'function'\n )\n}\n\nfunction makeParamDecorator(source: ParamSource) {\n /**\n * Overloaded parameter decorator:\n * - `@Body()` / `@Param()` / `@Query()` — whole-object extraction\n * - `@Body('key')` / `@Param('key')` — named-field extraction\n * - `@Body(zodSchema)` — whole-object with explicit Zod validation\n * (works WITHOUT emitDecoratorMetadata — TheoKit \"Zod is SSoT\" alignment)\n */\n return function (keyOrSchema?: string | z.ZodType): ParameterDecorator {\n return (target, propertyKey, parameterIndex) => {\n if (propertyKey === undefined) return\n const map =\n getMeta<Map<string | symbol, ParamEntry[]>>(ROUTE_PARAMS, target.constructor) ?? new Map()\n const entries = map.get(propertyKey) ?? []\n\n const entry: ParamEntry = { source, index: parameterIndex }\n if (typeof keyOrSchema === 'string') {\n entry.key = keyOrSchema\n } else if (isZodSchema(keyOrSchema)) {\n entry.schema = keyOrSchema\n }\n\n entries.push(entry)\n map.set(propertyKey, entries)\n setMeta(ROUTE_PARAMS, target.constructor, map)\n }\n }\n}\n\nexport const Req = makeParamDecorator('req')\nexport const Body = makeParamDecorator('body')\nexport const Param = makeParamDecorator('param')\nexport const Query = makeParamDecorator('query')\nexport const Headers = makeParamDecorator('headers')\nexport const Session = makeParamDecorator('session')\nexport const Ip = makeParamDecorator('ip')\nexport const HostParam = makeParamDecorator('host')\n\nexport function Res(opts?: { passthrough?: boolean }): ParameterDecorator {\n return (target, propertyKey, parameterIndex) => {\n if (propertyKey === undefined) return\n const map =\n getMeta<Map<string | symbol, ParamEntry[]>>(ROUTE_PARAMS, target.constructor) ?? new Map()\n const entries = map.get(propertyKey) ?? []\n entries.push({\n source: 'res',\n index: parameterIndex,\n passthrough: opts?.passthrough,\n })\n map.set(propertyKey, entries)\n setMeta(ROUTE_PARAMS, target.constructor, map)\n }\n}\n","import { setMeta, getMeta, ROUTE_STATUS, ROUTE_HEADERS, ROUTE_REDIRECT } from '../metadata/index.js'\n\nexport function HttpCode(status: number): MethodDecorator {\n return (target, propertyKey) => {\n setMeta(ROUTE_STATUS, target.constructor, status, propertyKey as string)\n }\n}\n\nexport function Header(name: string, value: string): MethodDecorator {\n return (target, propertyKey) => {\n const existing =\n getMeta<[string, string][]>(ROUTE_HEADERS, target.constructor, propertyKey) ?? []\n existing.push([name, value])\n setMeta(ROUTE_HEADERS, target.constructor, existing, propertyKey as string)\n }\n}\n\nexport interface RedirectMeta {\n url: string\n status: number\n}\n\nexport function Redirect(url: string, status = 302): MethodDecorator {\n return (target, propertyKey) => {\n setMeta<RedirectMeta>(ROUTE_REDIRECT, target.constructor, { url, status }, propertyKey)\n }\n}\n","import {\n setMeta,\n getMeta,\n USE_GUARDS,\n USE_INTERCEPTORS,\n USE_FILTERS,\n CATCH_EXCEPTIONS,\n} from '../metadata/index.js'\n\nexport function UseGuards(...guards: Function[]): ClassDecorator & MethodDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const actualTarget = propertyKey ? target.constructor : target\n const existing = getMeta<Function[]>(USE_GUARDS, actualTarget, propertyKey) ?? []\n setMeta(USE_GUARDS, actualTarget, [...existing, ...guards], propertyKey)\n }\n}\n\nexport function UseInterceptors(...interceptors: Function[]): ClassDecorator & MethodDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const actualTarget = propertyKey ? target.constructor : target\n const existing = getMeta<Function[]>(USE_INTERCEPTORS, actualTarget, propertyKey) ?? []\n setMeta(USE_INTERCEPTORS, actualTarget, [...existing, ...interceptors], propertyKey)\n }\n}\n\nexport function UseFilters(...filters: Function[]): ClassDecorator & MethodDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const actualTarget = propertyKey ? target.constructor : target\n const existing = getMeta<Function[]>(USE_FILTERS, actualTarget, propertyKey) ?? []\n setMeta(USE_FILTERS, actualTarget, [...existing, ...filters], propertyKey)\n }\n}\n\n/** @Catch(ExceptionType, ...) — marks which exception types an ExceptionFilter handles.\n * Empty args = catch-all filter. */\nexport function Catch(...exceptions: Function[]): ClassDecorator {\n return (target: object) => {\n setMeta(CATCH_EXCEPTIONS, target, exceptions)\n }\n}\n","/**\n * @SetMetadata + Reflector — NestJS-style custom metadata for guards.\n *\n * Enables role-based auth pattern:\n * const Roles = createDecorator<string[]>()\n * @Roles(['admin']) → guard reads via reflector.get(Roles, handler)\n */\nimport 'reflect-metadata'\n\n/** Unique key type for type-safe metadata decorators. */\nexport type MetadataKey<T> = symbol & { __type?: T }\n\n/**\n * Create a typed decorator that attaches metadata to a handler or class.\n * NestJS equivalent: `Reflector.createDecorator<T>()`.\n *\n * @example\n * ```ts\n * const Roles = createDecorator<string[]>()\n *\n * @Controller('cats')\n * class CatsController {\n * @Post()\n * @Roles(['admin'])\n * create() { ... }\n * }\n * ```\n */\n/** Monotonic counter for unique decorator keys — deterministic, no randomness. */\nlet decoratorKeyCounter = 0\n\nexport function createDecorator<T>(): (value: T) => MethodDecorator & ClassDecorator {\n const key = Symbol.for(`theokit:custom:${++decoratorKeyCounter}`) as MetadataKey<T>\n\n const decorator = (value: T): MethodDecorator & ClassDecorator => {\n return (target: object, propertyKey?: string | symbol) => {\n const metaTarget = propertyKey !== undefined ? target.constructor : target\n Reflect.defineMetadata(key, value, metaTarget, propertyKey as string)\n }\n }\n\n // Attach the key so Reflector can read it\n ;(decorator as unknown as { key: MetadataKey<T> }).key = key\n return decorator\n}\n\n/**\n * Low-level @SetMetadata decorator — attaches arbitrary metadata.\n * NestJS equivalent: `@SetMetadata(key, value)`.\n *\n * Prefer `createDecorator<T>()` for type-safe metadata.\n */\nexport function SetMetadata<T>(\n metaKey: string | symbol,\n value: T,\n): MethodDecorator & ClassDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const metaTarget = propertyKey !== undefined ? target.constructor : target\n Reflect.defineMetadata(metaKey, value, metaTarget, propertyKey as string)\n }\n}\n\n/**\n * Reflector — reads metadata set by createDecorator or @SetMetadata.\n * NestJS-compatible Reflector with getAllAndOverride/getAllAndMerge.\n * HTTP-only per ADR D1.\n */\nexport class Reflector {\n /**\n * Read metadata set by a typed decorator created via createDecorator<T>().\n *\n * @example\n * ```ts\n * const Roles = createDecorator<string[]>()\n * const reflector = new Reflector()\n * const roles = reflector.get(Roles, handlerFn) // string[] | undefined\n * ```\n */\n get<T>(\n decorator: (value: T) => MethodDecorator & ClassDecorator,\n target: Function,\n propertyKey?: string | symbol,\n ): T | undefined {\n const key = (decorator as { key?: MetadataKey<T> }).key\n if (!key) return undefined\n if (propertyKey !== undefined) {\n return Reflect.getMetadata(key, target, propertyKey) as T | undefined\n }\n return Reflect.getMetadata(key, target) as T | undefined\n }\n\n /**\n * Read metadata set by @SetMetadata(key, value).\n */\n getByKey<T>(\n key: string | symbol,\n target: Function,\n propertyKey?: string | symbol,\n ): T | undefined {\n if (propertyKey !== undefined) {\n return Reflect.getMetadata(key, target, propertyKey) as T | undefined\n }\n return Reflect.getMetadata(key, target) as T | undefined\n }\n\n /**\n * Read metadata checking method-level first, then class-level.\n * Returns the first non-undefined value found.\n *\n * NestJS equivalent: `reflector.getAllAndOverride(ROLES_KEY, [context.getHandler(), context.getClass()])`\n *\n * @example\n * ```ts\n * const Roles = createDecorator<string[]>()\n * // In a guard:\n * const roles = reflector.getAllAndOverride(Roles, context.getClass(), context.getMethodName())\n * // Checks method-level @Roles first, falls back to class-level @Roles\n * ```\n */\n getAllAndOverride<T>(\n decorator: (value: T) => MethodDecorator & ClassDecorator,\n target: Function,\n propertyKey?: string | symbol,\n ): T | undefined {\n if (propertyKey !== undefined) {\n const methodLevel = this.get(decorator, target, propertyKey)\n if (methodLevel !== undefined) return methodLevel\n }\n return this.get(decorator, target)\n }\n\n /**\n * Read metadata checking method-level first, then class-level, by raw key.\n * Returns the first non-undefined value found.\n */\n getAllAndOverrideByKey<T>(\n key: string | symbol,\n target: Function,\n propertyKey?: string | symbol,\n ): T | undefined {\n if (propertyKey !== undefined) {\n const methodLevel = this.getByKey<T>(key, target, propertyKey)\n if (methodLevel !== undefined) return methodLevel\n }\n return this.getByKey<T>(key, target)\n }\n\n /**\n * Read metadata from both method-level and class-level, merging arrays.\n * Returns all found values as a flat array.\n *\n * NestJS equivalent: `reflector.getAllAndMerge(ROLES_KEY, [context.getHandler(), context.getClass()])`\n *\n * @example\n * ```ts\n * const Tags = createDecorator<string[]>()\n *\n * @Tags(['api'])\n * @Controller('cats')\n * class CatsCtrl {\n * @Tags(['read'])\n * @Get()\n * findAll() {}\n * }\n *\n * reflector.getAllAndMerge(Tags, CatsCtrl, 'findAll')\n * // → ['read', 'api'] (method + class merged)\n * ```\n */\n getAllAndMerge<T>(\n decorator: (value: T) => MethodDecorator & ClassDecorator,\n target: Function,\n propertyKey?: string | symbol,\n ): T extends (infer U)[] ? U[] : T[] {\n const result: unknown[] = []\n if (propertyKey !== undefined) {\n const methodLevel = this.get(decorator, target, propertyKey)\n if (methodLevel !== undefined) {\n if (Array.isArray(methodLevel)) result.push(...methodLevel)\n else result.push(methodLevel)\n }\n }\n const classLevel = this.get(decorator, target)\n if (classLevel !== undefined) {\n if (Array.isArray(classLevel)) result.push(...classLevel)\n else result.push(classLevel)\n }\n return result as T extends (infer U)[] ? U[] : T[]\n }\n}\n","/**\n * @Throttle() + @SkipThrottle() — NestJS-style rate limiting decorators.\n *\n * Thin bridge over @theokit/plugin-rate-limit. These decorators store\n * metadata that the rate-limit plugin reads at request time to override\n * or skip the global throttle config per route/controller.\n *\n * Usage:\n * ```ts\n * @Controller('api/tasks')\n * @Throttle({ limit: 100, ttl: 60_000 }) // 100 req/min for all routes\n * class TasksController {\n * @Get()\n * @SkipThrottle() // no rate limit on this route\n * health() { return { ok: true } }\n *\n * @Post()\n * @Throttle({ limit: 5, ttl: 60_000 }) // stricter: 5 req/min\n * create(@Body(schema) body) { ... }\n * }\n * ```\n */\nimport { setMeta, getMeta } from '../metadata/index.js'\n\nconst THROTTLE_KEY = Symbol.for('theokit:http-decorators:throttle')\nconst SKIP_THROTTLE_KEY = Symbol.for('theokit:http-decorators:skip-throttle')\n\nexport interface ThrottleOptions {\n /** Maximum requests within the TTL window. */\n limit: number\n /** Time-to-live in milliseconds. */\n ttl: number\n /** Optional throttle set name (for multiple throttler definitions). */\n name?: string\n}\n\n/**\n * Override the global rate limit for a controller or specific route.\n * NestJS equivalent: `@Throttle({ default: { limit, ttl } })`.\n */\nexport function Throttle(options: ThrottleOptions): ClassDecorator & MethodDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const actualTarget = propertyKey !== undefined ? target.constructor : target\n setMeta(THROTTLE_KEY, actualTarget, options, propertyKey)\n }\n}\n\n/**\n * Skip rate limiting for a controller or specific route.\n * NestJS equivalent: `@SkipThrottle()`.\n *\n * @param skip — defaults to `true`. Pass `false` to re-enable on a\n * specific route inside a skipped controller.\n */\nexport function SkipThrottle(skip = true): ClassDecorator & MethodDecorator {\n return (target: object, propertyKey?: string | symbol) => {\n const actualTarget = propertyKey !== undefined ? target.constructor : target\n setMeta(SKIP_THROTTLE_KEY, actualTarget, skip, propertyKey)\n }\n}\n\n/**\n * Read throttle metadata for a given class or method.\n * Used by the rate-limit plugin to resolve per-route overrides.\n */\nexport function getThrottleOptions(\n target: Function,\n propertyKey?: string | symbol,\n): ThrottleOptions | undefined {\n return getMeta<ThrottleOptions>(THROTTLE_KEY, target, propertyKey)\n}\n\n/**\n * Check if throttling is skipped for a given class or method.\n */\nexport function isThrottleSkipped(target: Function, propertyKey?: string | symbol): boolean {\n return getMeta<boolean>(SKIP_THROTTLE_KEY, target, propertyKey) ?? false\n}\n","import type { HttpVerb } from '../decorators/methods.js'\n\nimport { walkControllerMetadata, type WalkResult } from './walk-metadata.js'\n\nexport interface RouteRegistration {\n verb: HttpVerb\n fullPath: string\n walkResult: WalkResult\n}\n\n/**\n * Low-level API: walks decorator metadata per controller class and returns\n * structured route descriptors. Used internally by the Vite plugin (ADR D7)\n * and available to advanced consumers who don't use Vite.\n *\n * EC-5: deduplicates by class reference; warns on duplicates.\n */\nexport function registerControllers(controllers: Function[]): RouteRegistration[] {\n const seen = new Set<Function>()\n const unique: Function[] = []\n for (const Ctor of controllers) {\n if (seen.has(Ctor)) {\n console.warn(\n `[@theokit/http] Controller ${Ctor.name} registered multiple times — dropping duplicate`,\n )\n continue\n }\n seen.add(Ctor)\n unique.push(Ctor)\n }\n return unique.flatMap((Ctor) => {\n const walks = walkControllerMetadata(Ctor)\n return walks.map((w) => ({\n verb: w.verb,\n fullPath: w.fullPath,\n walkResult: w,\n }))\n })\n}\n","/* eslint-disable security/detect-non-literal-regexp --\n * Route patterns like /cats/:id are converted to regex at startup —\n * NOT from user HTTP input. The patterns come from decorator metadata\n * authored by the developer. No injection vector.\n */\nimport 'reflect-metadata'\n\nimport type { ParamEntry } from '../decorators/params.js'\nimport { ForbiddenException } from '../exceptions/http-exception.js'\n\nimport { resolveOrNew, type DiContainer } from './di-resolve.js'\nimport { runExceptionFilters } from './exception-filter-chain.js'\nimport { createExecutionContext, type CanActivate, type ExecutionContext } from './execution-context.js'\nimport { runInterceptors } from './interceptor-chain.js'\nimport {\n MiddlewareConsumerImpl,\n runMiddleware,\n type ResolvedMiddleware,\n} from './middleware-consumer.js'\nimport { createNodeAdapter } from './runtime/node.js'\nimport { walkControllerMetadata, type WalkResult } from './walk-metadata.js'\n\n/**\n * Creates a real HTTP server from decorated controller classes.\n * Uses Web Standard Request/Response internally; Node adapter at the boundary.\n */\nexport interface CreateDecoratorServerOptions {\n controllers: Function[]\n container?: DiContainer\n configure?: (consumer: MiddlewareConsumerImpl) => void\n}\n\nexport function createDecoratorServer(\n controllersOrOpts: Function[] | CreateDecoratorServerOptions,\n) {\n const { controllers, container, configure } = Array.isArray(controllersOrOpts)\n ? { controllers: controllersOrOpts, container: undefined, configure: undefined }\n : controllersOrOpts\n\n // Collect middleware\n const middlewareConsumer = new MiddlewareConsumerImpl(container)\n if (configure) configure(middlewareConsumer)\n const middlewareEntries = middlewareConsumer.getEntries()\n\n // Dedupe controllers (EC-5)\n const seen = new Set<Function>()\n const unique: Function[] = []\n for (const Ctor of controllers) {\n if (seen.has(Ctor)) continue\n seen.add(Ctor)\n unique.push(Ctor)\n }\n\n // Walk metadata\n const routes: { walk: WalkResult; instance: object }[] = []\n for (const Ctor of unique) {\n const instance = resolveOrNew(Ctor, container)\n const walks = walkControllerMetadata(Ctor)\n for (const w of walks) {\n routes.push({ walk: w, instance })\n }\n }\n\n // Sort: static routes first\n routes.sort((a, b) => {\n const aP = a.walk.fullPath.includes(':')\n const bP = b.walk.fullPath.includes(':')\n if (aP !== bP) return aP ? 1 : -1\n return 0\n })\n\n // Create Web Standard handler + Node adapter\n const adapter = createNodeAdapter()\n const handler = (request: Request) => handleRequest(routes, request, container, middlewareEntries)\n return adapter.createServer(handler)\n}\n\n// ─── Web Standard request handler ────────────────────────────\n\nasync function handleRequest(\n routes: { walk: WalkResult; instance: object }[],\n request: Request,\n container?: DiContainer,\n middlewareEntries: ResolvedMiddleware[] = [],\n): Promise<Response> {\n const url = new URL(request.url)\n const method = request.method.toUpperCase()\n const pathname = url.pathname\n\n const match = findRoute(routes, method, pathname)\n if (!match) {\n return jsonResponse(404, { error: { code: 'NOT_FOUND', message: `No route for ${method} ${pathname}` } })\n }\n\n const { walk, instance, params } = match\n\n try {\n // Middleware\n const mwResponse = await runMiddleware(middlewareEntries, request, pathname)\n if (mwResponse) return mwResponse\n\n // Guards\n const ctx = createExecutionContext(request, instance.constructor, walk.propertyKey)\n const guardResponse = await runGuards(walk.guards, ctx, container)\n if (guardResponse) return guardResponse\n\n // Body\n const body = await resolveBody(method, request, walk)\n if (body instanceof Response) return body // validation error response\n\n // Build args\n const args = buildArgs(walk.paramEntries, { request, body, params, query: Object.fromEntries(url.searchParams) })\n\n // Redirect\n if (walk.redirect) {\n return new Response(null, { status: walk.redirect.status, headers: { location: walk.redirect.url } })\n }\n\n const handlerFn = (instance as Record<string | symbol, Function>)[walk.propertyKey]\n\n // Interceptors wrap handler\n const result = await runInterceptors(\n walk.interceptors,\n () => handlerFn.apply(instance, args) as Promise<unknown>,\n request,\n container,\n )\n\n return buildResponse(result, walk, method)\n } catch (err) {\n return runExceptionFilters(err, walk.filters, request, container)\n }\n}\n\n// ─── Guards (return Response on rejection, null on pass) ─────\n\nasync function runGuards(\n guards: Function[],\n context: ExecutionContext,\n container?: DiContainer,\n): Promise<Response | null> {\n for (const GuardCtor of guards) {\n const guard = resolveOrNew(GuardCtor, container) as CanActivate\n const allowed = await guard.canActivate(context)\n if (!allowed) {\n const ex = new ForbiddenException('Forbidden resource')\n return jsonResponse(ex.statusCode, ex.toJSON())\n }\n }\n return null\n}\n\n// ─── Body resolution ─────────────────────────────────────────\n\nasync function resolveBody(method: string, request: Request, walk: WalkResult): Promise<unknown> {\n if (!['POST', 'PUT', 'PATCH'].includes(method)) return undefined\n\n let body: unknown\n try {\n const text = await request.text()\n body = text ? JSON.parse(text) : undefined\n } catch {\n body = undefined\n }\n\n if (walk.bodySchema && body !== undefined) {\n const result = walk.bodySchema.safeParse(body)\n if (!result.success) {\n return jsonResponse(422, { error: { code: 'VALIDATION_ERROR', issues: result.error.issues } })\n }\n body = result.data\n }\n return body\n}\n\n// ─── Response builder ────────────────────────────────────────\n\nfunction buildResponse(result: unknown, walk: WalkResult, method: string): Response {\n const status = walk.status ?? (method === 'POST' ? 201 : 200)\n const headers: Record<string, string> = { 'content-type': 'application/json' }\n for (const [name, value] of walk.headers) {\n headers[name.toLowerCase()] = value\n }\n\n if (result === undefined || result === null) {\n return new Response(null, { status: status === 200 ? 204 : status, headers })\n }\n\n if (typeof result === 'string') {\n headers['content-type'] = 'text/plain'\n return new Response(result, { status, headers })\n }\n\n return new Response(JSON.stringify(result), { status, headers })\n}\n\nfunction jsonResponse(status: number, body: unknown): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n// ─── Route matching ──────────────────────────────────────────\n\ninterface RouteMatch {\n walk: WalkResult\n instance: object\n params: Record<string, string>\n}\n\nfunction findRoute(\n routes: { walk: WalkResult; instance: object }[],\n method: string,\n pathname: string,\n): RouteMatch | null {\n for (const { walk, instance } of routes) {\n if (walk.verb !== 'ALL' && walk.verb !== method) continue\n const params = matchPath(walk.fullPath, pathname)\n if (params !== null) return { walk, instance, params }\n }\n return null\n}\n\nfunction matchPath(pattern: string, pathname: string): Record<string, string> | null {\n const paramNames: string[] = []\n const regexStr = pattern.replace(/:(\\w+)/g, (_m, name: string) => {\n paramNames.push(name)\n return '([^/]+)'\n })\n const match = new RegExp(`^${regexStr}$`).exec(pathname)\n if (!match) return null\n const params: Record<string, string> = {}\n paramNames.forEach((name, i) => { params[name] = match[i + 1] })\n return params\n}\n\n// ─── Argument builder ────────────────────────────────────────\n\ninterface ArgContext {\n request: Request\n body: unknown\n params: Record<string, string>\n query: Record<string, string>\n}\n\nfunction buildArgs(paramEntries: ParamEntry[], ctx: ArgContext): unknown[] {\n if (paramEntries.length === 0) return []\n const maxIndex = Math.max(...paramEntries.map((p) => p.index))\n const args: unknown[] = Array.from({ length: maxIndex + 1 }, () => undefined)\n for (const p of paramEntries) {\n switch (p.source) {\n case 'req':\n args[p.index] = ctx.request\n break\n case 'body':\n args[p.index] = p.key ? (ctx.body as Record<string, unknown>)[p.key] : ctx.body\n break\n case 'param':\n args[p.index] = p.key ? ctx.params[p.key] : ctx.params\n break\n case 'query':\n args[p.index] = p.key ? ctx.query[p.key] : ctx.query\n break\n case 'headers':\n args[p.index] = p.key ? ctx.request.headers.get(p.key.toLowerCase()) : Object.fromEntries(ctx.request.headers.entries())\n break\n case 'ip':\n args[p.index] = ctx.request.headers.get('x-forwarded-for') ?? '127.0.0.1'\n break\n case 'session':\n args[p.index] = undefined\n break\n default:\n args[p.index] = undefined\n }\n }\n return args\n}\n","/**\n * Typed Client — end-to-end type inference from route contracts.\n *\n * Zero codegen, zero runtime overhead on types. The developer defines\n * a route map using `contract()`, and `createTypedClient<T>()` infers\n * request body + response types automatically.\n */\nimport type { z } from 'zod'\n\n// ── Route Map types ──\n\nexport interface RouteDefinition {\n body?: z.ZodType\n params?: Record<string, 'string' | 'number'>\n query?: Record<string, 'string' | 'number' | 'boolean'>\n response: unknown\n}\n\nexport type RouteMap = Record<string, RouteDefinition>\n\n// ── Type extraction ──\n\ntype InferBody<D> = D extends { body: z.ZodType } ? z.infer<D['body']> : never\ntype InferResponse<D> = D extends { response: infer R } ? R : unknown\n\n// ── Client interface (simplified — works with strict DTS) ──\n\nexport interface TypedClient<M extends RouteMap> {\n get<P extends string & keyof M>(\n path: P,\n opts?: { query?: Record<string, string>; headers?: Record<string, string> },\n ): Promise<InferResponse<M[`GET ${P}`] extends never ? M[P] : M[`GET ${P}`]>>\n\n post<P extends string>(\n path: P,\n body?: InferBody<M[`POST ${P}`]>,\n opts?: { headers?: Record<string, string> },\n ): Promise<InferResponse<M[`POST ${P}`]>>\n\n put<P extends string>(\n path: P,\n body?: InferBody<M[`PUT ${P}`]>,\n opts?: { headers?: Record<string, string> },\n ): Promise<InferResponse<M[`PUT ${P}`]>>\n\n delete<P extends string>(\n path: P,\n opts?: { headers?: Record<string, string> },\n ): Promise<InferResponse<M[`DELETE ${P}`]>>\n}\n\n// ── Client factory ──\n\nexport function createTypedClient<M extends RouteMap>(\n baseUrl: string,\n defaultHeaders?: Record<string, string>,\n): TypedClient<M> {\n async function request(\n method: string,\n path: string,\n body?: unknown,\n opts?: { headers?: Record<string, string>; query?: Record<string, string> },\n ) {\n const url = new URL(path, baseUrl)\n if (opts?.query) {\n for (const [k, v] of Object.entries(opts.query)) url.searchParams.set(k, v)\n }\n const headers: Record<string, string> = { ...defaultHeaders, ...opts?.headers }\n if (body !== undefined) headers['content-type'] = 'application/json'\n\n const res = await fetch(url.toString(), {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n\n if (!res.ok) {\n const error = await res.json().catch(() => ({ message: res.statusText }))\n throw new TypedClientError(res.status, error as Record<string, unknown>)\n }\n\n if (res.status === 204) return undefined\n return res.json()\n }\n\n return {\n get: (path: string, opts?: Record<string, unknown>) => request('GET', path, undefined, opts),\n post: (path: string, body?: unknown, opts?: Record<string, unknown>) =>\n request('POST', path, body, opts),\n put: (path: string, body?: unknown, opts?: Record<string, unknown>) =>\n request('PUT', path, body, opts),\n delete: (path: string, opts?: Record<string, unknown>) =>\n request('DELETE', path, undefined, opts),\n } as TypedClient<M>\n}\n\nexport class TypedClientError extends Error {\n constructor(\n public readonly status: number,\n public readonly body: Record<string, unknown>,\n ) {\n super(`HTTP ${status}: ${JSON.stringify(body)}`)\n this.name = 'TypedClientError'\n }\n}\n","/**\n * Route Contract — type-level bridge between @Controller and TypedClient.\n *\n * The developer defines a contract object mapping routes to their types.\n * This object is the single source of truth for both server validation\n * and client type inference.\n *\n * @example\n * ```ts\n * // server/contracts.ts — shared between server and client\n * import { z } from 'zod'\n * import { contract } from '@theokit/http'\n *\n * export const zCreateTask = z.object({\n * title: z.string().min(3),\n * priority: z.enum(['low', 'medium', 'high']).default('medium'),\n * })\n *\n * export interface Task { id: number; title: string; priority: string; done: boolean }\n *\n * export const routes = contract({\n * 'GET /api/tasks': { response: [] as Task[] },\n * 'GET /api/tasks/:id': { response: {} as Task },\n * 'POST /api/tasks': { body: zCreateTask, response: {} as Task },\n * 'PUT /api/tasks/:id': { body: z.object({ done: z.boolean() }), response: {} as Task },\n * 'DELETE /api/tasks/:id': { response: undefined as void },\n * })\n * export type AppRoutes = typeof routes\n * ```\n *\n * The `contract()` function is identity at runtime (zero overhead) but\n * enforces the RouteMap type at the type level, enabling full inference.\n */\nimport type { RouteMap } from './typed-client.js'\n\n/**\n * Identity function that enforces RouteMap type constraint.\n * Zero runtime overhead — exists only for type inference.\n */\nexport function contract<T extends RouteMap>(routes: T): T {\n return routes\n}\n"],"mappings":"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","names":["inferPrefix","className","stripped","replace","kebab","toLowerCase","Controller","prefixOrOpts","maybeOpts","target","prefix","opts","name","setMeta","CONTROLLER_PREFIX","host","makeVerbDecorator","verb","path","target","propertyKey","existing","getMeta","ROUTE_METHODS","push","setMeta","Get","Post","Put","Patch","Delete","Options","Head","All","isZodSchema","v","undefined","safeParse","makeParamDecorator","source","keyOrSchema","target","propertyKey","parameterIndex","map","getMeta","ROUTE_PARAMS","Map","entries","get","entry","index","key","schema","push","set","setMeta","Req","Body","Param","Query","Headers","Session","Ip","HostParam","Res","opts","passthrough","HttpCode","status","target","propertyKey","setMeta","ROUTE_STATUS","Header","name","value","existing","getMeta","ROUTE_HEADERS","push","Redirect","url","ROUTE_REDIRECT","UseGuards","guards","target","propertyKey","actualTarget","existing","getMeta","USE_GUARDS","setMeta","UseInterceptors","interceptors","USE_INTERCEPTORS","UseFilters","filters","USE_FILTERS","Catch","exceptions","CATCH_EXCEPTIONS","decoratorKeyCounter","createDecorator","key","Symbol","for","decorator","value","target","propertyKey","metaTarget","undefined","Reflect","defineMetadata","SetMetadata","metaKey","Reflector","get","getMetadata","getByKey","getAllAndOverride","methodLevel","getAllAndOverrideByKey","getAllAndMerge","result","Array","isArray","push","classLevel","THROTTLE_KEY","Symbol","for","SKIP_THROTTLE_KEY","Throttle","options","target","propertyKey","actualTarget","undefined","setMeta","SkipThrottle","skip","getThrottleOptions","getMeta","isThrottleSkipped","registerControllers","controllers","seen","Set","unique","Ctor","has","console","warn","name","add","push","flatMap","walks","walkControllerMetadata","map","w","verb","fullPath","walkResult","createDecoratorServer","controllersOrOpts","controllers","container","configure","Array","isArray","undefined","middlewareConsumer","MiddlewareConsumerImpl","middlewareEntries","getEntries","seen","Set","unique","Ctor","has","add","push","routes","instance","resolveOrNew","walks","walkControllerMetadata","w","walk","sort","a","b","aP","fullPath","includes","bP","adapter","createNodeAdapter","handler","request","handleRequest","createServer","url","URL","method","toUpperCase","pathname","match","findRoute","jsonResponse","error","code","message","params","mwResponse","runMiddleware","ctx","createExecutionContext","propertyKey","guardResponse","runGuards","guards","body","resolveBody","Response","args","buildArgs","paramEntries","query","Object","fromEntries","searchParams","redirect","status","headers","location","handlerFn","result","runInterceptors","interceptors","apply","buildResponse","err","runExceptionFilters","filters","context","GuardCtor","guard","allowed","canActivate","ex","ForbiddenException","statusCode","toJSON","text","JSON","parse","bodySchema","safeParse","success","issues","data","name","value","toLowerCase","stringify","verb","matchPath","pattern","paramNames","regexStr","replace","_m","RegExp","exec","forEach","i","length","maxIndex","Math","max","map","p","index","from","source","key","get","entries","createTypedClient","baseUrl","defaultHeaders","request","method","path","body","opts","url","URL","query","k","v","Object","entries","searchParams","set","headers","undefined","res","fetch","toString","JSON","stringify","ok","error","json","catch","message","statusText","TypedClientError","status","get","post","put","delete","Error","name","contract","routes"]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/app.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-regexp, complexity, sonarjs/cognitive-complexity, max-depth, sonarjs/no-collapsible-if */\nimport 'reflect-metadata'\n\nimport { createExecutionContext, type CanActivate } from './bridge/execution-context.js'\nimport { createNodeAdapter } from './bridge/runtime/node.js'\nimport type { ServerHandle } from './bridge/runtime/types.js'\nimport { walkControllerMetadata, type WalkResult } from './bridge/walk-metadata.js'\nimport type { ParamEntry } from './decorators/params.js'\nimport { ForbiddenException, HttpException } from './exceptions/http-exception.js'\n\n/**\n * TheoApp — NestJS/Spring Boot-style application bootstrap.\n *\n * Internally uses Web Standard Request/Response pipeline.\n * Node adapter converts at the HTTP server boundary.\n */\n\n/** Readiness check — async function returning health status. */\nexport type ReadinessCheck = () => Promise<{ name: string; healthy: boolean; message?: string }>\n\nexport interface TheoAppOptions {\n /** Controller classes decorated with @Controller. */\n controllers: Function[]\n /** Agent classes decorated with @Agent — auto-wired with routes + SSE + tools. */\n agents?: Function[]\n /** @Module class for structured DI. */\n module?: Function\n /** Provider/toolbox classes — instantiated and injected into controllers + agents. */\n providers?: Function[]\n /** LLM API key for agent execution (reads OPENROUTER_API_KEY env if not set). */\n llmApiKey?: string\n /** LLM model override (default: from @Agent({ model }) metadata). */\n llmModel?: string\n /** Agent stream factory override (for testing or custom SDK wiring). */\n agentStreamFactory?: (\n walk: unknown,\n tools: unknown[],\n apiKey: string,\n model?: string,\n ) => (message: string, sessionId: string) => AsyncIterable<unknown>\n /** HTML string to serve at GET / (inline frontend). */\n html?: string\n /** Readiness checks for GET /__theo/ready (K8s readiness probe). */\n readinessChecks?: ReadinessCheck[]\n /** Custom health endpoint path (default: '/__theo/health'). */\n healthPath?: string\n /** Custom readiness endpoint path (default: '/__theo/ready'). */\n readyPath?: string\n}\n\ninterface RouteEntry {\n walk: WalkResult\n instance: object\n /** Pre-compiled regex + param names (Elysia-inspired: compile once at create, not per-request). */\n compiledPattern?: RegExp\n compiledParamNames?: string[]\n /** Whether handler needs body parsing (skip for GET/DELETE without @Body). */\n needsBody?: boolean\n}\n\nexport class TheoApp {\n private serverHandle: ServerHandle\n private readonly routes: RouteEntry[] = []\n private frontendHtml?: string\n private readonly startTime = Date.now()\n private readonly healthPath: string\n private readonly readyPath: string\n private readonly readinessChecks: ReadinessCheck[]\n\n private constructor(opts?: Pick<TheoAppOptions, 'readinessChecks' | 'healthPath' | 'readyPath'>) {\n const hp = opts?.healthPath ?? '/__theo/health'\n const rp = opts?.readyPath ?? '/__theo/ready'\n // Security: prevent health paths from colliding with user API routes\n if (hp.startsWith('/api/'))\n throw new Error(\n `[TheoApp] healthPath \"${hp}\" must not start with /api/ — would collide with user routes`,\n )\n if (rp.startsWith('/api/'))\n throw new Error(\n `[TheoApp] readyPath \"${rp}\" must not start with /api/ — would collide with user routes`,\n )\n this.healthPath = hp\n this.readyPath = rp\n this.readinessChecks = opts?.readinessChecks ?? []\n const adapter = createNodeAdapter()\n this.serverHandle = adapter.createServer((request) => this.handleRequest(request))\n }\n\n /**\n * Create a TheoKit application with Spring Boot-style DI.\n *\n * EC-7: async because Container may resolve async factories (Agent.create).\n * EC-2: Registration order guaranteed: providers → controllers → agents.\n */\n static async create(opts: TheoAppOptions): Promise<TheoApp> {\n const app = new TheoApp(opts)\n\n // ── DI Container (replaces manual Map<Function, object>) ──\n // Uses @theokit/di Container for: scopes, lifecycle, async, typed errors.\n // Fallback to manual resolution when @theokit/di is not available.\n const registry = new Map<Function, object>()\n\n // 1. Module resolution (@Module metadata)\n if (opts.module) {\n const moduleMeta = Reflect.getMetadata('usetheo:di:module', opts.module)\n if (moduleMeta) {\n const allModules = [opts.module, ...(moduleMeta.imports ?? [])]\n for (const Mod of allModules) {\n const meta = Reflect.getMetadata('usetheo:di:module', Mod)\n if (!meta) continue\n for (const Prov of (meta.providers ?? []) as Function[]) {\n if (!registry.has(Prov)) {\n registry.set(Prov, new (Prov as new () => object)())\n }\n }\n }\n }\n }\n\n // 2. Inline providers (EC-2: BEFORE controllers and agents)\n if (opts.providers) {\n for (const Prov of opts.providers) {\n if (!registry.has(Prov)) {\n registry.set(Prov, new (Prov as new () => object)())\n }\n }\n }\n\n // 3. Controllers with DI\n for (const Controller of opts.controllers) {\n const paramTypes: Function[] = Reflect.getMetadata('design:paramtypes', Controller) ?? []\n const args = paramTypes.map((pt: Function) => {\n const dep = registry.get(pt)\n if (!dep) {\n throw new Error(\n `[TheoApp] Cannot resolve ${pt.name} for ${Controller.name}. ` +\n `Add ${pt.name} to providers (or to @Module({ providers: [...] })).`,\n )\n }\n return dep\n })\n const instance = new (Controller as new (...a: unknown[]) => object)(...args)\n\n // Lifecycle: call @PostConstruct if present\n const postConstruct = Reflect.getMetadata('usetheo:di:post-construct', Controller)\n if (\n postConstruct &&\n typeof (instance as Record<string, Function>)[postConstruct] === 'function'\n ) {\n const result = (instance as Record<string, Function>)[postConstruct]()\n if (result instanceof Promise) await result // EC-1: await async PostConstruct\n }\n\n const walks = walkControllerMetadata(Controller)\n for (const w of walks) {\n app.routes.push({ walk: w, instance })\n }\n }\n\n // Sort: static before parameterized\n app.routes.sort((a, b) => {\n const aP = a.walk.fullPath.includes(':')\n const bP = b.walk.fullPath.includes(':')\n if (aP !== bP) return aP ? 1 : -1\n return 0\n })\n\n // Pre-compile route patterns (Elysia-inspired: regex built once, not per-request)\n for (const entry of app.routes) {\n const paramNames: string[] = []\n const regexStr = entry.walk.fullPath.replace(/:(\\w+)/g, (_m, name: string) => {\n paramNames.push(name)\n return '([^/]+)'\n })\n entry.compiledPattern = new RegExp(`^${regexStr}$`)\n entry.compiledParamNames = paramNames\n // Determine if handler needs body parsing (skip if no @Body decorator)\n entry.needsBody = entry.walk.paramEntries.some((p) => p.source === 'body')\n }\n\n // Bug #8: Store frontend HTML\n if (opts.html) app.frontendHtml = opts.html\n\n // 4. Auto-wire agents (EC-2: AFTER providers and controllers)\n // The framework handles EVERYTHING — walk, compile, mount, stream.\n // Consumer writes: agents: [MyAgent] — and that's it.\n if (opts.agents?.length) {\n await app.autoWireAgents(opts.agents, registry, opts)\n }\n\n return app\n }\n\n async listen(port: number): Promise<void> {\n return new Promise((resolve) => {\n this.serverHandle.listen(port, () => {\n console.log(`TheoKit app listening on http://localhost:${port}`)\n resolve()\n })\n })\n }\n\n getServerHandle(): ServerHandle {\n return this.serverHandle\n }\n\n async close(): Promise<void> {\n return new Promise((resolve) => {\n this.serverHandle.close(() => {\n resolve()\n })\n })\n }\n\n // ── Auto-wire agents (the \"SpringApplication.run()\" moment) ──\n\n private agentRoutes: {\n method: string\n pattern: RegExp\n paramNames: string[]\n handler: (request: Request) => Promise<Response>\n guards: Function[]\n agentClass: Function\n methodName: string | symbol\n }[] = []\n\n private async autoWireAgents(\n agentClasses: Function[],\n registry: Map<Function, object>,\n opts: TheoAppOptions,\n ) {\n // Dynamic import — @theokit/agents is optional peer dependency\n // SECURITY: new Function used for dynamic import of optional peer dep.\n // Argument is HARDCODED ('@theokit/agents'), never user input. Safe.\n // eslint-disable-next-line @typescript-eslint/no-implied-eval -- dynamic import avoids compile-time dependency on optional peer\n const importFn = new Function('specifier', 'return import(specifier)') as (\n s: string,\n ) => Promise<Record<string, Function>>\n let walkAgentMetadata: Function,\n compileAgent: Function,\n generateAgentRoutes: Function,\n getMixins: Function,\n createSdkAgentStreamFn: Function\n try {\n const mod = await importFn('@theokit/agents')\n walkAgentMetadata = mod.walkAgentMetadata\n compileAgent = mod.compileAgent\n generateAgentRoutes = mod.generateAgentRoutes\n getMixins = mod.getMixins\n createSdkAgentStreamFn = mod.createSdkAgentStream\n } catch {\n throw new Error(\n '[TheoApp] @theokit/agents is required when agents[] is provided. Install: npm install @theokit/agents',\n )\n }\n\n const apiKey = opts.llmApiKey ?? process.env.OPENROUTER_API_KEY ?? ''\n\n for (const AgentClass of agentClasses) {\n // 1. Walk metadata (decorators → structured data)\n const mixins = getMixins(AgentClass)\n const allToolboxes = [...mixins]\n\n // Also check providers for @Toolbox classes\n for (const [Cls] of registry) {\n if (Reflect.getMetadata(Symbol.for('theokit:agents:toolbox'), Cls)) {\n if (!allToolboxes.includes(Cls)) allToolboxes.push(Cls)\n }\n }\n\n const walk = walkAgentMetadata(AgentClass, allToolboxes)\n\n // 2. Resolve toolbox instances from registry (DI)\n const toolboxInstances = new Map<Function, object>()\n for (const tb of walk.toolboxes) {\n let instance = registry.get(tb.class)\n if (!instance) {\n instance = new (tb.class as new () => object)()\n registry.set(tb.class, instance)\n }\n toolboxInstances.set(tb.class, instance)\n }\n\n // 3. Compile tools (decorator metadata → defineTool-compatible)\n const compiled = compileAgent(walk, toolboxInstances)\n\n // 4. Create SDK agent stream factory\n let createRun: (message: string, sessionId: string) => AsyncIterable<unknown>\n\n if (opts.agentStreamFactory) {\n createRun = opts.agentStreamFactory(walk, compiled.tools, apiKey, opts.llmModel)\n } else if (apiKey) {\n // SDK adapter: bridges @theokit/agents decorators → @theokit/sdk runtime\n createRun = createSdkAgentStreamFn(walk, compiled.tools, apiKey, opts.llmModel) as (\n m: string,\n s: string,\n ) => AsyncIterable<unknown>\n } else {\n createRun = this.createFallbackStream(walk.agentConfig.name, apiKey)\n }\n\n // 5. Generate routes (POST /chat, GET /runs/:id)\n const routes = generateAgentRoutes({\n walkResult: walk,\n compiledOptions: compiled,\n createRun: createRun as (\n message: string,\n sessionId: string,\n ) => AsyncIterable<{ type: string; [k: string]: unknown }>,\n })\n\n // 6. Mount routes\n for (const route of routes) {\n const paramNames: string[] = []\n const regexStr = route.path.replace(/:(\\w+)/g, (_m: string, name: string) => {\n paramNames.push(name)\n return '([^/]+)'\n })\n this.agentRoutes.push({\n method: route.method,\n pattern: new RegExp(`^${regexStr}$`),\n paramNames,\n handler: route.handler,\n guards: walk.guards ?? [],\n agentClass: AgentClass,\n methodName: walk.mainLoop?.propertyKey ?? 'run',\n })\n }\n\n console.log(\n ` 🤖 Agent \"${walk.agentConfig.name}\" mounted at ${walk.route}/chat (${compiled.tools.length} tools)`,\n )\n }\n }\n\n private async handleReadinessCheck(): Promise<Response> {\n if (this.readinessChecks.length === 0) {\n return jsonResponse(200, { status: 'ready', checks: [] })\n }\n const results = await Promise.all(\n this.readinessChecks.map(async (check) => {\n try {\n return await Promise.race([\n check(),\n new Promise<{ name: string; healthy: boolean; message?: string }>((resolve) =>\n setTimeout(\n () =>\n resolve({\n name: 'unknown',\n healthy: false,\n message: 'Readiness check timed out (5s)',\n }),\n 5000,\n ),\n ),\n ])\n } catch (err) {\n return {\n name: 'unknown',\n healthy: false,\n message: err instanceof Error ? err.message : 'Check failed',\n }\n }\n }),\n )\n const allHealthy = results.every((r) => r.healthy)\n return jsonResponse(allHealthy ? 200 : 503, {\n status: allHealthy ? 'ready' : 'not_ready',\n checks: results,\n })\n }\n\n private createFallbackStream(agentName: string, apiKey: string) {\n const msg = !apiKey\n ? 'Set OPENROUTER_API_KEY environment variable or pass llmApiKey to TheoApp.create()'\n : 'Pass agentStreamFactory to TheoApp.create() to connect your LLM provider'\n return (_message: string, _sessionId: string) => {\n const events = [\n { type: 'run_started', runId: `run-${Date.now()}`, agentName },\n { type: 'error', code: 'AGENT_NOT_WIRED', message: msg, retryable: false },\n ]\n return {\n [Symbol.asyncIterator]: () => {\n let i = 0\n return {\n next: () =>\n Promise.resolve(\n i < events.length\n ? { value: events[i++], done: false as const }\n : { value: undefined, done: true as const },\n ),\n }\n },\n }\n }\n }\n\n // ── Web Standard request handler ──────────────────\n\n private async handleRequest(request: Request): Promise<Response> {\n const pathname = new URL(request.url).pathname\n\n // ── Health & Readiness probes (bypass guards/interceptors) ──\n if (request.method === 'GET') {\n if (pathname === this.healthPath) {\n return jsonResponse(200, {\n status: 'ok',\n uptime: (Date.now() - this.startTime) / 1000,\n timestamp: Date.now(),\n })\n }\n if (pathname === this.readyPath) {\n return this.handleReadinessCheck()\n }\n }\n\n // Bug #8: Serve frontend HTML at GET /\n if (request.method === 'GET') {\n if ((pathname === '/' || pathname === '/index.html') && this.frontendHtml) {\n return new Response(this.frontendHtml, {\n status: 200,\n headers: { 'content-type': 'text/html; charset=utf-8' },\n })\n }\n }\n\n // Agent routes (auto-wired — checked first, with guard enforcement per Bug #4)\n for (const route of this.agentRoutes) {\n if (request.method.toUpperCase() === route.method && route.pattern.test(pathname)) {\n // Bug #4 fix: enforce @UseGuards on agent routes (same pipeline as controllers)\n if (route.guards.length > 0) {\n const ctx = createExecutionContext(request, route.agentClass, route.methodName)\n for (const GuardCtor of route.guards) {\n const guard = new (GuardCtor as new () => CanActivate)()\n if (!(await guard.canActivate(ctx))) {\n const ex = new ForbiddenException('Forbidden resource')\n return jsonResponse(ex.statusCode, ex.toJSON())\n }\n }\n }\n return route.handler(request)\n }\n }\n\n const url = new URL(request.url)\n const method = request.method.toUpperCase()\n\n const match = this.findRoute(method, url.pathname)\n if (!match) {\n return jsonResponse(404, {\n error: { code: 'NOT_FOUND', message: `No route for ${method} ${url.pathname}` },\n })\n }\n\n const { entry, params } = match\n\n try {\n // Guards\n const ctx = createExecutionContext(\n request,\n entry.instance.constructor,\n entry.walk.propertyKey,\n )\n for (const GuardCtor of entry.walk.guards) {\n const guard = new (GuardCtor as new () => CanActivate)()\n if (!(await guard.canActivate(ctx))) {\n const ex = new ForbiddenException('Forbidden resource')\n return jsonResponse(ex.statusCode, ex.toJSON())\n }\n }\n\n // Body — skip parsing entirely if handler has no @Body decorator (Elysia-inspired lazy parsing)\n let body: unknown\n if (entry.needsBody && ['POST', 'PUT', 'PATCH'].includes(method)) {\n try {\n const text = await request.text()\n body = text ? JSON.parse(text) : undefined\n } catch {\n body = undefined\n }\n\n if (entry.walk.bodySchema && body !== undefined) {\n const result = entry.walk.bodySchema.safeParse(body)\n if (!result.success) {\n return jsonResponse(422, {\n error: { code: 'VALIDATION_ERROR', issues: result.error.issues },\n })\n }\n body = result.data\n }\n }\n\n // Args\n const args = this.buildArgs(\n entry.walk.paramEntries,\n request,\n body,\n params,\n Object.fromEntries(url.searchParams),\n )\n\n // Redirect\n if (entry.walk.redirect) {\n return new Response(null, {\n status: entry.walk.redirect.status,\n headers: { location: entry.walk.redirect.url },\n })\n }\n\n // Handler — wrapped by interceptor chain (Bug #2 fix)\n const handlerFn = (entry.instance as Record<string | symbol, Function>)[\n entry.walk.propertyKey\n ]\n\n let result: unknown\n if (entry.walk.interceptors.length > 0) {\n // Import runInterceptors dynamically to avoid circular dep\n const { runInterceptors } = await import('./bridge/interceptor-chain.js')\n result = await runInterceptors(\n entry.walk.interceptors,\n () => handlerFn.apply(entry.instance, args) as Promise<unknown>,\n request,\n )\n } else {\n result = await handlerFn.apply(entry.instance, args)\n }\n\n return buildResponse(result, entry.walk, method)\n } catch (err) {\n // Exception filters (Bug #2 fix — filters also wired)\n if (entry.walk.filters.length > 0) {\n const { runExceptionFilters } = await import('./bridge/exception-filter-chain.js')\n return runExceptionFilters(err, entry.walk.filters, request)\n }\n // Fallback: HttpException subclasses (Bug #3 fix)\n if (err instanceof HttpException) {\n return jsonResponse(err.statusCode, err.toJSON())\n }\n // Security: never leak raw error messages to clients\n console.error('[theokit] Internal error:', err instanceof Error ? err.message : err)\n return jsonResponse(500, {\n error: { code: 'INTERNAL_SERVER_ERROR', message: 'Internal Server Error' },\n })\n }\n }\n\n private findRoute(method: string, pathname: string) {\n for (const entry of this.routes) {\n if (entry.walk.verb !== 'ALL' && entry.walk.verb !== method) continue\n // Use pre-compiled regex (built once at create time, not per-request)\n const match = entry.compiledPattern!.exec(pathname)\n if (!match) continue\n const params: Record<string, string> = {}\n entry.compiledParamNames!.forEach((name, i) => {\n params[name] = match[i + 1]\n })\n return { entry, params }\n }\n return null\n }\n\n private buildArgs(\n entries: ParamEntry[],\n request: Request,\n body: unknown,\n params: Record<string, string>,\n query: Record<string, string>,\n ): unknown[] {\n if (entries.length === 0) return []\n const max = Math.max(...entries.map((p) => p.index))\n const args: unknown[] = Array.from({ length: max + 1 }, () => undefined)\n for (const p of entries) {\n switch (p.source) {\n case 'req':\n args[p.index] = request\n break\n case 'body':\n args[p.index] = p.key ? (body as Record<string, unknown>)[p.key] : body\n break\n case 'param':\n args[p.index] = p.key ? params[p.key] : params\n break\n case 'query':\n args[p.index] = p.key ? query[p.key] : query\n break\n case 'headers':\n args[p.index] = p.key\n ? request.headers.get(p.key.toLowerCase())\n : Object.fromEntries(request.headers.entries())\n break\n case 'ip':\n args[p.index] = request.headers.get('x-forwarded-for') ?? '127.0.0.1'\n break\n default:\n args[p.index] = undefined\n }\n }\n return args\n }\n}\n\nfunction jsonResponse(status: number, body: unknown): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n\nfunction buildResponse(result: unknown, walk: WalkResult, method: string): Response {\n const status = walk.status ?? (method === 'POST' ? 201 : 200)\n const headers: Record<string, string> = { 'content-type': 'application/json' }\n for (const [n, v] of walk.headers) headers[n.toLowerCase()] = v\n\n if (result === undefined || result === null) {\n return new Response(null, { status: status === 200 ? 204 : status, headers })\n }\n if (typeof result === 'string') {\n headers['content-type'] = 'text/plain'\n return new Response(result, { status, headers })\n }\n return new Response(JSON.stringify(result), { status, headers })\n}\n"],"mappings":"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","names":["TheoApp","serverHandle","routes","frontendHtml","startTime","Date","now","healthPath","readyPath","readinessChecks","opts","hp","rp","startsWith","Error","adapter","createNodeAdapter","createServer","request","handleRequest","create","app","registry","Map","module","moduleMeta","Reflect","getMetadata","allModules","imports","Mod","meta","Prov","providers","has","set","Controller","controllers","paramTypes","args","map","pt","dep","get","name","instance","postConstruct","result","Promise","walks","walkControllerMetadata","w","push","walk","sort","a","b","aP","fullPath","includes","bP","entry","paramNames","regexStr","replace","_m","compiledPattern","RegExp","compiledParamNames","needsBody","paramEntries","some","p","source","html","agents","length","autoWireAgents","listen","port","resolve","console","log","getServerHandle","close","agentRoutes","agentClasses","importFn","Function","walkAgentMetadata","compileAgent","generateAgentRoutes","getMixins","createSdkAgentStreamFn","mod","createSdkAgentStream","apiKey","llmApiKey","process","env","OPENROUTER_API_KEY","AgentClass","mixins","allToolboxes","Cls","Symbol","for","toolboxInstances","tb","toolboxes","class","compiled","createRun","agentStreamFactory","tools","llmModel","createFallbackStream","agentConfig","walkResult","compiledOptions","route","path","method","pattern","handler","guards","agentClass","methodName","mainLoop","propertyKey","handleReadinessCheck","jsonResponse","status","checks","results","all","check","race","setTimeout","healthy","message","err","allHealthy","every","r","agentName","msg","_message","_sessionId","events","type","runId","code","retryable","asyncIterator","i","next","value","done","undefined","pathname","URL","url","uptime","timestamp","Response","headers","toUpperCase","test","ctx","createExecutionContext","GuardCtor","guard","canActivate","ex","ForbiddenException","statusCode","toJSON","match","findRoute","error","params","body","text","JSON","parse","bodySchema","safeParse","success","issues","data","buildArgs","Object","fromEntries","searchParams","redirect","location","handlerFn","interceptors","runInterceptors","apply","buildResponse","filters","runExceptionFilters","HttpException","verb","exec","forEach","entries","query","max","Math","index","Array","from","key","toLowerCase","stringify","n","v"]}
|