@ngn-net/nestjs-telescope 0.1.6 → 0.1.7
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/README.md +42 -34
- package/dist/constants.d.ts +12 -3
- package/dist/constants.js +14 -5
- package/dist/controllers/telescope.controller.d.ts +5 -2
- package/dist/controllers/telescope.controller.js +41 -13
- package/dist/index.d.ts +11 -0
- package/dist/index.js +12 -0
- package/dist/interfaces/telescope-options.interface.d.ts +9 -3
- package/dist/storage/entities/telescope-entry.entity.js +34 -7
- package/dist/storage/telescope-repository.service.d.ts +17 -7
- package/dist/storage/telescope-repository.service.js +42 -17
- package/dist/telescope.module.d.ts +6 -2
- package/dist/telescope.module.js +148 -44
- package/dist/telescope.service.d.ts +21 -1
- package/dist/telescope.service.js +69 -23
- package/dist/ui/index.html +1635 -0
- package/dist/watchers/cache.watcher.d.ts +5 -4
- package/dist/watchers/cache.watcher.js +50 -34
- package/dist/watchers/event.watcher.d.ts +7 -3
- package/dist/watchers/event.watcher.js +22 -6
- package/dist/watchers/exception.watcher.js +7 -1
- package/dist/watchers/http-request.watcher.d.ts +3 -1
- package/dist/watchers/http-request.watcher.js +25 -8
- package/dist/watchers/log.watcher.d.ts +1 -0
- package/dist/watchers/log.watcher.js +22 -17
- package/dist/watchers/mail.watcher.d.ts +1 -1
- package/dist/watchers/mail.watcher.js +28 -56
- package/dist/watchers/query.watcher.d.ts +6 -3
- package/dist/watchers/query.watcher.js +36 -8
- package/dist/watchers/queue.watcher.d.ts +2 -4
- package/dist/watchers/queue.watcher.js +38 -32
- package/dist/watchers/redis.watcher.d.ts +3 -1
- package/dist/watchers/redis.watcher.js +16 -4
- package/dist/watchers/schedule.watcher.d.ts +8 -3
- package/dist/watchers/schedule.watcher.js +25 -11
- package/package.json +51 -19
- package/ui/index.html +602 -235
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
2
|
import { TelescopeService } from '../telescope.service';
|
|
3
|
-
export declare class CacheWatcher {
|
|
4
|
-
private cacheManager;
|
|
3
|
+
export declare class CacheWatcher implements OnModuleInit {
|
|
5
4
|
private readonly telescope;
|
|
6
|
-
|
|
5
|
+
private cacheManager?;
|
|
6
|
+
constructor(telescope: TelescopeService, cacheManager?: any | undefined);
|
|
7
|
+
onModuleInit(): void;
|
|
7
8
|
}
|
|
@@ -15,48 +15,64 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.CacheWatcher = void 0;
|
|
16
16
|
// src/watchers/cache.watcher.ts
|
|
17
17
|
const common_1 = require("@nestjs/common");
|
|
18
|
-
const cache_manager_1 = require("@nestjs/cache-manager");
|
|
19
18
|
const telescope_service_1 = require("../telescope.service");
|
|
20
19
|
const entry_type_enum_1 = require("../enums/entry-type.enum");
|
|
21
20
|
let CacheWatcher = class CacheWatcher {
|
|
22
|
-
cacheManager;
|
|
23
21
|
telescope;
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
cacheManager;
|
|
23
|
+
constructor(telescope, cacheManager) {
|
|
26
24
|
this.telescope = telescope;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
this.cacheManager
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
25
|
+
this.cacheManager = cacheManager;
|
|
26
|
+
}
|
|
27
|
+
onModuleInit() {
|
|
28
|
+
// Skip wrapping if no cache manager is available
|
|
29
|
+
if (!this.cacheManager)
|
|
30
|
+
return;
|
|
31
|
+
try {
|
|
32
|
+
const originalSet = this.cacheManager.set?.bind(this.cacheManager);
|
|
33
|
+
const originalGet = this.cacheManager.get?.bind(this.cacheManager);
|
|
34
|
+
const originalDel = this.cacheManager.del?.bind(this.cacheManager);
|
|
35
|
+
const telescope = this.telescope;
|
|
36
|
+
if (originalSet) {
|
|
37
|
+
this.cacheManager.set = async (key, value, ttl) => {
|
|
38
|
+
const result = await originalSet(key, value, ttl);
|
|
39
|
+
telescope.record({
|
|
40
|
+
type: entry_type_enum_1.EntryType.CACHE,
|
|
41
|
+
content: { action: 'SET', key, value, ttl },
|
|
42
|
+
});
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (originalGet) {
|
|
47
|
+
this.cacheManager.get = async (key) => {
|
|
48
|
+
const value = await originalGet(key);
|
|
49
|
+
telescope.record({
|
|
50
|
+
type: entry_type_enum_1.EntryType.CACHE,
|
|
51
|
+
content: { action: 'GET', key, value },
|
|
52
|
+
});
|
|
53
|
+
return value;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (originalDel) {
|
|
57
|
+
this.cacheManager.del = async (key) => {
|
|
58
|
+
const result = await originalDel(key);
|
|
59
|
+
telescope.record({
|
|
60
|
+
type: entry_type_enum_1.EntryType.CACHE,
|
|
61
|
+
content: { action: 'DEL', key },
|
|
62
|
+
});
|
|
63
|
+
return result;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Ignore errors during wrapping
|
|
69
|
+
}
|
|
55
70
|
}
|
|
56
71
|
};
|
|
57
72
|
exports.CacheWatcher = CacheWatcher;
|
|
58
73
|
exports.CacheWatcher = CacheWatcher = __decorate([
|
|
59
74
|
(0, common_1.Injectable)(),
|
|
60
|
-
__param(
|
|
61
|
-
|
|
75
|
+
__param(1, (0, common_1.Inject)('CACHE_MANAGER')),
|
|
76
|
+
__param(1, (0, common_1.Optional)()),
|
|
77
|
+
__metadata("design:paramtypes", [telescope_service_1.TelescopeService, Object])
|
|
62
78
|
], CacheWatcher);
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
-
import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
3
2
|
import { TelescopeService } from '../telescope.service';
|
|
4
3
|
/**
|
|
5
4
|
* Hooks into EventEmitter2 at the 'onAny' listener level so every
|
|
6
5
|
* application event is captured without requiring per-event config.
|
|
7
6
|
*/
|
|
8
7
|
export declare class EventWatcher implements OnModuleInit {
|
|
9
|
-
private readonly emitter;
|
|
10
8
|
private readonly telescope;
|
|
11
|
-
|
|
9
|
+
private emitter;
|
|
10
|
+
constructor(telescope: TelescopeService);
|
|
12
11
|
onModuleInit(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Called manually or via DI if EventEmitter2 is available.
|
|
14
|
+
* Use setEmitter() from the module setup to provide the emitter instance.
|
|
15
|
+
*/
|
|
16
|
+
setEmitter(emitter: any): void;
|
|
13
17
|
}
|
|
@@ -12,7 +12,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.EventWatcher = void 0;
|
|
13
13
|
// src/watchers/event.watcher.ts
|
|
14
14
|
const common_1 = require("@nestjs/common");
|
|
15
|
-
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
16
15
|
const telescope_service_1 = require("../telescope.service");
|
|
17
16
|
const entry_type_enum_1 = require("../enums/entry-type.enum");
|
|
18
17
|
/**
|
|
@@ -20,13 +19,31 @@ const entry_type_enum_1 = require("../enums/entry-type.enum");
|
|
|
20
19
|
* application event is captured without requiring per-event config.
|
|
21
20
|
*/
|
|
22
21
|
let EventWatcher = class EventWatcher {
|
|
23
|
-
emitter;
|
|
24
22
|
telescope;
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
emitter;
|
|
24
|
+
constructor(telescope) {
|
|
27
25
|
this.telescope = telescope;
|
|
28
26
|
}
|
|
29
27
|
onModuleInit() {
|
|
28
|
+
// Dynamically resolve EventEmitter2 to avoid hard dependency
|
|
29
|
+
try {
|
|
30
|
+
const { EventEmitter2 } = require('@nestjs/event-emitter');
|
|
31
|
+
// If EventEmitter2 is available as a global/module provider, we can't inject it
|
|
32
|
+
// So we hook into it via the module system. For now, rely on the constructor injection
|
|
33
|
+
// approach but make it resilient.
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// @nestjs/event-emitter not available
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Called manually or via DI if EventEmitter2 is available.
|
|
41
|
+
* Use setEmitter() from the module setup to provide the emitter instance.
|
|
42
|
+
*/
|
|
43
|
+
setEmitter(emitter) {
|
|
44
|
+
if (!emitter || typeof emitter.onAny !== 'function')
|
|
45
|
+
return;
|
|
46
|
+
this.emitter = emitter;
|
|
30
47
|
this.emitter.onAny((event, payload) => {
|
|
31
48
|
const eventName = Array.isArray(event) ? event.join('.') : event;
|
|
32
49
|
// Ignore internal telescope events to avoid recursion
|
|
@@ -46,6 +63,5 @@ let EventWatcher = class EventWatcher {
|
|
|
46
63
|
exports.EventWatcher = EventWatcher;
|
|
47
64
|
exports.EventWatcher = EventWatcher = __decorate([
|
|
48
65
|
(0, common_1.Injectable)(),
|
|
49
|
-
__metadata("design:paramtypes", [
|
|
50
|
-
telescope_service_1.TelescopeService])
|
|
66
|
+
__metadata("design:paramtypes", [telescope_service_1.TelescopeService])
|
|
51
67
|
], EventWatcher);
|
|
@@ -22,8 +22,8 @@ let ExceptionWatcher = class ExceptionWatcher {
|
|
|
22
22
|
this.telescope = telescope;
|
|
23
23
|
}
|
|
24
24
|
intercept(context, next) {
|
|
25
|
+
const request = context.switchToHttp().getRequest();
|
|
25
26
|
return next.handle().pipe((0, operators_1.catchError)((err) => {
|
|
26
|
-
// Only record if it looks like an error
|
|
27
27
|
this.telescope.record({
|
|
28
28
|
type: entry_type_enum_1.EntryType.EXCEPTION,
|
|
29
29
|
content: {
|
|
@@ -31,6 +31,12 @@ let ExceptionWatcher = class ExceptionWatcher {
|
|
|
31
31
|
message: err.message || String(err),
|
|
32
32
|
stack: err.stack || null,
|
|
33
33
|
status: err.status || err.statusCode || 500,
|
|
34
|
+
// Include request context for easier debugging
|
|
35
|
+
request: {
|
|
36
|
+
method: request?.method,
|
|
37
|
+
url: request?.originalUrl || request?.url,
|
|
38
|
+
ip: request?.ip,
|
|
39
|
+
},
|
|
34
40
|
},
|
|
35
41
|
});
|
|
36
42
|
return (0, rxjs_1.throwError)(() => err);
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import { TelescopeService } from '../telescope.service';
|
|
4
|
+
import { TelescopeOptions } from '../interfaces/telescope-options.interface';
|
|
4
5
|
export declare class HttpRequestWatcher implements NestInterceptor {
|
|
5
6
|
private readonly telescope;
|
|
6
|
-
|
|
7
|
+
private readonly options?;
|
|
8
|
+
constructor(telescope: TelescopeService, options?: TelescopeOptions | undefined);
|
|
7
9
|
intercept(context: ExecutionContext, next: CallHandler): Observable<any>;
|
|
8
10
|
}
|
|
@@ -8,6 +8,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.HttpRequestWatcher = void 0;
|
|
13
16
|
// src/watchers/http-request.watcher.ts
|
|
@@ -15,38 +18,52 @@ const common_1 = require("@nestjs/common");
|
|
|
15
18
|
const operators_1 = require("rxjs/operators");
|
|
16
19
|
const telescope_service_1 = require("../telescope.service");
|
|
17
20
|
const entry_type_enum_1 = require("../enums/entry-type.enum");
|
|
21
|
+
const constants_1 = require("../constants");
|
|
18
22
|
let HttpRequestWatcher = class HttpRequestWatcher {
|
|
19
23
|
telescope;
|
|
20
|
-
|
|
24
|
+
options;
|
|
25
|
+
constructor(telescope, options) {
|
|
21
26
|
this.telescope = telescope;
|
|
27
|
+
this.options = options;
|
|
22
28
|
}
|
|
23
29
|
intercept(context, next) {
|
|
24
30
|
const request = context.switchToHttp().getRequest();
|
|
31
|
+
const response = context.switchToHttp().getResponse();
|
|
32
|
+
const url = request.originalUrl || request.url || '/';
|
|
33
|
+
// Skip ignored paths
|
|
34
|
+
if (this.telescope.shouldIgnorePath(url)) {
|
|
35
|
+
return next.handle();
|
|
36
|
+
}
|
|
25
37
|
const start = Date.now();
|
|
26
38
|
const requestData = {
|
|
27
39
|
method: request.method,
|
|
28
|
-
url
|
|
40
|
+
url,
|
|
29
41
|
headers: request.headers,
|
|
30
42
|
body: request.body,
|
|
31
43
|
query: request.query,
|
|
32
44
|
ip: request.ip,
|
|
33
45
|
};
|
|
34
|
-
return next.handle().pipe((0, operators_1.tap)((
|
|
46
|
+
return next.handle().pipe((0, operators_1.tap)((responseBody) => {
|
|
35
47
|
const duration = Date.now() - start;
|
|
36
|
-
const
|
|
48
|
+
const statusCode = response.statusCode || 200;
|
|
49
|
+
this.telescope.record({
|
|
37
50
|
type: entry_type_enum_1.EntryType.REQUEST,
|
|
38
51
|
content: {
|
|
39
52
|
request: requestData,
|
|
40
|
-
response:
|
|
53
|
+
response: {
|
|
54
|
+
statusCode,
|
|
55
|
+
body: responseBody,
|
|
56
|
+
},
|
|
41
57
|
duration,
|
|
42
58
|
},
|
|
43
|
-
};
|
|
44
|
-
this.telescope.record(entry);
|
|
59
|
+
});
|
|
45
60
|
}));
|
|
46
61
|
}
|
|
47
62
|
};
|
|
48
63
|
exports.HttpRequestWatcher = HttpRequestWatcher;
|
|
49
64
|
exports.HttpRequestWatcher = HttpRequestWatcher = __decorate([
|
|
50
65
|
(0, common_1.Injectable)(),
|
|
51
|
-
|
|
66
|
+
__param(1, (0, common_1.Inject)(constants_1.TELESCOPE_OPTIONS)),
|
|
67
|
+
__param(1, (0, common_1.Optional)()),
|
|
68
|
+
__metadata("design:paramtypes", [telescope_service_1.TelescopeService, Object])
|
|
52
69
|
], HttpRequestWatcher);
|
|
@@ -2,6 +2,7 @@ import { OnApplicationBootstrap } from '@nestjs/common';
|
|
|
2
2
|
import { TelescopeService } from '../telescope.service';
|
|
3
3
|
export declare class LogWatcher implements OnApplicationBootstrap {
|
|
4
4
|
private readonly telescope;
|
|
5
|
+
private isRecording;
|
|
5
6
|
constructor(telescope: TelescopeService);
|
|
6
7
|
onApplicationBootstrap(): void;
|
|
7
8
|
}
|
|
@@ -16,42 +16,47 @@ const telescope_service_1 = require("../telescope.service");
|
|
|
16
16
|
const entry_type_enum_1 = require("../enums/entry-type.enum");
|
|
17
17
|
let LogWatcher = class LogWatcher {
|
|
18
18
|
telescope;
|
|
19
|
+
isRecording = false; // Guard against infinite recursion
|
|
19
20
|
constructor(telescope) {
|
|
20
21
|
this.telescope = telescope;
|
|
21
22
|
}
|
|
22
23
|
onApplicationBootstrap() {
|
|
23
|
-
// Patch the global console to capture log calls
|
|
24
24
|
const originalLog = console.log.bind(console);
|
|
25
25
|
const originalError = console.error.bind(console);
|
|
26
26
|
const originalWarn = console.warn.bind(console);
|
|
27
27
|
const originalDebug = console.debug.bind(console);
|
|
28
28
|
const self = this;
|
|
29
|
+
const formatArgs = (args) => args.map((a) => (typeof a === 'object' ? JSON.stringify(a) : String(a))).join(' ');
|
|
30
|
+
const recordLog = (level, args) => {
|
|
31
|
+
// Guard: if we're already recording, skip to prevent infinite recursion
|
|
32
|
+
// (recording a log → save to DB → TypeORM logs → recording again → ...)
|
|
33
|
+
if (self.isRecording)
|
|
34
|
+
return;
|
|
35
|
+
self.isRecording = true;
|
|
36
|
+
try {
|
|
37
|
+
self.telescope.record({
|
|
38
|
+
type: entry_type_enum_1.EntryType.LOG,
|
|
39
|
+
content: { level, message: formatArgs(args) },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
self.isRecording = false;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
29
46
|
console.log = function (...args) {
|
|
30
|
-
|
|
31
|
-
type: entry_type_enum_1.EntryType.LOG,
|
|
32
|
-
content: { level: 'log', message: args.map(a => (typeof a === 'object' ? JSON.stringify(a) : String(a))).join(' ') },
|
|
33
|
-
});
|
|
47
|
+
recordLog('log', args);
|
|
34
48
|
return originalLog(...args);
|
|
35
49
|
};
|
|
36
50
|
console.error = function (...args) {
|
|
37
|
-
|
|
38
|
-
type: entry_type_enum_1.EntryType.LOG,
|
|
39
|
-
content: { level: 'error', message: args.map(a => (typeof a === 'object' ? JSON.stringify(a) : String(a))).join(' ') },
|
|
40
|
-
});
|
|
51
|
+
recordLog('error', args);
|
|
41
52
|
return originalError(...args);
|
|
42
53
|
};
|
|
43
54
|
console.warn = function (...args) {
|
|
44
|
-
|
|
45
|
-
type: entry_type_enum_1.EntryType.LOG,
|
|
46
|
-
content: { level: 'warn', message: args.map(a => (typeof a === 'object' ? JSON.stringify(a) : String(a))).join(' ') },
|
|
47
|
-
});
|
|
55
|
+
recordLog('warn', args);
|
|
48
56
|
return originalWarn(...args);
|
|
49
57
|
};
|
|
50
58
|
console.debug = function (...args) {
|
|
51
|
-
|
|
52
|
-
type: entry_type_enum_1.EntryType.LOG,
|
|
53
|
-
content: { level: 'debug', message: args.map(a => (typeof a === 'object' ? JSON.stringify(a) : String(a))).join(' ') },
|
|
54
|
-
});
|
|
59
|
+
recordLog('debug', args);
|
|
55
60
|
return originalDebug(...args);
|
|
56
61
|
};
|
|
57
62
|
}
|
|
@@ -3,10 +3,10 @@ import { TelescopeService } from '../telescope.service';
|
|
|
3
3
|
/**
|
|
4
4
|
* Wraps Nodemailer transport's `sendMail` method to capture outgoing e‑mails.
|
|
5
5
|
* The original transport is replaced with a proxy that records each call.
|
|
6
|
+
* If nodemailer is not installed, this watcher is silently skipped.
|
|
6
7
|
*/
|
|
7
8
|
export declare class MailWatcher implements OnModuleInit {
|
|
8
9
|
private readonly telescope;
|
|
9
|
-
private originalCreateTransport;
|
|
10
10
|
constructor(telescope: TelescopeService);
|
|
11
11
|
onModuleInit(): void;
|
|
12
12
|
}
|
|
@@ -1,43 +1,10 @@
|
|
|
1
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
2
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
3
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
4
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
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;
|
|
22
6
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
7
|
};
|
|
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
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
42
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
43
10
|
};
|
|
@@ -45,42 +12,47 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
45
12
|
exports.MailWatcher = void 0;
|
|
46
13
|
// src/watchers/mail.watcher.ts
|
|
47
14
|
const common_1 = require("@nestjs/common");
|
|
48
|
-
const nodemailer = __importStar(require("nodemailer"));
|
|
49
15
|
const telescope_service_1 = require("../telescope.service");
|
|
50
16
|
const entry_type_enum_1 = require("../enums/entry-type.enum");
|
|
51
17
|
/**
|
|
52
18
|
* Wraps Nodemailer transport's `sendMail` method to capture outgoing e‑mails.
|
|
53
19
|
* The original transport is replaced with a proxy that records each call.
|
|
20
|
+
* If nodemailer is not installed, this watcher is silently skipped.
|
|
54
21
|
*/
|
|
55
22
|
let MailWatcher = class MailWatcher {
|
|
56
23
|
telescope;
|
|
57
|
-
originalCreateTransport = nodemailer.createTransport;
|
|
58
24
|
constructor(telescope) {
|
|
59
25
|
this.telescope = telescope;
|
|
60
26
|
}
|
|
61
27
|
onModuleInit() {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
28
|
+
try {
|
|
29
|
+
const nodemailer = require('nodemailer');
|
|
30
|
+
const originalCreateTransport = nodemailer.createTransport;
|
|
31
|
+
const self = this;
|
|
32
|
+
nodemailer.createTransport = function (...args) {
|
|
33
|
+
const transport = originalCreateTransport.apply(this, args);
|
|
34
|
+
const originalSendMail = transport.sendMail.bind(transport);
|
|
35
|
+
transport.sendMail = async function (mailOptions) {
|
|
36
|
+
const info = await originalSendMail(mailOptions);
|
|
37
|
+
self.telescope.record({
|
|
38
|
+
type: entry_type_enum_1.EntryType.MAIL,
|
|
39
|
+
content: {
|
|
40
|
+
from: mailOptions.from,
|
|
41
|
+
to: mailOptions.to,
|
|
42
|
+
subject: mailOptions.subject,
|
|
43
|
+
text: mailOptions.text,
|
|
44
|
+
html: mailOptions.html,
|
|
45
|
+
messageId: info.messageId,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
return info;
|
|
49
|
+
};
|
|
50
|
+
return transport;
|
|
81
51
|
};
|
|
82
|
-
|
|
83
|
-
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// nodemailer is not installed — skip silently
|
|
55
|
+
}
|
|
84
56
|
}
|
|
85
57
|
};
|
|
86
58
|
exports.MailWatcher = MailWatcher;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { DataSource, InsertEvent, UpdateEvent, RemoveEvent } from 'typeorm';
|
|
2
3
|
import { TelescopeService } from '../telescope.service';
|
|
3
|
-
export declare class QueryWatcher {
|
|
4
|
+
export declare class QueryWatcher implements OnModuleInit {
|
|
4
5
|
private readonly telescope;
|
|
5
|
-
|
|
6
|
+
private readonly dataSource?;
|
|
7
|
+
constructor(telescope: TelescopeService, dataSource?: DataSource | undefined);
|
|
8
|
+
onModuleInit(): void;
|
|
6
9
|
afterInsert(event: InsertEvent<any>): void;
|
|
7
10
|
afterUpdate(event: UpdateEvent<any>): void;
|
|
8
11
|
afterRemove(event: RemoveEvent<any>): void;
|
|
@@ -8,6 +8,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var QueryWatcher_1;
|
|
11
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
16
|
exports.QueryWatcher = void 0;
|
|
13
17
|
// src/watchers/query.watcher.ts
|
|
@@ -15,10 +19,29 @@ const common_1 = require("@nestjs/common");
|
|
|
15
19
|
const typeorm_1 = require("typeorm");
|
|
16
20
|
const telescope_service_1 = require("../telescope.service");
|
|
17
21
|
const entry_type_enum_1 = require("../enums/entry-type.enum");
|
|
18
|
-
let QueryWatcher = class QueryWatcher {
|
|
22
|
+
let QueryWatcher = QueryWatcher_1 = class QueryWatcher {
|
|
19
23
|
telescope;
|
|
20
|
-
|
|
24
|
+
dataSource;
|
|
25
|
+
constructor(telescope, dataSource) {
|
|
21
26
|
this.telescope = telescope;
|
|
27
|
+
this.dataSource = dataSource;
|
|
28
|
+
}
|
|
29
|
+
onModuleInit() {
|
|
30
|
+
// Manually register this subscriber with the DataSource
|
|
31
|
+
// The @EventSubscriber() decorator alone doesn't auto-register when the
|
|
32
|
+
// subscriber is managed by NestJS DI rather than TypeORM's internal discovery
|
|
33
|
+
if (this.dataSource) {
|
|
34
|
+
try {
|
|
35
|
+
// Avoid duplicate registration
|
|
36
|
+
const alreadyRegistered = this.dataSource.subscribers.some((s) => s instanceof QueryWatcher_1);
|
|
37
|
+
if (!alreadyRegistered) {
|
|
38
|
+
this.dataSource.subscribers.push(this);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Ignore registration errors
|
|
43
|
+
}
|
|
44
|
+
}
|
|
22
45
|
}
|
|
23
46
|
afterInsert(event) {
|
|
24
47
|
this.capture(event, 'INSERT');
|
|
@@ -30,23 +53,28 @@ let QueryWatcher = class QueryWatcher {
|
|
|
30
53
|
this.capture(event, 'REMOVE');
|
|
31
54
|
}
|
|
32
55
|
capture(event, operation) {
|
|
33
|
-
|
|
56
|
+
// Skip recording telescope's own entity changes to avoid infinite loops
|
|
57
|
+
const tableName = event.metadata?.tableName;
|
|
58
|
+
if (tableName === 'telescope_entries')
|
|
59
|
+
return;
|
|
60
|
+
this.telescope.record({
|
|
34
61
|
type: entry_type_enum_1.EntryType.QUERY,
|
|
35
62
|
content: {
|
|
36
63
|
operation,
|
|
37
|
-
entity:
|
|
64
|
+
entity: tableName || 'unknown',
|
|
38
65
|
primaryKey: event.entity?.id || null,
|
|
39
66
|
data: event.entity,
|
|
40
67
|
query: event.query,
|
|
41
68
|
parameters: event.parameters,
|
|
42
69
|
},
|
|
43
|
-
};
|
|
44
|
-
this.telescope.record(entry);
|
|
70
|
+
});
|
|
45
71
|
}
|
|
46
72
|
};
|
|
47
73
|
exports.QueryWatcher = QueryWatcher;
|
|
48
|
-
exports.QueryWatcher = QueryWatcher = __decorate([
|
|
74
|
+
exports.QueryWatcher = QueryWatcher = QueryWatcher_1 = __decorate([
|
|
49
75
|
(0, typeorm_1.EventSubscriber)(),
|
|
50
76
|
(0, common_1.Injectable)(),
|
|
51
|
-
|
|
77
|
+
__param(1, (0, common_1.Optional)()),
|
|
78
|
+
__metadata("design:paramtypes", [telescope_service_1.TelescopeService,
|
|
79
|
+
typeorm_1.DataSource])
|
|
52
80
|
], QueryWatcher);
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
-
import { Queue } from 'bullmq';
|
|
3
2
|
import { TelescopeService } from '../telescope.service';
|
|
4
3
|
export declare class QueueWatcher implements OnModuleInit {
|
|
5
|
-
private readonly queue;
|
|
6
4
|
private readonly telescope;
|
|
7
|
-
private
|
|
8
|
-
constructor(
|
|
5
|
+
private readonly queue?;
|
|
6
|
+
constructor(telescope: TelescopeService, queue?: any | undefined);
|
|
9
7
|
onModuleInit(): void;
|
|
10
8
|
}
|