@forinda/kickjs-devtools 1.2.10 → 1.2.12

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/index.js CHANGED
@@ -1,330 +1 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
-
4
- // src/index.ts
5
- import "reflect-metadata";
6
-
7
- // src/adapter.ts
8
- import { Router, static as serveStatic } from "express";
9
- import { dirname, join } from "path";
10
- import { fileURLToPath } from "url";
11
- import { existsSync, readFileSync } from "fs";
12
- import { randomBytes } from "crypto";
13
- import { METADATA, ref, computed, reactive, watch, createLogger } from "@forinda/kickjs-core";
14
- var log = createLogger("DevTools");
15
- var DevToolsAdapter = class {
16
- static {
17
- __name(this, "DevToolsAdapter");
18
- }
19
- name = "DevToolsAdapter";
20
- basePath;
21
- enabled;
22
- exposeConfig;
23
- configPrefixes;
24
- errorRateThreshold;
25
- secret;
26
- // ── Reactive State ───────────────────────────────────────────────────
27
- /** Total requests received */
28
- requestCount;
29
- /** Total responses with status >= 500 */
30
- errorCount;
31
- /** Total responses with status >= 400 and < 500 */
32
- clientErrorCount;
33
- /** Server start time */
34
- startedAt;
35
- /** Computed error rate (server errors / total requests) */
36
- errorRate;
37
- /** Computed uptime in seconds */
38
- uptimeSeconds;
39
- /** Per-route latency tracking */
40
- routeLatency;
41
- // ── Internal State ───────────────────────────────────────────────────
42
- routes = [];
43
- container = null;
44
- appRef = null;
45
- adapterStatuses = {};
46
- stopErrorWatch = null;
47
- peerAdapters = [];
48
- constructor(options = {}) {
49
- this.basePath = options.basePath ?? "/_debug";
50
- this.enabled = options.enabled ?? process.env.NODE_ENV !== "production";
51
- this.exposeConfig = options.exposeConfig ?? false;
52
- this.configPrefixes = options.configPrefixes ?? [
53
- "APP_",
54
- "NODE_ENV"
55
- ];
56
- this.errorRateThreshold = options.errorRateThreshold ?? 0.5;
57
- this.peerAdapters = options.adapters ?? [];
58
- if (options.secret === false) {
59
- this.secret = false;
60
- } else if (options.secret) {
61
- this.secret = options.secret;
62
- } else {
63
- this.secret = randomBytes(16).toString("hex");
64
- }
65
- this.requestCount = ref(0);
66
- this.errorCount = ref(0);
67
- this.clientErrorCount = ref(0);
68
- this.startedAt = ref(Date.now());
69
- this.routeLatency = reactive({});
70
- this.errorRate = computed(() => this.requestCount.value > 0 ? this.errorCount.value / this.requestCount.value : 0);
71
- this.uptimeSeconds = computed(() => Math.floor((Date.now() - this.startedAt.value) / 1e3));
72
- if (options.onErrorRateExceeded) {
73
- const callback = options.onErrorRateExceeded;
74
- const threshold = this.errorRateThreshold;
75
- this.stopErrorWatch = watch(this.errorRate, (rate) => {
76
- if (rate > threshold) {
77
- callback(rate);
78
- }
79
- });
80
- } else {
81
- this.stopErrorWatch = watch(this.errorRate, (rate) => {
82
- if (rate > this.errorRateThreshold) {
83
- log.warn(`Error rate elevated: ${(rate * 100).toFixed(1)}%`);
84
- }
85
- });
86
- }
87
- }
88
- // ── Adapter Lifecycle ────────────────────────────────────────────────
89
- /**
90
- * Resolve peer adapters at request time. Prefers live adapters from the
91
- * Application registry (survives HMR rebuild) and falls back to the
92
- * constructor-provided refs.
93
- */
94
- getPeerAdapters() {
95
- const kickApp = this.appRef?.__kickApp;
96
- if (kickApp && typeof kickApp.getAdapters === "function") {
97
- return kickApp.getAdapters();
98
- }
99
- return this.peerAdapters;
100
- }
101
- beforeMount(app, container) {
102
- if (!this.enabled) return;
103
- this.appRef = app;
104
- this.container = container;
105
- this.startedAt.value = Date.now();
106
- this.routes = [];
107
- this.adapterStatuses[this.name] = "running";
108
- const router = Router();
109
- if (this.secret !== false) {
110
- const token = this.secret;
111
- router.use((req, res, next) => {
112
- const provided = req.headers["x-devtools-token"] ?? req.query?.token;
113
- if (provided === token) return next();
114
- if (req.path === "/" && req.method === "GET" && !req.query?.token) {
115
- return next();
116
- }
117
- if (req.path.endsWith(".js") || req.path.endsWith(".css")) {
118
- return next();
119
- }
120
- res.status(403).json({
121
- error: "Forbidden \u2014 invalid or missing devtools token"
122
- });
123
- });
124
- }
125
- router.get("/routes", (_req, res) => {
126
- res.json({
127
- routes: this.routes
128
- });
129
- });
130
- router.get("/container", (_req, res) => {
131
- const registrations = this.container?.getRegistrations() ?? [];
132
- res.json({
133
- registrations,
134
- count: registrations.length
135
- });
136
- });
137
- router.get("/metrics", (_req, res) => {
138
- res.json({
139
- requests: this.requestCount.value,
140
- serverErrors: this.errorCount.value,
141
- clientErrors: this.clientErrorCount.value,
142
- errorRate: this.errorRate.value,
143
- uptimeSeconds: this.uptimeSeconds.value,
144
- startedAt: new Date(this.startedAt.value).toISOString(),
145
- routeLatency: this.routeLatency
146
- });
147
- });
148
- router.get("/health", (_req, res) => {
149
- const healthy = this.errorRate.value < this.errorRateThreshold;
150
- const status = healthy ? "healthy" : "degraded";
151
- res.status(healthy ? 200 : 503).json({
152
- status,
153
- errorRate: this.errorRate.value,
154
- uptime: this.uptimeSeconds.value,
155
- adapters: this.adapterStatuses
156
- });
157
- });
158
- router.get("/state", (_req, res) => {
159
- const wsAdapter = this.getPeerAdapters().find((a) => a.name === "WsAdapter" && typeof a.getStats === "function");
160
- res.json({
161
- reactive: {
162
- requestCount: this.requestCount.value,
163
- errorCount: this.errorCount.value,
164
- clientErrorCount: this.clientErrorCount.value,
165
- errorRate: this.errorRate.value,
166
- uptimeSeconds: this.uptimeSeconds.value,
167
- startedAt: new Date(this.startedAt.value).toISOString()
168
- },
169
- routes: this.routes.length,
170
- container: this.container?.getRegistrations().length ?? 0,
171
- routeLatency: this.routeLatency,
172
- ...wsAdapter ? {
173
- ws: wsAdapter.getStats()
174
- } : {}
175
- });
176
- });
177
- router.get("/ws", (_req, res) => {
178
- const wsAdapter = this.getPeerAdapters().find((a) => a.name === "WsAdapter" && typeof a.getStats === "function");
179
- if (!wsAdapter) {
180
- res.json({
181
- enabled: false,
182
- message: "WsAdapter not found"
183
- });
184
- return;
185
- }
186
- res.json({
187
- enabled: true,
188
- ...wsAdapter.getStats()
189
- });
190
- });
191
- router.get("/queues", async (_req, res) => {
192
- const queueAdapter = this.getPeerAdapters().find((a) => a.name === "QueueAdapter" && typeof a.getQueueNames === "function");
193
- if (!queueAdapter) {
194
- res.json({
195
- enabled: false,
196
- message: "QueueAdapter not found"
197
- });
198
- return;
199
- }
200
- try {
201
- const names = queueAdapter.getQueueNames?.() ?? [];
202
- const queues = [];
203
- for (const name of names) {
204
- const stats = await queueAdapter.getQueueStats?.(name);
205
- queues.push({
206
- name,
207
- ...stats
208
- });
209
- }
210
- res.json({
211
- enabled: true,
212
- queues
213
- });
214
- } catch {
215
- res.json({
216
- enabled: true,
217
- queues: [],
218
- error: "Failed to fetch queue stats"
219
- });
220
- }
221
- });
222
- if (this.exposeConfig) {
223
- router.get("/config", (_req, res) => {
224
- const config = {};
225
- for (const [key, value] of Object.entries(process.env)) {
226
- if (value === void 0) continue;
227
- const allowed = this.configPrefixes.some((prefix) => key.startsWith(prefix));
228
- config[key] = allowed ? value : "[REDACTED]";
229
- }
230
- res.json({
231
- config
232
- });
233
- });
234
- }
235
- const publicDir = this.resolvePublicDir();
236
- if (publicDir) {
237
- router.use(serveStatic(publicDir));
238
- const indexHtml = readFileSync(join(publicDir, "index.html"), "utf-8");
239
- router.get("/", (_req, res) => {
240
- const html = indexHtml.replace("<body", `<body data-base="${this.basePath}"`);
241
- res.type("html").send(html);
242
- });
243
- } else {
244
- router.get("/", (_req, res) => {
245
- res.type("html").send("<h1>DevTools: public directory not found</h1>");
246
- });
247
- }
248
- app.use(this.basePath, router);
249
- if (this.secret) {
250
- log.info(`DevTools mounted at ${this.basePath} [token: ${this.secret}]`);
251
- log.info(`Access: ${this.basePath}?token=${this.secret}`);
252
- } else {
253
- log.info(`DevTools mounted at ${this.basePath} [no guard]`);
254
- }
255
- }
256
- middleware() {
257
- if (!this.enabled) return [];
258
- return [
259
- {
260
- handler: /* @__PURE__ */ __name((req, res, next) => {
261
- const start = Date.now();
262
- this.requestCount.value++;
263
- res.on("finish", () => {
264
- if (res.statusCode >= 500) this.errorCount.value++;
265
- else if (res.statusCode >= 400) this.clientErrorCount.value++;
266
- const routeKey = `${req.method} ${req.route?.path ?? req.path}`;
267
- const elapsed = Date.now() - start;
268
- if (!this.routeLatency[routeKey]) {
269
- this.routeLatency[routeKey] = {
270
- count: 0,
271
- totalMs: 0,
272
- minMs: Infinity,
273
- maxMs: 0
274
- };
275
- }
276
- const stats = this.routeLatency[routeKey];
277
- stats.count++;
278
- stats.totalMs += elapsed;
279
- stats.minMs = Math.min(stats.minMs, elapsed);
280
- stats.maxMs = Math.max(stats.maxMs, elapsed);
281
- });
282
- next();
283
- }, "handler"),
284
- phase: "beforeGlobal"
285
- }
286
- ];
287
- }
288
- onRouteMount(controllerClass, mountPath) {
289
- if (!this.enabled) return;
290
- const routes = Reflect.getMetadata(METADATA.ROUTES, controllerClass) ?? [];
291
- const classMiddleware = Reflect.getMetadata(METADATA.CLASS_MIDDLEWARES, controllerClass) ?? [];
292
- for (const route of routes) {
293
- const methodMiddleware = Reflect.getMetadata(METADATA.METHOD_MIDDLEWARES, controllerClass.prototype, route.handlerName) ?? [];
294
- this.routes.push({
295
- method: route.method.toUpperCase(),
296
- path: `${mountPath}${route.path === "/" ? "" : route.path}`,
297
- controller: controllerClass.name,
298
- handler: route.handlerName,
299
- middleware: [
300
- ...classMiddleware.map((m) => m.name || "anonymous"),
301
- ...methodMiddleware.map((m) => m.name || "anonymous")
302
- ]
303
- });
304
- }
305
- }
306
- afterStart(_server, _container) {
307
- if (!this.enabled) return;
308
- log.info(`DevTools ready \u2014 ${this.routes.length} routes tracked, ${this.container?.getRegistrations().length ?? 0} DI bindings`);
309
- }
310
- shutdown() {
311
- this.stopErrorWatch?.();
312
- this.adapterStatuses[this.name] = "stopped";
313
- }
314
- /** Find the public/devtools directory relative to the built dist or source */
315
- resolvePublicDir() {
316
- const thisDir = dirname(fileURLToPath(import.meta.url));
317
- const candidates = [
318
- join(thisDir, "..", "public", "devtools"),
319
- join(thisDir, "..", "..", "public", "devtools")
320
- ];
321
- for (const dir of candidates) {
322
- if (existsSync(join(dir, "index.html"))) return dir;
323
- }
324
- return null;
325
- }
326
- };
327
- export {
328
- DevToolsAdapter
329
- };
330
- //# sourceMappingURL=index.js.map
1
+ var R=Object.defineProperty;var p=(v,t)=>R(v,"name",{value:t,configurable:!0});import"reflect-metadata";import{Router as y,static as E}from"express";import{dirname as S,join as c}from"path";import{fileURLToPath as D}from"url";import{existsSync as C,readFileSync as M}from"fs";import{randomBytes as x}from"crypto";import{METADATA as m,ref as l,computed as b,reactive as P,watch as A,createLogger as w}from"@forinda/kickjs-core";var h=w("DevTools"),g=class{static{p(this,"DevToolsAdapter")}name="DevToolsAdapter";basePath;enabled;exposeConfig;configPrefixes;errorRateThreshold;secret;requestCount;errorCount;clientErrorCount;startedAt;errorRate;uptimeSeconds;routeLatency;routes=[];container=null;appRef=null;adapterStatuses={};stopErrorWatch=null;peerAdapters=[];constructor(t={}){if(this.basePath=t.basePath??"/_debug",this.enabled=t.enabled??process.env.NODE_ENV!=="production",this.exposeConfig=t.exposeConfig??!1,this.configPrefixes=t.configPrefixes??["APP_","NODE_ENV"],this.errorRateThreshold=t.errorRateThreshold??.5,this.peerAdapters=t.adapters??[],t.secret===!1?this.secret=!1:t.secret?this.secret=t.secret:this.secret=x(16).toString("hex"),this.requestCount=l(0),this.errorCount=l(0),this.clientErrorCount=l(0),this.startedAt=l(Date.now()),this.routeLatency=P({}),this.errorRate=b(()=>this.requestCount.value>0?this.errorCount.value/this.requestCount.value:0),this.uptimeSeconds=b(()=>Math.floor((Date.now()-this.startedAt.value)/1e3)),t.onErrorRateExceeded){let n=t.onErrorRateExceeded,s=this.errorRateThreshold;this.stopErrorWatch=A(this.errorRate,i=>{i>s&&n(i)})}else this.stopErrorWatch=A(this.errorRate,n=>{n>this.errorRateThreshold&&h.warn(`Error rate elevated: ${(n*100).toFixed(1)}%`)})}getPeerAdapters(){let t=this.appRef?.__kickApp;return t&&typeof t.getAdapters=="function"?t.getAdapters():this.peerAdapters}beforeMount(t,n){if(!this.enabled)return;this.appRef=t,this.container=n,this.startedAt.value=Date.now(),this.routes=[],this.adapterStatuses[this.name]="running";let s=y();if(this.secret!==!1){let o=this.secret;s.use((e,r,a)=>{if((e.headers["x-devtools-token"]??e.query?.token)===o||e.path==="/"&&e.method==="GET"&&!e.query?.token||e.path.endsWith(".js")||e.path.endsWith(".css"))return a();r.status(403).json({error:"Forbidden \u2014 invalid or missing devtools token"})})}s.get("/routes",(o,e)=>{e.json({routes:this.routes})}),s.get("/container",(o,e)=>{let r=this.container?.getRegistrations()??[];e.json({registrations:r,count:r.length})}),s.get("/metrics",(o,e)=>{e.json({requests:this.requestCount.value,serverErrors:this.errorCount.value,clientErrors:this.clientErrorCount.value,errorRate:this.errorRate.value,uptimeSeconds:this.uptimeSeconds.value,startedAt:new Date(this.startedAt.value).toISOString(),routeLatency:this.routeLatency})}),s.get("/health",(o,e)=>{let r=this.errorRate.value<this.errorRateThreshold,a=r?"healthy":"degraded";e.status(r?200:503).json({status:a,errorRate:this.errorRate.value,uptime:this.uptimeSeconds.value,adapters:this.adapterStatuses})}),s.get("/state",(o,e)=>{let r=this.getPeerAdapters().find(a=>a.name==="WsAdapter"&&typeof a.getStats=="function");e.json({reactive:{requestCount:this.requestCount.value,errorCount:this.errorCount.value,clientErrorCount:this.clientErrorCount.value,errorRate:this.errorRate.value,uptimeSeconds:this.uptimeSeconds.value,startedAt:new Date(this.startedAt.value).toISOString()},routes:this.routes.length,container:this.container?.getRegistrations().length??0,routeLatency:this.routeLatency,...r?{ws:r.getStats()}:{}})}),s.get("/ws",(o,e)=>{let r=this.getPeerAdapters().find(a=>a.name==="WsAdapter"&&typeof a.getStats=="function");if(!r){e.json({enabled:!1,message:"WsAdapter not found"});return}e.json({enabled:!0,...r.getStats()})}),s.get("/queues",async(o,e)=>{let r=this.getPeerAdapters().find(a=>a.name==="QueueAdapter"&&typeof a.getQueueNames=="function");if(!r){e.json({enabled:!1,message:"QueueAdapter not found"});return}try{let a=r.getQueueNames?.()??[],u=[];for(let d of a){let f=await r.getQueueStats?.(d);u.push({name:d,...f})}e.json({enabled:!0,queues:u})}catch{e.json({enabled:!0,queues:[],error:"Failed to fetch queue stats"})}}),this.exposeConfig&&s.get("/config",(o,e)=>{let r={};for(let[a,u]of Object.entries(process.env)){if(u===void 0)continue;let d=this.configPrefixes.some(f=>a.startsWith(f));r[a]=d?u:"[REDACTED]"}e.json({config:r})});let i=this.resolvePublicDir();if(i){s.use(E(i));let o=M(c(i,"index.html"),"utf-8");s.get("/",(e,r)=>{let a=o.replace("<body",`<body data-base="${this.basePath}"`);r.type("html").send(a)})}else s.get("/",(o,e)=>{e.type("html").send("<h1>DevTools: public directory not found</h1>")});t.use(this.basePath,s),this.secret?(h.info(`DevTools mounted at ${this.basePath} [token: ${this.secret}]`),h.info(`Access: ${this.basePath}?token=${this.secret}`)):h.info(`DevTools mounted at ${this.basePath} [no guard]`)}middleware(){return this.enabled?[{handler:p((t,n,s)=>{let i=Date.now();this.requestCount.value++,n.on("finish",()=>{n.statusCode>=500?this.errorCount.value++:n.statusCode>=400&&this.clientErrorCount.value++;let o=`${t.method} ${t.route?.path??t.path}`,e=Date.now()-i;this.routeLatency[o]||(this.routeLatency[o]={count:0,totalMs:0,minMs:1/0,maxMs:0});let r=this.routeLatency[o];r.count++,r.totalMs+=e,r.minMs=Math.min(r.minMs,e),r.maxMs=Math.max(r.maxMs,e)}),s()},"handler"),phase:"beforeGlobal"}]:[]}onRouteMount(t,n){if(!this.enabled)return;let s=Reflect.getMetadata(m.ROUTES,t)??[],i=Reflect.getMetadata(m.CLASS_MIDDLEWARES,t)??[];for(let o of s){let e=Reflect.getMetadata(m.METHOD_MIDDLEWARES,t.prototype,o.handlerName)??[];this.routes.push({method:o.method.toUpperCase(),path:`${n}${o.path==="/"?"":o.path}`,controller:t.name,handler:o.handlerName,middleware:[...i.map(r=>r.name||"anonymous"),...e.map(r=>r.name||"anonymous")]})}}afterStart(t,n){this.enabled&&h.info(`DevTools ready \u2014 ${this.routes.length} routes tracked, ${this.container?.getRegistrations().length??0} DI bindings`)}shutdown(){this.stopErrorWatch?.(),this.adapterStatuses[this.name]="stopped"}resolvePublicDir(){let t=S(D(import.meta.url)),n=[c(t,"..","public","devtools"),c(t,"..","..","public","devtools")];for(let s of n)if(C(c(s,"index.html")))return s;return null}};export{g as DevToolsAdapter};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forinda/kickjs-devtools",
3
- "version": "1.2.10",
3
+ "version": "1.2.12",
4
4
  "description": "Development introspection dashboard for KickJS — routes, DI container, metrics, health",
5
5
  "keywords": [
6
6
  "kickjs",
@@ -27,7 +27,7 @@
27
27
  ],
28
28
  "dependencies": {
29
29
  "reflect-metadata": "^0.2.2",
30
- "@forinda/kickjs-core": "1.2.10"
30
+ "@forinda/kickjs-core": "1.2.12"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "express": "^5.1.0"
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/adapter.ts"],"sourcesContent":["import 'reflect-metadata'\n\nexport { DevToolsAdapter, type DevToolsOptions } from './adapter'\n","import type { Request, Response, NextFunction } from 'express'\nimport { Router, static as serveStatic } from 'express'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { randomBytes } from 'node:crypto'\nimport {\n type AppAdapter,\n type AdapterMiddleware,\n type Container,\n METADATA,\n ref,\n computed,\n reactive,\n watch,\n createLogger,\n type Ref,\n type ComputedRef,\n} from '@forinda/kickjs-core'\n\nconst log = createLogger('DevTools')\n\n/** Route metadata collected during mount */\ninterface RouteInfo {\n method: string\n path: string\n controller: string\n handler: string\n middleware: string[]\n}\n\n/** Per-route latency stats */\ninterface RouteStats {\n count: number\n totalMs: number\n minMs: number\n maxMs: number\n}\n\nexport interface DevToolsOptions {\n /** Base path for debug endpoints (default: '/_debug') */\n basePath?: string\n /** Only enable when this is true (default: process.env.NODE_ENV !== 'production') */\n enabled?: boolean\n /** Include environment variables (sanitized) at /_debug/config (default: false) */\n exposeConfig?: boolean\n /** Env var prefixes to expose (default: ['APP_', 'NODE_ENV']). Others are redacted. */\n configPrefixes?: string[]\n /** Callback when error rate exceeds threshold */\n onErrorRateExceeded?: (rate: number) => void\n /** Error rate threshold (default: 0.5 = 50%) */\n errorRateThreshold?: number\n /** Other adapters to discover stats from (e.g., WsAdapter) */\n adapters?: any[]\n\n /**\n * Secret token to guard DevTools access. When set, all requests must\n * include this token as `x-devtools-token` header or `?token=` query param.\n *\n * Auto-generated on startup if not provided. The token is logged to the console.\n * Set to `false` to disable the guard entirely (not recommended).\n *\n * @example\n * ```ts\n * new DevToolsAdapter({ secret: process.env.DEVTOOLS_SECRET })\n * ```\n */\n secret?: string | false\n}\n\n/**\n * DevToolsAdapter — Vue-style reactive introspection for KickJS applications.\n *\n * Exposes debug endpoints powered by reactive state (ref, computed, watch):\n * - `GET /_debug/routes` — all registered routes with middleware\n * - `GET /_debug/container` — DI registry with scopes and instantiation status\n * - `GET /_debug/metrics` — live request/error counts, error rate, uptime\n * - `GET /_debug/health` — deep health check with adapter status\n * - `GET /_debug/config` — sanitized environment variables (opt-in)\n * - `GET /_debug/state` — full reactive state snapshot\n *\n * @example\n * ```ts\n * import { DevToolsAdapter } from '@forinda/kickjs-devtools'\n *\n * bootstrap({\n * modules: [UserModule],\n * adapters: [\n * new DevToolsAdapter({\n * enabled: process.env.NODE_ENV !== 'production',\n * exposeConfig: true,\n * configPrefixes: ['APP_', 'DATABASE_'],\n * }),\n * ],\n * })\n * ```\n */\nexport class DevToolsAdapter implements AppAdapter {\n readonly name = 'DevToolsAdapter'\n\n private basePath: string\n private enabled: boolean\n private exposeConfig: boolean\n private configPrefixes: string[]\n private errorRateThreshold: number\n private secret: string | false\n\n // ── Reactive State ───────────────────────────────────────────────────\n /** Total requests received */\n readonly requestCount: Ref<number>\n /** Total responses with status >= 500 */\n readonly errorCount: Ref<number>\n /** Total responses with status >= 400 and < 500 */\n readonly clientErrorCount: Ref<number>\n /** Server start time */\n readonly startedAt: Ref<number>\n /** Computed error rate (server errors / total requests) */\n readonly errorRate: ComputedRef<number>\n /** Computed uptime in seconds */\n readonly uptimeSeconds: ComputedRef<number>\n /** Per-route latency tracking */\n readonly routeLatency: Record<string, RouteStats>\n\n // ── Internal State ───────────────────────────────────────────────────\n private routes: RouteInfo[] = []\n private container: Container | null = null\n private appRef: any = null\n private adapterStatuses: Record<string, string> = {}\n private stopErrorWatch: (() => void) | null = null\n private peerAdapters: any[] = []\n\n constructor(options: DevToolsOptions = {}) {\n this.basePath = options.basePath ?? '/_debug'\n this.enabled = options.enabled ?? process.env.NODE_ENV !== 'production'\n this.exposeConfig = options.exposeConfig ?? false\n this.configPrefixes = options.configPrefixes ?? ['APP_', 'NODE_ENV']\n this.errorRateThreshold = options.errorRateThreshold ?? 0.5\n this.peerAdapters = options.adapters ?? []\n\n // Secret token guard\n if (options.secret === false) {\n this.secret = false\n } else if (options.secret) {\n this.secret = options.secret\n } else {\n // Auto-generate a random token\n this.secret = randomBytes(16).toString('hex')\n }\n\n // Initialize reactive state\n this.requestCount = ref(0)\n this.errorCount = ref(0)\n this.clientErrorCount = ref(0)\n this.startedAt = ref(Date.now())\n this.routeLatency = reactive({})\n\n this.errorRate = computed(() =>\n this.requestCount.value > 0 ? this.errorCount.value / this.requestCount.value : 0,\n )\n\n this.uptimeSeconds = computed(() => Math.floor((Date.now() - this.startedAt.value) / 1000))\n\n // Watch error rate — log warnings when elevated\n if (options.onErrorRateExceeded) {\n const callback = options.onErrorRateExceeded\n const threshold = this.errorRateThreshold\n this.stopErrorWatch = watch(this.errorRate, (rate) => {\n if (rate > threshold) {\n callback(rate)\n }\n })\n } else {\n this.stopErrorWatch = watch(this.errorRate, (rate) => {\n if (rate > this.errorRateThreshold) {\n log.warn(`Error rate elevated: ${(rate * 100).toFixed(1)}%`)\n }\n })\n }\n }\n\n // ── Adapter Lifecycle ────────────────────────────────────────────────\n\n /**\n * Resolve peer adapters at request time. Prefers live adapters from the\n * Application registry (survives HMR rebuild) and falls back to the\n * constructor-provided refs.\n */\n private getPeerAdapters(): any[] {\n const kickApp = this.appRef?.__kickApp\n if (kickApp && typeof kickApp.getAdapters === 'function') {\n return kickApp.getAdapters()\n }\n return this.peerAdapters\n }\n\n beforeMount(app: any, container: Container): void {\n if (!this.enabled) return\n\n this.appRef = app\n this.container = container\n this.startedAt.value = Date.now()\n // Clear routes on rebuild/restart to prevent HMR duplication\n this.routes = []\n this.adapterStatuses[this.name] = 'running'\n\n const router = Router()\n\n // ── Access guard — require secret token ──────────────────────────\n if (this.secret !== false) {\n const token = this.secret\n router.use((req: Request, res: Response, next: NextFunction) => {\n const provided = req.headers['x-devtools-token'] ?? req.query?.token\n if (provided === token) return next()\n // Allow the dashboard HTML itself (it will include the token in API calls)\n if (req.path === '/' && req.method === 'GET' && !req.query?.token) {\n return next() // serve dashboard, it handles auth via token\n }\n // Serve static assets for the dashboard (js files)\n if (req.path.endsWith('.js') || req.path.endsWith('.css')) {\n return next()\n }\n res.status(403).json({ error: 'Forbidden — invalid or missing devtools token' })\n })\n }\n\n router.get('/routes', (_req: Request, res: Response) => {\n res.json({ routes: this.routes })\n })\n\n router.get('/container', (_req: Request, res: Response) => {\n const registrations = this.container?.getRegistrations() ?? []\n res.json({ registrations, count: registrations.length })\n })\n\n router.get('/metrics', (_req: Request, res: Response) => {\n res.json({\n requests: this.requestCount.value,\n serverErrors: this.errorCount.value,\n clientErrors: this.clientErrorCount.value,\n errorRate: this.errorRate.value,\n uptimeSeconds: this.uptimeSeconds.value,\n startedAt: new Date(this.startedAt.value).toISOString(),\n routeLatency: this.routeLatency,\n })\n })\n\n router.get('/health', (_req: Request, res: Response) => {\n const healthy = this.errorRate.value < this.errorRateThreshold\n const status = healthy ? 'healthy' : 'degraded'\n\n res.status(healthy ? 200 : 503).json({\n status,\n errorRate: this.errorRate.value,\n uptime: this.uptimeSeconds.value,\n adapters: this.adapterStatuses,\n })\n })\n\n router.get('/state', (_req: Request, res: Response) => {\n const wsAdapter = this.getPeerAdapters().find(\n (a) => a.name === 'WsAdapter' && typeof a.getStats === 'function',\n )\n res.json({\n reactive: {\n requestCount: this.requestCount.value,\n errorCount: this.errorCount.value,\n clientErrorCount: this.clientErrorCount.value,\n errorRate: this.errorRate.value,\n uptimeSeconds: this.uptimeSeconds.value,\n startedAt: new Date(this.startedAt.value).toISOString(),\n },\n routes: this.routes.length,\n container: this.container?.getRegistrations().length ?? 0,\n routeLatency: this.routeLatency,\n ...(wsAdapter ? { ws: wsAdapter.getStats() } : {}),\n })\n })\n\n router.get('/ws', (_req: Request, res: Response) => {\n const wsAdapter = this.getPeerAdapters().find(\n (a) => a.name === 'WsAdapter' && typeof a.getStats === 'function',\n )\n if (!wsAdapter) {\n res.json({ enabled: false, message: 'WsAdapter not found' })\n return\n }\n res.json({ enabled: true, ...wsAdapter.getStats() })\n })\n\n router.get('/queues', async (_req: Request, res: Response) => {\n const queueAdapter = this.getPeerAdapters().find(\n (a) => a.name === 'QueueAdapter' && typeof a.getQueueNames === 'function',\n )\n if (!queueAdapter) {\n res.json({ enabled: false, message: 'QueueAdapter not found' })\n return\n }\n try {\n const names: string[] = queueAdapter.getQueueNames?.() ?? []\n const queues: any[] = []\n for (const name of names) {\n const stats = await queueAdapter.getQueueStats?.(name)\n queues.push({ name, ...stats })\n }\n res.json({ enabled: true, queues })\n } catch {\n res.json({ enabled: true, queues: [], error: 'Failed to fetch queue stats' })\n }\n })\n\n if (this.exposeConfig) {\n router.get('/config', (_req: Request, res: Response) => {\n const config: Record<string, string> = {}\n for (const [key, value] of Object.entries(process.env)) {\n if (value === undefined) continue\n const allowed = this.configPrefixes.some((prefix) => key.startsWith(prefix))\n config[key] = allowed ? value : '[REDACTED]'\n }\n res.json({ config })\n })\n }\n\n // Dashboard UI — Vue + Tailwind from public/devtools directory\n const publicDir = this.resolvePublicDir()\n if (publicDir) {\n // Serve static assets (vue.global.min.js, tailwind-cdn.js)\n router.use(serveStatic(publicDir))\n\n // Serve index.html with base path injected\n const indexHtml = readFileSync(join(publicDir, 'index.html'), 'utf-8')\n router.get('/', (_req: Request, res: Response) => {\n // Inject basePath as data attribute for the Vue app\n const html = indexHtml.replace('<body', `<body data-base=\"${this.basePath}\"`)\n res.type('html').send(html)\n })\n } else {\n router.get('/', (_req: Request, res: Response) => {\n res.type('html').send('<h1>DevTools: public directory not found</h1>')\n })\n }\n\n app.use(this.basePath, router)\n\n if (this.secret) {\n log.info(`DevTools mounted at ${this.basePath} [token: ${this.secret}]`)\n log.info(`Access: ${this.basePath}?token=${this.secret}`)\n } else {\n log.info(`DevTools mounted at ${this.basePath} [no guard]`)\n }\n }\n\n middleware(): AdapterMiddleware[] {\n if (!this.enabled) return []\n\n return [\n {\n handler: (req: Request, res: Response, next: NextFunction) => {\n const start = Date.now()\n this.requestCount.value++\n\n res.on('finish', () => {\n if (res.statusCode >= 500) this.errorCount.value++\n else if (res.statusCode >= 400) this.clientErrorCount.value++\n\n // Track per-route latency\n const routeKey = `${req.method} ${req.route?.path ?? req.path}`\n const elapsed = Date.now() - start\n\n if (!this.routeLatency[routeKey]) {\n this.routeLatency[routeKey] = {\n count: 0,\n totalMs: 0,\n minMs: Infinity,\n maxMs: 0,\n }\n }\n const stats = this.routeLatency[routeKey]\n stats.count++\n stats.totalMs += elapsed\n stats.minMs = Math.min(stats.minMs, elapsed)\n stats.maxMs = Math.max(stats.maxMs, elapsed)\n })\n\n next()\n },\n phase: 'beforeGlobal',\n },\n ]\n }\n\n onRouteMount(controllerClass: any, mountPath: string): void {\n if (!this.enabled) return\n\n const routes: Array<{ method: string; path: string; handlerName: string }> =\n Reflect.getMetadata(METADATA.ROUTES, controllerClass) ?? []\n\n const classMiddleware: any[] =\n Reflect.getMetadata(METADATA.CLASS_MIDDLEWARES, controllerClass) ?? []\n\n for (const route of routes) {\n const methodMiddleware: any[] =\n Reflect.getMetadata(\n METADATA.METHOD_MIDDLEWARES,\n controllerClass.prototype,\n route.handlerName,\n ) ?? []\n\n this.routes.push({\n method: route.method.toUpperCase(),\n path: `${mountPath}${route.path === '/' ? '' : route.path}`,\n controller: controllerClass.name,\n handler: route.handlerName,\n middleware: [\n ...classMiddleware.map((m: any) => m.name || 'anonymous'),\n ...methodMiddleware.map((m: any) => m.name || 'anonymous'),\n ],\n })\n }\n }\n\n afterStart(_server: any, _container: Container): void {\n if (!this.enabled) return\n log.info(\n `DevTools ready — ${this.routes.length} routes tracked, ` +\n `${this.container?.getRegistrations().length ?? 0} DI bindings`,\n )\n }\n\n shutdown(): void {\n this.stopErrorWatch?.()\n this.adapterStatuses[this.name] = 'stopped'\n }\n\n /** Find the public/devtools directory relative to the built dist or source */\n private resolvePublicDir(): string | null {\n // Try relative to this file's location (works in dist/)\n const thisDir = dirname(fileURLToPath(import.meta.url))\n const candidates = [\n join(thisDir, '..', 'public', 'devtools'), // dist/ -> public/devtools\n join(thisDir, '..', '..', 'public', 'devtools'), // src/ -> public/devtools\n ]\n for (const dir of candidates) {\n if (existsSync(join(dir, 'index.html'))) return dir\n }\n return null\n }\n}\n"],"mappings":"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","names":["Router","static","serveStatic","dirname","join","fileURLToPath","existsSync","readFileSync","randomBytes","METADATA","ref","computed","reactive","watch","createLogger","log","createLogger","DevToolsAdapter","name","basePath","enabled","exposeConfig","configPrefixes","errorRateThreshold","secret","requestCount","errorCount","clientErrorCount","startedAt","errorRate","uptimeSeconds","routeLatency","routes","container","appRef","adapterStatuses","stopErrorWatch","peerAdapters","options","process","env","NODE_ENV","adapters","randomBytes","toString","ref","Date","now","reactive","computed","value","Math","floor","onErrorRateExceeded","callback","threshold","watch","rate","warn","toFixed","getPeerAdapters","kickApp","__kickApp","getAdapters","beforeMount","app","router","Router","token","use","req","res","next","provided","headers","query","path","method","endsWith","status","json","error","get","_req","registrations","getRegistrations","count","length","requests","serverErrors","clientErrors","toISOString","healthy","uptime","wsAdapter","find","a","getStats","ws","message","queueAdapter","getQueueNames","names","queues","stats","getQueueStats","push","config","key","Object","entries","undefined","allowed","some","prefix","startsWith","publicDir","resolvePublicDir","serveStatic","indexHtml","readFileSync","join","html","replace","type","send","info","middleware","handler","start","on","statusCode","routeKey","route","elapsed","totalMs","minMs","Infinity","maxMs","min","max","phase","onRouteMount","controllerClass","mountPath","Reflect","getMetadata","METADATA","ROUTES","classMiddleware","CLASS_MIDDLEWARES","methodMiddleware","METHOD_MIDDLEWARES","prototype","handlerName","toUpperCase","controller","map","m","afterStart","_server","_container","shutdown","thisDir","dirname","fileURLToPath","url","candidates","dir","existsSync"]}