@ngn-net/nestjs-telescope 0.3.0 → 0.3.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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  A full-featured developer assistant and application monitoring suite for NestJS, inspired by Laravel Telescope. It monitors incoming HTTP requests, database queries, cache operations, background queue jobs, application events, outgoing mail, logs, unhandled exceptions, cron job schedules, Redis commands, CLI commands, ORM model lifecycle events, notifications, and authorization gate checks.
6
6
 
7
- All telemetry records are persisted to **MongoDB** (via Mongoose) for zero-impact storage that never touches your production database.
7
+ All telemetry records are persisted to a **dedicated MongoDB** (via Mongoose) and accessible via a modern, high-fidelity dark-themed single-page application dashboard. Telescope uses its own MongoDB connection — completely separate from your project's database.
8
8
 
9
9
  ---
10
10
 
@@ -41,18 +41,18 @@ Telescope stores its telemetry data in a **dedicated MongoDB collection** (`tele
41
41
 
42
42
  ### MongoDB Connection
43
43
 
44
- Telescope connects to MongoDB using the `MONGO_URI` environment variable, or falls back to `mongodb://localhost:27017/telescope`.
44
+ Telescope connects to its own dedicated MongoDB using the `TELESCOPE_MONGO_URI` environment variable, or falls back to `mongodb://localhost:27017/telescope`.
45
45
 
46
46
  ```bash
47
47
  # .env
48
- MONGO_URI=mongodb://localhost:27017/telescope
48
+ TELESCOPE_MONGO_URI=mongodb://localhost:27017/telescope
49
49
  ```
50
50
 
51
51
  Or pass the URI directly in configuration:
52
52
 
53
53
  ```typescript
54
54
  TelescopeModule.forRoot({
55
- mongoUri: 'mongodb://localhost:27017/telescope',
55
+ mongoUri: 'mongodb://your-mongo-host:27017/telescope',
56
56
  // ... other options
57
57
  })
58
58
  ```
@@ -64,10 +64,10 @@ TelescopeModule.forRoot({
64
64
  Install the package:
65
65
 
66
66
  ```bash
67
- npm install @ngn-net/nestjs-telescope @nestjs/mongoose mongoose @nestjs/jwt @nestjs/passport passport-jwt
67
+ npm install @ngn-net/nestjs-telescope @nestjs/jwt @nestjs/passport passport-jwt
68
68
  ```
69
69
 
70
- Ensure you have `MongooseModule` initialized in your NestJS application.
70
+ No need to install `mongoose` or configure `MongooseModule` Telescope handles its own MongoDB connection internally.
71
71
 
72
72
  ---
73
73
 
@@ -75,25 +75,23 @@ Ensure you have `MongooseModule` initialized in your NestJS application.
75
75
 
76
76
  ```typescript
77
77
  import { Module } from '@nestjs/common';
78
- import { MongooseModule } from '@nestjs/mongoose';
79
78
  import { TelescopeModule } from '@ngn-net/nestjs-telescope';
80
79
 
81
80
  @Module({
82
81
  imports: [
83
- MongooseModule.forRoot(process.env.MONGO_URI || 'mongodb://localhost:27017/telescope'),
84
82
  TelescopeModule.forRoot({
85
83
  path: 'telescope',
86
84
  jwtSecret: 'your-secret-key',
87
85
  password: 'your-password',
86
+ // Telescope connects to its own MongoDB automatically
87
+ // Default: mongodb://localhost:27017/telescope
88
88
  }),
89
89
  ],
90
90
  })
91
91
  export class AppModule {}
92
92
  ```
93
93
 
94
- ---
95
-
96
- ## Optional & Peer Dependencies
94
+ Your app's database (TypeORM/Prisma/Sequelize/etc.) stays completely separate — Telescope never touches it.
97
95
 
98
96
  All watchers are dynamically activated. If your application does not use certain modules, Telescope will safely boot without them. Simply install the peer dependencies for the watchers you want to enable:
99
97
 
@@ -147,35 +145,22 @@ You can pass configuration options into `TelescopeModule.forRoot(options)`:
147
145
 
148
146
  ```typescript
149
147
  import { Module } from '@nestjs/common';
150
- import { MongooseModule } from '@nestjs/mongoose';
148
+ import { TypeOrmModule } from '@nestjs/typeorm';
151
149
  import { TelescopeModule, EntryType } from '@ngn-net/nestjs-telescope';
152
150
 
153
151
  @Module({
154
152
  imports: [
155
- MongooseModule.forRoot(process.env.MONGO_URI || 'mongodb://localhost:27017/myapp'),
153
+ // Your project database — completely separate from Telescope
154
+ TypeOrmModule.forRoot({
155
+ type: 'postgres',
156
+ database: 'myapp_db',
157
+ }),
156
158
  TelescopeModule.forRoot({
157
159
  path: 'telescope',
158
160
  password: 'my-secure-password',
159
161
  jwtSecret: 'my-jwt-secret',
160
162
  maxEntries: 500,
161
- ignorePaths: ['/health-check'],
162
- enabledEntryTypes: [
163
- EntryType.REQUEST,
164
- EntryType.HTTP_CLIENT,
165
- EntryType.QUERY,
166
- EntryType.CACHE,
167
- EntryType.JOB,
168
- EntryType.EVENT,
169
- EntryType.LOG,
170
- EntryType.EXCEPTION,
171
- EntryType.SCHEDULED_TASK,
172
- EntryType.REDIS,
173
- EntryType.MAIL,
174
- EntryType.GATE,
175
- EntryType.COMMAND,
176
- EntryType.MODEL,
177
- EntryType.NOTIFICATION,
178
- ],
163
+ // Telescope uses its own MongoDB: mongodb://localhost:27017/telescope
179
164
  }),
180
165
  ],
181
166
  })
@@ -277,14 +262,14 @@ npm run test
277
262
 
278
263
  If upgrading from v0.2.x (which used TypeORM/SQL):
279
264
 
280
- 1. Install the new dependencies:
265
+ 1. Update the package:
281
266
  ```bash
282
- npm install @ngn-net/nestjs-telescope @nestjs/mongoose mongoose
267
+ npm install @ngn-net/nestjs-telescope@latest
283
268
  ```
284
269
 
285
- 2. Add `MongooseModule.forRoot()` to your root module (if not already present).
270
+ 2. Ensure MongoDB is available at `mongodb://localhost:27017/telescope` (or configure `mongoUri`).
286
271
 
287
- 3. Remove the old TypeORM-based telescope entity Telescope now manages its own MongoDB collection automatically.
272
+ 3. Remove the old `TypeOrmModule` import if it was only added for Telescope.
288
273
 
289
274
  4. The old `telescope_entries` SQL table can be dropped after migration.
290
275
 
@@ -1,5 +1,7 @@
1
1
  /** Injection token for telescope configuration options */
2
2
  export declare const TELESCOPE_OPTIONS = "TELESCOPE_OPTIONS";
3
+ /** Injection token for Telescope's dedicated Mongoose connection name */
4
+ export declare const TELESCOPE_MONGO_CONNECTION = "TELESCOPE_MONGO";
3
5
  /** Default base path for the Telescope UI & API */
4
6
  export declare const DEFAULT_TELESCOPE_PATH = "telescope";
5
7
  /** Default JWT secret (should always be overridden in production) */
@@ -8,5 +10,7 @@ export declare const DEFAULT_JWT_SECRET = "telescope-change-me";
8
10
  export declare const DEFAULT_MAX_ENTRIES = 1000;
9
11
  /** Default password for UI authentication */
10
12
  export declare const DEFAULT_PASSWORD = "password";
13
+ /** Default MongoDB URI for Telescope's dedicated connection */
14
+ export declare const DEFAULT_MONGO_URI = "mongodb://localhost:27017/telescope";
11
15
  /** Minimum interval (ms) between prune operations */
12
16
  export declare const PRUNE_THROTTLE_MS = 60000;
package/dist/constants.js CHANGED
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  // src/constants.ts
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.PRUNE_THROTTLE_MS = exports.DEFAULT_PASSWORD = exports.DEFAULT_MAX_ENTRIES = exports.DEFAULT_JWT_SECRET = exports.DEFAULT_TELESCOPE_PATH = exports.TELESCOPE_OPTIONS = void 0;
4
+ exports.PRUNE_THROTTLE_MS = exports.DEFAULT_MONGO_URI = exports.DEFAULT_PASSWORD = exports.DEFAULT_MAX_ENTRIES = exports.DEFAULT_JWT_SECRET = exports.DEFAULT_TELESCOPE_PATH = exports.TELESCOPE_MONGO_CONNECTION = exports.TELESCOPE_OPTIONS = void 0;
5
5
  /** Injection token for telescope configuration options */
6
6
  exports.TELESCOPE_OPTIONS = 'TELESCOPE_OPTIONS';
7
+ /** Injection token for Telescope's dedicated Mongoose connection name */
8
+ exports.TELESCOPE_MONGO_CONNECTION = 'TELESCOPE_MONGO';
7
9
  /** Default base path for the Telescope UI & API */
8
10
  exports.DEFAULT_TELESCOPE_PATH = 'telescope';
9
11
  /** Default JWT secret (should always be overridden in production) */
@@ -12,5 +14,7 @@ exports.DEFAULT_JWT_SECRET = 'telescope-change-me';
12
14
  exports.DEFAULT_MAX_ENTRIES = 1000;
13
15
  /** Default password for UI authentication */
14
16
  exports.DEFAULT_PASSWORD = 'password';
17
+ /** Default MongoDB URI for Telescope's dedicated connection */
18
+ exports.DEFAULT_MONGO_URI = 'mongodb://localhost:27017/telescope';
15
19
  /** Minimum interval (ms) between prune operations */
16
20
  exports.PRUNE_THROTTLE_MS = 60_000;
@@ -18,6 +18,8 @@ export interface TelescopeOptions {
18
18
  ignoreCommands?: string[];
19
19
  /** Additional middleware to apply to UI routes */
20
20
  uiMiddleware?: any[];
21
+ /** MongoDB URI for Telescope's dedicated connection (default: 'mongodb://localhost:27017/telescope') */
22
+ mongoUri?: string;
21
23
  }
22
24
  export interface TelescopeOptionsFactory {
23
25
  createTelescopeOptions(): Promise<TelescopeOptions> | TelescopeOptions;
@@ -17,6 +17,7 @@ const common_1 = require("@nestjs/common");
17
17
  const mongoose_1 = require("@nestjs/mongoose");
18
18
  const mongoose_2 = require("mongoose");
19
19
  const telescope_entry_entity_1 = require("./entities/telescope-entry.entity");
20
+ const constants_1 = require("../constants");
20
21
  let TelescopeRepository = class TelescopeRepository {
21
22
  entryModel;
22
23
  constructor(entryModel) {
@@ -96,6 +97,6 @@ let TelescopeRepository = class TelescopeRepository {
96
97
  exports.TelescopeRepository = TelescopeRepository;
97
98
  exports.TelescopeRepository = TelescopeRepository = __decorate([
98
99
  (0, common_1.Injectable)(),
99
- __param(0, (0, mongoose_1.InjectModel)(telescope_entry_entity_1.TelescopeEntry.name)),
100
+ __param(0, (0, mongoose_1.InjectModel)(telescope_entry_entity_1.TelescopeEntry.name, constants_1.TELESCOPE_MONGO_CONNECTION)),
100
101
  __metadata("design:paramtypes", [mongoose_2.Model])
101
102
  ], TelescopeRepository);
@@ -100,10 +100,10 @@ let TelescopeModule = TelescopeModule_1 = class TelescopeModule {
100
100
  catch (e) { }
101
101
  }
102
102
  static forRoot(options = {}) {
103
+ const mongoUri = options.mongoUri || process.env.TELESCOPE_MONGO_URI || constants_1.DEFAULT_MONGO_URI;
103
104
  const imports = [
104
- mongoose_1.MongooseModule.forFeature([
105
- { name: telescope_entry_entity_1.TelescopeEntry.name, schema: telescope_entry_entity_1.TelescopeEntrySchema },
106
- ]),
105
+ mongoose_1.MongooseModule.forRoot(mongoUri, { connectionName: constants_1.TELESCOPE_MONGO_CONNECTION }),
106
+ mongoose_1.MongooseModule.forFeature([{ name: telescope_entry_entity_1.TelescopeEntry.name, schema: telescope_entry_entity_1.TelescopeEntrySchema }], constants_1.TELESCOPE_MONGO_CONNECTION),
107
107
  jwt_1.JwtModule.register({
108
108
  secret: options.jwtSecret || process.env.TELESCOPE_JWT_SECRET || constants_1.DEFAULT_JWT_SECRET,
109
109
  signOptions: { expiresIn: '1d' },
@@ -143,9 +143,15 @@ let TelescopeModule = TelescopeModule_1 = class TelescopeModule {
143
143
  telescope_jwt_guard_1.JwtAuthGuard,
144
144
  ];
145
145
  const imports = [
146
- mongoose_1.MongooseModule.forFeature([
147
- { name: telescope_entry_entity_1.TelescopeEntry.name, schema: telescope_entry_entity_1.TelescopeEntrySchema },
148
- ]),
146
+ mongoose_1.MongooseModule.forRootAsync({
147
+ connectionName: constants_1.TELESCOPE_MONGO_CONNECTION,
148
+ imports: options.imports || [],
149
+ inject: [constants_1.TELESCOPE_OPTIONS],
150
+ useFactory: async (telescopeOpts) => ({
151
+ uri: telescopeOpts.mongoUri || process.env.TELESCOPE_MONGO_URI || constants_1.DEFAULT_MONGO_URI,
152
+ }),
153
+ }),
154
+ mongoose_1.MongooseModule.forFeature([{ name: telescope_entry_entity_1.TelescopeEntry.name, schema: telescope_entry_entity_1.TelescopeEntrySchema }], constants_1.TELESCOPE_MONGO_CONNECTION),
149
155
  jwt_1.JwtModule.registerAsync({
150
156
  imports: options.imports || [],
151
157
  inject: [constants_1.TELESCOPE_OPTIONS],
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ngn-net/nestjs-telescope",
3
- "version": "0.3.0",
4
- "builtAt": "2026-06-13T09:00:02.618Z"
3
+ "version": "0.3.2",
4
+ "builtAt": "2026-06-13T10:27:41.954Z"
5
5
  }
@@ -10,7 +10,6 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.ExceptionWatcher = void 0;
13
- // src/watchers/exception.watcher.ts
14
13
  const common_1 = require("@nestjs/common");
15
14
  const rxjs_1 = require("rxjs");
16
15
  const operators_1 = require("rxjs/operators");
@@ -22,11 +21,14 @@ let ExceptionWatcher = class ExceptionWatcher {
22
21
  this.telescope = telescope;
23
22
  }
24
23
  intercept(context, next) {
25
- // Skip non-HTTP execution contexts (e.g. RPC/RabbitMQ or WebSockets)
26
24
  if (context.getType() !== 'http') {
27
25
  return next.handle();
28
26
  }
29
27
  const request = context.switchToHttp().getRequest();
28
+ const url = request.originalUrl || request.url || '';
29
+ if (this.telescope.shouldIgnorePath(url)) {
30
+ return next.handle();
31
+ }
30
32
  return next.handle().pipe((0, operators_1.catchError)((err) => {
31
33
  this.telescope.record({
32
34
  type: entry_type_enum_1.EntryType.EXCEPTION,
@@ -35,10 +37,9 @@ let ExceptionWatcher = class ExceptionWatcher {
35
37
  message: err.message || String(err),
36
38
  stack: err.stack || null,
37
39
  status: err.status || err.statusCode || 500,
38
- // Include request context for easier debugging
39
40
  request: {
40
41
  method: request?.method,
41
- url: request?.originalUrl || request?.url,
42
+ url,
42
43
  ip: request?.ip,
43
44
  },
44
45
  },
@@ -24,6 +24,10 @@ let GateWatcher = class GateWatcher {
24
24
  return next.handle();
25
25
  }
26
26
  const request = context.switchToHttp().getRequest();
27
+ const url = request.originalUrl || request.url || '';
28
+ if (this.telescope.shouldIgnorePath(url)) {
29
+ return next.handle();
30
+ }
27
31
  const user = request.user || request.auth || null;
28
32
  return next.handle().pipe((0, rxjs_1.tap)({
29
33
  next: () => {
@@ -34,7 +38,7 @@ let GateWatcher = class GateWatcher {
34
38
  allowed: true,
35
39
  user: user ? { id: user.sub || user.id || user.username } : null,
36
40
  method: request.method,
37
- url: request.originalUrl || request.url,
41
+ url,
38
42
  },
39
43
  }).catch(() => { });
40
44
  },
@@ -50,7 +54,7 @@ let GateWatcher = class GateWatcher {
50
54
  reason: err.message || err.constructor?.name || 'Access denied',
51
55
  user: user ? { id: user.sub || user.id || user.username } : null,
52
56
  method: request.method,
53
- url: request.originalUrl || request.url,
57
+ url,
54
58
  },
55
59
  }).catch(() => { });
56
60
  }
@@ -41,7 +41,7 @@ let LogWatcher = class LogWatcher {
41
41
  rawMessage = chunk.toString(encoding || 'utf8');
42
42
  }
43
43
  // Skip telescope internal queries or module logs
44
- if (rawMessage.includes('telescope_entries') || rawMessage.includes('TelescopeModule')) {
44
+ if (rawMessage.includes('telescope_entries') || rawMessage.includes('TelescopeModule') || rawMessage.includes('Telescope')) {
45
45
  return;
46
46
  }
47
47
  // Parse the log message
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngn-net/nestjs-telescope",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },