nestjs-profiler 1.0.12 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/analyzers/explain-analyzer.d.ts +5 -0
  2. package/analyzers/explain-analyzer.js +41 -0
  3. package/analyzers/explain-analyzer.js.map +1 -0
  4. package/collectors/cache-collector.d.ts +18 -0
  5. package/collectors/cache-collector.js +175 -0
  6. package/collectors/cache-collector.js.map +1 -0
  7. package/collectors/log-collector.d.ts +12 -0
  8. package/collectors/log-collector.js +66 -0
  9. package/collectors/log-collector.js.map +1 -0
  10. package/collectors/mongo-collector.d.ts +19 -0
  11. package/collectors/mongo-collector.js +200 -0
  12. package/collectors/mongo-collector.js.map +1 -0
  13. package/collectors/mysql-collector.d.ts +12 -0
  14. package/collectors/mysql-collector.js +128 -0
  15. package/collectors/mysql-collector.js.map +1 -0
  16. package/collectors/postgres-collector.d.ts +15 -0
  17. package/collectors/postgres-collector.js +201 -0
  18. package/collectors/postgres-collector.js.map +1 -0
  19. package/common/profiler-options.interface.d.ts +20 -0
  20. package/common/profiler-options.interface.js +3 -0
  21. package/common/profiler-options.interface.js.map +1 -0
  22. package/common/profiler.model.d.ts +67 -0
  23. package/common/profiler.model.js +3 -0
  24. package/common/profiler.model.js.map +1 -0
  25. package/controllers/profiler.controller.d.ts +34 -0
  26. package/controllers/profiler.controller.js +254 -0
  27. package/controllers/profiler.controller.js.map +1 -0
  28. package/interceptors/request-profiler.interceptor.d.ts +11 -0
  29. package/interceptors/request-profiler.interceptor.js +103 -0
  30. package/interceptors/request-profiler.interceptor.js.map +1 -0
  31. package/middleware/profiler.middleware.d.ts +4 -0
  32. package/middleware/profiler.middleware.js +21 -0
  33. package/middleware/profiler.middleware.js.map +1 -0
  34. package/package.json +5 -4
  35. package/profiler-logger.d.ts +12 -0
  36. package/profiler-logger.js +59 -0
  37. package/profiler-logger.js.map +1 -0
  38. package/profiler.module.d.ts +7 -0
  39. package/profiler.module.js +105 -0
  40. package/profiler.module.js.map +1 -0
  41. package/services/entity-explorer.service.d.ts +19 -0
  42. package/services/entity-explorer.service.js +111 -0
  43. package/services/entity-explorer.service.js.map +1 -0
  44. package/services/profiler.service.d.ts +31 -0
  45. package/services/profiler.service.js +216 -0
  46. package/services/profiler.service.js.map +1 -0
  47. package/services/route-explorer.service.d.ts +15 -0
  48. package/services/route-explorer.service.js +94 -0
  49. package/services/route-explorer.service.js.map +1 -0
  50. package/services/template-builder.service.d.ts +27 -0
  51. package/services/template-builder.service.js +348 -0
  52. package/services/template-builder.service.js.map +1 -0
  53. package/services/view.service.d.ts +17 -0
  54. package/services/view.service.js +196 -0
  55. package/services/view.service.js.map +1 -0
  56. package/storage/in-memory-profiler-storage.d.ts +9 -0
  57. package/storage/in-memory-profiler-storage.js +29 -0
  58. package/storage/in-memory-profiler-storage.js.map +1 -0
  59. package/storage/profiler-storage.interface.d.ts +6 -0
  60. package/storage/profiler-storage.interface.js +3 -0
  61. package/storage/profiler-storage.interface.js.map +1 -0
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var MysqlCollector_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.MysqlCollector = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const profiler_service_1 = require("../services/profiler.service");
19
+ let MysqlCollector = MysqlCollector_1 = class MysqlCollector {
20
+ constructor(profiler, options) {
21
+ this.profiler = profiler;
22
+ this.options = options;
23
+ this.logger = new common_1.Logger(MysqlCollector_1.name);
24
+ }
25
+ onModuleInit() {
26
+ if (this.options.collectMysql === false) {
27
+ return;
28
+ }
29
+ try {
30
+ this.mysql = this.options.mysqlDriver || require('mysql2');
31
+ this.patchMysql();
32
+ this.logger.log('MysqlCollector initialized: Patching mysql2 driver');
33
+ }
34
+ catch (e) {
35
+ if (e.code === 'MODULE_NOT_FOUND') {
36
+ this.logger.debug('mysql2 driver not found, skipping MySQL profiling');
37
+ }
38
+ else {
39
+ this.logger.error('Failed to initialize MysqlCollector', e);
40
+ }
41
+ }
42
+ }
43
+ patchMysql() {
44
+ if (!this.mysql || !this.mysql.Connection) {
45
+ this.logger.warn('mysql2.Connection not found, cannot patch');
46
+ return;
47
+ }
48
+ const self = this;
49
+ const Connection = this.mysql.Connection;
50
+ const originalQuery = Connection.prototype.query;
51
+ if (!originalQuery) {
52
+ this.logger.warn('Connection.prototype.query not found');
53
+ return;
54
+ }
55
+ Connection.prototype.query = function (...args) {
56
+ const startTime = Date.now();
57
+ const config = this.config || {};
58
+ const dbName = config.database || 'unknown';
59
+ const host = config.host || 'localhost';
60
+ const port = config.port || 3306;
61
+ const connectionName = `${dbName}@${host}:${port}`;
62
+ let sql = '';
63
+ let params = [];
64
+ let callback;
65
+ if (typeof args[0] === 'string') {
66
+ sql = args[0];
67
+ if (Array.isArray(args[1])) {
68
+ params = args[1];
69
+ callback = args[2];
70
+ }
71
+ else if (typeof args[1] === 'function') {
72
+ callback = args[1];
73
+ }
74
+ }
75
+ else if (typeof args[0] === 'object') {
76
+ sql = args[0].sql || '';
77
+ params = args[0].values || [];
78
+ callback = args[1];
79
+ }
80
+ const wrappedCallback = function (err, results, fields) {
81
+ const endTime = Date.now();
82
+ const duration = endTime - startTime;
83
+ let rowCount;
84
+ if (results) {
85
+ if (Array.isArray(results)) {
86
+ rowCount = results.length;
87
+ }
88
+ else if (results.affectedRows !== undefined) {
89
+ rowCount = results.affectedRows;
90
+ }
91
+ }
92
+ const queryProfile = {
93
+ sql,
94
+ params: params.length > 0 ? params : undefined,
95
+ duration,
96
+ startTime,
97
+ rowCount,
98
+ connection: connectionName,
99
+ database: 'mysql',
100
+ error: err ? String(err.message || err) : undefined,
101
+ };
102
+ self.profiler.addQuery(queryProfile);
103
+ if (callback) {
104
+ callback(err, results, fields);
105
+ }
106
+ };
107
+ if (typeof args[0] === 'string') {
108
+ if (Array.isArray(args[1])) {
109
+ args[2] = wrappedCallback;
110
+ }
111
+ else {
112
+ args[1] = wrappedCallback;
113
+ }
114
+ }
115
+ else {
116
+ args[1] = wrappedCallback;
117
+ }
118
+ return originalQuery.apply(this, args);
119
+ };
120
+ }
121
+ };
122
+ exports.MysqlCollector = MysqlCollector;
123
+ exports.MysqlCollector = MysqlCollector = MysqlCollector_1 = __decorate([
124
+ (0, common_1.Injectable)(),
125
+ __param(1, (0, common_1.Inject)('PROFILER_OPTIONS')),
126
+ __metadata("design:paramtypes", [profiler_service_1.ProfilerService, Object])
127
+ ], MysqlCollector);
128
+ //# sourceMappingURL=mysql-collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql-collector.js","sourceRoot":"","sources":["../../../libs/nestjs-profiler/src/collectors/mysql-collector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+ import { ProfilerService } from '../services/profiler.service';
3
+ import { ExplainAnalyzer } from '../analyzers/explain-analyzer';
4
+ import type { ProfilerOptions } from '../common/profiler-options.interface';
5
+ export declare class PostgresCollector implements OnModuleInit {
6
+ private profiler;
7
+ private explainAnalyzer;
8
+ private options;
9
+ private logger;
10
+ private originalQuery;
11
+ constructor(profiler: ProfilerService, explainAnalyzer: ExplainAnalyzer, options: ProfilerOptions);
12
+ onModuleInit(): void;
13
+ private patchPg;
14
+ private captureQuery;
15
+ }
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
45
+ return function (target, key) { decorator(target, key, paramIndex); }
46
+ };
47
+ var PostgresCollector_1;
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.PostgresCollector = void 0;
50
+ const common_1 = require("@nestjs/common");
51
+ const pg = __importStar(require("pg"));
52
+ const profiler_service_1 = require("../services/profiler.service");
53
+ const explain_analyzer_1 = require("../analyzers/explain-analyzer");
54
+ const pg_1 = require("pg");
55
+ let PostgresCollector = PostgresCollector_1 = class PostgresCollector {
56
+ constructor(profiler, explainAnalyzer, options) {
57
+ this.profiler = profiler;
58
+ this.explainAnalyzer = explainAnalyzer;
59
+ this.options = options;
60
+ this.logger = new common_1.Logger(PostgresCollector_1.name);
61
+ }
62
+ onModuleInit() {
63
+ try {
64
+ this.logger.debug(`Resolved pg package at: ${require.resolve('pg')}`);
65
+ }
66
+ catch (e) { }
67
+ this.patchPg();
68
+ }
69
+ patchPg() {
70
+ const self = this;
71
+ const pgDriver = this.options.pgDriver || pg;
72
+ const client = pgDriver.Client;
73
+ if (client.prototype.query.__isPatched) {
74
+ this.logger.debug('PostgreSQL Client already patched - skipping re-patching');
75
+ return;
76
+ }
77
+ this.logger.log(`Initializing PostgreSQL Profiler: Patching ${this.options.pgDriver ? 'INJECTED' : 'LOCAL'} pg.Client.prototype.query`);
78
+ this.originalQuery = client.prototype.query;
79
+ if (!this.originalQuery) {
80
+ this.logger.warn('Failed to patch PostgreSQL: Client.prototype.query is undefined');
81
+ return;
82
+ }
83
+ client.prototype.query = function (...args) {
84
+ const clientInstance = this;
85
+ const startTime = Date.now();
86
+ let queryText = '';
87
+ let queryParams = [];
88
+ let connectionName = 'unknown';
89
+ try {
90
+ const dbName = clientInstance.database || clientInstance.connectionParameters?.database || 'unknown';
91
+ const dbHost = clientInstance.host || clientInstance.connectionParameters?.host || 'localhost';
92
+ connectionName = `${dbName}@${dbHost}`;
93
+ if (typeof args[0] === 'string') {
94
+ queryText = args[0];
95
+ if (args[1] instanceof Array) {
96
+ queryParams = args[1];
97
+ }
98
+ }
99
+ else if (typeof args[0] === 'object' && args[0] !== null) {
100
+ queryText = args[0].text || '';
101
+ queryParams = args[0].values || [];
102
+ }
103
+ }
104
+ catch (e) {
105
+ self.logger.error('Profiler query extraction failed', e);
106
+ }
107
+ if (process.env.PROFILER_DEBUG) {
108
+ self.logger.debug('[PostgresCollector] Intercepted query call');
109
+ }
110
+ let callback;
111
+ if (args.length > 0) {
112
+ const lastArg = args[args.length - 1];
113
+ if (typeof lastArg === 'function') {
114
+ callback = lastArg;
115
+ }
116
+ }
117
+ if (callback) {
118
+ const originalCallback = callback;
119
+ args[args.length - 1] = (err, result) => {
120
+ self.captureQuery(clientInstance, queryText, queryParams, connectionName, startTime, result ? result.rowCount : null, err);
121
+ originalCallback(err, result);
122
+ };
123
+ return self.originalQuery.apply(this, args);
124
+ }
125
+ else {
126
+ const resultPromise = self.originalQuery.apply(this, args);
127
+ if (resultPromise && typeof resultPromise.then === 'function') {
128
+ return resultPromise.then((result) => {
129
+ self.captureQuery(clientInstance, queryText, queryParams, connectionName, startTime, result ? result.rowCount : 0);
130
+ return result;
131
+ }, (err) => {
132
+ self.captureQuery(clientInstance, queryText, queryParams, connectionName, startTime, 0, err);
133
+ throw err;
134
+ });
135
+ }
136
+ return resultPromise;
137
+ }
138
+ };
139
+ pg_1.Client.prototype.query.__isPatched = true;
140
+ this.logger.log('PostgreSQL Client.query successfully patched');
141
+ }
142
+ captureQuery(clientInstance, queryText, queryParams, connectionName, startTime, rowCount, err) {
143
+ try {
144
+ const endTime = Date.now();
145
+ const duration = endTime - startTime;
146
+ const queryProfile = {
147
+ sql: queryText,
148
+ params: queryParams,
149
+ duration,
150
+ startTime,
151
+ rowCount: rowCount ?? undefined,
152
+ error: err?.message,
153
+ connection: connectionName,
154
+ database: 'postgres',
155
+ };
156
+ const profile = this.profiler.getCurrentProfile();
157
+ if (profile) {
158
+ this.profiler.addQuery(queryProfile);
159
+ const explainConfig = this.options.explain;
160
+ if (explainConfig?.enabled && duration >= (explainConfig.thresholdMs || 0)) {
161
+ const isExplainable = queryText && /^\s*(SELECT|INSERT|UPDATE|DELETE|WITH)/i.test(queryText) && !/^\s*EXPLAIN/i.test(queryText);
162
+ if (isExplainable) {
163
+ this.explainAnalyzer.analyze(clientInstance, queryText, queryParams, explainConfig.analyze)
164
+ .then(plan => {
165
+ if (plan) {
166
+ queryProfile.explainPlan = plan;
167
+ const planString = JSON.stringify(plan).toLowerCase();
168
+ if (planString.includes('seq scan')) {
169
+ if (!queryProfile.tags)
170
+ queryProfile.tags = [];
171
+ queryProfile.tags.push('seq-scan');
172
+ queryProfile.planType = 'Seq Scan';
173
+ }
174
+ else if (planString.includes('index scan') || planString.includes('index only scan')) {
175
+ queryProfile.planType = 'Index Scan';
176
+ }
177
+ }
178
+ })
179
+ .catch(e => {
180
+ this.logger.error('Profiler explain failed', e);
181
+ });
182
+ }
183
+ }
184
+ }
185
+ else if (process.env.PROFILER_DEBUG) {
186
+ this.logger.debug(`Query captured OUTSIDE request context: ${(queryText || 'UNKNOWN').substring(0, 50)}...`);
187
+ }
188
+ }
189
+ catch (e) {
190
+ this.logger.error('Profiler capture failed', e);
191
+ }
192
+ }
193
+ };
194
+ exports.PostgresCollector = PostgresCollector;
195
+ exports.PostgresCollector = PostgresCollector = PostgresCollector_1 = __decorate([
196
+ (0, common_1.Injectable)(),
197
+ __param(2, (0, common_1.Inject)('PROFILER_OPTIONS')),
198
+ __metadata("design:paramtypes", [profiler_service_1.ProfilerService,
199
+ explain_analyzer_1.ExplainAnalyzer, Object])
200
+ ], PostgresCollector);
201
+ //# sourceMappingURL=postgres-collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-collector.js","sourceRoot":"","sources":["../../../libs/nestjs-profiler/src/collectors/postgres-collector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { ProfilerStorage } from '../storage/profiler-storage.interface';
2
+ export interface ProfilerExplainOptions {
3
+ enabled?: boolean;
4
+ analyze?: boolean;
5
+ thresholdMs?: number;
6
+ }
7
+ export type ProfilerStorageType = 'memory' | ProfilerStorage;
8
+ export interface ProfilerOptions {
9
+ enabled?: boolean;
10
+ storage?: ProfilerStorageType;
11
+ pgDriver?: any;
12
+ mongoDriver?: any;
13
+ mysqlDriver?: any;
14
+ collectQueries?: boolean;
15
+ collectLogs?: boolean;
16
+ collectMongo?: boolean;
17
+ collectCache?: boolean;
18
+ collectMysql?: boolean;
19
+ explain?: ProfilerExplainOptions;
20
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=profiler-options.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiler-options.interface.js","sourceRoot":"","sources":["../../../libs/nestjs-profiler/src/common/profiler-options.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,67 @@
1
+ export interface QueryProfile {
2
+ sql: string;
3
+ query?: string;
4
+ database?: 'postgres' | 'mongodb' | 'mysql';
5
+ operation?: string;
6
+ filter?: any;
7
+ params?: any[];
8
+ duration: number;
9
+ startTime: number;
10
+ rowCount?: number;
11
+ error?: string;
12
+ explainPlan?: any;
13
+ connection?: string;
14
+ tags?: string[];
15
+ duplicatedCount?: number;
16
+ planType?: string;
17
+ }
18
+ export interface LogProfile {
19
+ level: string;
20
+ message: string;
21
+ context?: string;
22
+ timestamp: number;
23
+ }
24
+ export interface CacheProfile {
25
+ key: string;
26
+ store: string;
27
+ operation: 'get' | 'set' | 'del' | 'reset' | 'unknown';
28
+ result: 'hit' | 'miss' | 'success' | 'fail' | null;
29
+ ttl?: number;
30
+ duration: number;
31
+ startTime: number;
32
+ value?: any;
33
+ }
34
+ export interface RequestProfile {
35
+ id: string;
36
+ method: string;
37
+ url: string;
38
+ route?: string;
39
+ controller?: string;
40
+ handler?: string;
41
+ startTime: number;
42
+ endTime?: number;
43
+ duration?: number;
44
+ statusCode?: number;
45
+ memory?: {
46
+ rss: number;
47
+ heapTotal: number;
48
+ heapUsed: number;
49
+ external: number;
50
+ arrayBuffers: number;
51
+ };
52
+ queries: QueryProfile[];
53
+ logs: LogProfile[];
54
+ cache?: CacheProfile[];
55
+ timestamp: number;
56
+ requestHeaders?: Record<string, any>;
57
+ requestBody?: any;
58
+ exception?: {
59
+ message: string;
60
+ stack: string;
61
+ };
62
+ timings?: {
63
+ total: number;
64
+ middleware: number;
65
+ handler: number;
66
+ };
67
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=profiler.model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiler.model.js","sourceRoot":"","sources":["../../../libs/nestjs-profiler/src/common/profiler.model.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ import type { Response } from 'express';
2
+ import { ProfilerService } from '../services/profiler.service';
3
+ import { ViewService } from '../services/view.service';
4
+ import { TemplateBuilderService } from '../services/template-builder.service';
5
+ import { EntityExplorerService } from '../services/entity-explorer.service';
6
+ import { RouteExplorerService } from '../services/route-explorer.service';
7
+ export declare class ProfilerController {
8
+ private readonly profilerService;
9
+ private readonly viewService;
10
+ private readonly templateBuilder;
11
+ private readonly entityExplorer;
12
+ private readonly routeExplorer;
13
+ constructor(profilerService: ProfilerService, viewService: ViewService, templateBuilder: TemplateBuilderService, entityExplorer: EntityExplorerService, routeExplorer: RouteExplorerService);
14
+ dashboard(res: Response): Promise<void>;
15
+ listJson(): Promise<import("..").RequestProfile[]>;
16
+ debugQuery(): Promise<{
17
+ status: string;
18
+ message: string;
19
+ tip?: undefined;
20
+ } | {
21
+ status: string;
22
+ message: string;
23
+ tip: string;
24
+ }>;
25
+ detail(id: string, res: Response): Promise<void>;
26
+ detailJson(id: string): Promise<import("..").RequestProfile>;
27
+ listQueries(res: Response): Promise<void>;
28
+ listLogs(res: Response, page?: number): Promise<void>;
29
+ listEntities(res: Response): Promise<void>;
30
+ listRoutes(res: Response): Promise<void>;
31
+ listCache(res: Response): Promise<void>;
32
+ serveAsset(file: string, res: Response): Promise<void>;
33
+ serveJs(file: string, res: Response): Promise<void>;
34
+ }