nestjs-telescope
Version:
A debugging and monitoring tool for NestJS applications, inspired by Laravel Telescope
195 lines • 9.82 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var TelescopeModule_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TelescopeModule = void 0;
const common_1 = require("@nestjs/common");
const core_1 = require("@nestjs/core");
const core_2 = require("@nestjs/core");
const telescope_service_1 = require("./telescope.service");
const telescope_basic_auth_guard_1 = require("./telescope-basic-auth.guard");
const telescope_interceptor_1 = require("./telescope.interceptor");
const telescope_exception_filter_1 = require("./telescope-exception.filter");
function telescopeMiddlewareFactory(telescopeService) {
return async (req, res, next) => {
if (!req.url.startsWith('/telescope'))
return next();
const isAuthEnabled = process.env.TELESCOPE_AUTH_ENABLED === 'true';
const username = process.env.TELESCOPE_USER;
const password = process.env.TELESCOPE_PASS;
if (isAuthEnabled) {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Basic ')) {
res.setHeader('WWW-Authenticate', 'Basic realm="Telescope"');
return res.status(401).send('Authentication required');
}
const base64 = authHeader.split(' ')[1];
const [user, pass] = Buffer.from(base64, 'base64').toString().split(':');
if (user !== username || pass !== password) {
res.setHeader('WWW-Authenticate', 'Basic realm="Telescope"');
return res.status(401).send('Invalid credentials');
}
}
if (req.url === '/telescope' || req.url === '/telescope/') {
const { join } = require('path');
const { existsSync } = require('fs');
const possiblePaths = [
join(__dirname, '..', 'public'),
join(__dirname, 'public'),
join(process.cwd(), 'node_modules', 'nestjs-telescope', 'public'),
join(process.cwd(), 'node_modules', 'nestjs-telescope', 'dist', 'public'),
join(process.cwd(), 'node_modules', 'nestjs-telescope', 'packages', 'core', 'public'),
join('/app', 'node_modules', 'nestjs-telescope', 'public'),
join('/app', 'node_modules', 'nestjs-telescope', 'dist', 'public'),
join(__dirname, '..', '..', 'public'),
join(__dirname, '..', '..', 'dist', 'public')
];
for (const rootPath of possiblePaths) {
const htmlPath = join(rootPath, 'index.html');
if (existsSync(htmlPath)) {
res.setHeader('Content-Type', 'text/html');
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
return res.sendFile('index.html', { root: rootPath });
}
}
if (process.env.NODE_ENV !== 'production') {
console.warn('Telescope UI files not found. Checked paths:', possiblePaths);
}
return res.status(500).send('Telescope interface files not found');
}
if (req.url.startsWith('/telescope/assets/')) {
const assetPath = req.url.replace(/^\/telescope\/assets\//, '');
const { join } = require('path');
const { existsSync } = require('fs');
const possiblePaths = [
join(__dirname, '..', 'public', 'assets'),
join(__dirname, 'public', 'assets'),
join(process.cwd(), 'node_modules', 'nestjs-telescope', 'public', 'assets'),
join(process.cwd(), 'node_modules', 'nestjs-telescope', 'dist', 'public', 'assets'),
join(process.cwd(), 'node_modules', 'nestjs-telescope', 'packages', 'core', 'public', 'assets'),
join('/app', 'node_modules', 'nestjs-telescope', 'public', 'assets'),
join('/app', 'node_modules', 'nestjs-telescope', 'dist', 'public', 'assets'),
join(__dirname, '..', '..', 'public', 'assets'),
join(__dirname, '..', '..', 'dist', 'public', 'assets')
];
for (const rootPath of possiblePaths) {
const fullAssetPath = join(rootPath, assetPath);
if (existsSync(fullAssetPath)) {
const ext = assetPath.split('.').pop()?.toLowerCase();
if (ext === 'css') {
res.setHeader('Content-Type', 'text/css');
}
else if (ext === 'js') {
res.setHeader('Content-Type', 'application/javascript');
}
res.setHeader('Cache-Control', 'public, max-age=31536000');
return res.sendFile(assetPath, { root: rootPath });
}
}
return res.status(404).send('Asset not found');
}
if (telescopeService) {
if (req.url === '/telescope/api/entries' && req.method === 'GET') {
const entries = telescopeService.getEntries();
return res.json(entries);
}
if (req.url.match(/^\/telescope\/api\/entries\/[\w-]+$/) && req.method === 'GET') {
const id = req.url.split('/').pop();
const entry = telescopeService.getEntry?.(id);
if (!entry)
return res.status(404).json({ message: 'Entry not found' });
return res.json(entry);
}
if (req.url === '/telescope/api/entries' && req.method === 'DELETE') {
telescopeService.clearEntries();
return res.json({ message: 'Entries cleared successfully' });
}
if (req.url === '/telescope/api/stats' && req.method === 'GET') {
const stats = telescopeService.getStats();
return res.json(stats);
}
}
return res.status(404).send('Not found');
};
}
let TelescopeModule = TelescopeModule_1 = class TelescopeModule {
constructor(moduleRef, httpAdapterHost) {
this.moduleRef = moduleRef;
this.httpAdapterHost = httpAdapterHost;
}
onModuleInit() {
if (!process.env.TELESCOPE_STANDALONE_SETUP) {
const app = this.httpAdapterHost?.httpAdapter?.getInstance?.();
const telescopeService = this.moduleRef.get(telescope_service_1.TelescopeService, { strict: false });
if (app && typeof app.use === 'function' && telescopeService) {
app.use(telescopeMiddlewareFactory(telescopeService));
}
}
}
static setup(app) {
process.env.TELESCOPE_STANDALONE_SETUP = 'true';
const httpAdapter = app.getHttpAdapter?.();
const instance = httpAdapter?.getInstance?.();
try {
const { TelescopeService } = require('./telescope.service');
const telescopeService = new TelescopeService();
const { TelescopeInterceptor } = require('./telescope.interceptor');
const { TelescopeExceptionFilter } = require('./telescope-exception.filter');
app.useGlobalInterceptors(new TelescopeInterceptor(telescopeService));
app.useGlobalFilters(new TelescopeExceptionFilter(telescopeService));
if (instance && typeof instance.use === 'function') {
instance.use(telescopeMiddlewareFactory(telescopeService));
}
}
catch (error) {
console.warn('Failed to setup Telescope:', error.message);
}
}
static forRoot() {
return {
module: TelescopeModule_1,
providers: [
telescope_service_1.TelescopeService,
telescope_basic_auth_guard_1.TelescopeBasicAuthGuard,
{
provide: core_2.APP_INTERCEPTOR,
useClass: telescope_interceptor_1.TelescopeInterceptor,
},
{
provide: core_2.APP_FILTER,
useClass: telescope_exception_filter_1.TelescopeExceptionFilter,
},
],
exports: [telescope_service_1.TelescopeService],
};
}
};
exports.TelescopeModule = TelescopeModule;
exports.TelescopeModule = TelescopeModule = TelescopeModule_1 = __decorate([
(0, common_1.Module)({
providers: [
telescope_service_1.TelescopeService,
telescope_basic_auth_guard_1.TelescopeBasicAuthGuard,
{
provide: core_2.APP_INTERCEPTOR,
useClass: telescope_interceptor_1.TelescopeInterceptor,
},
{
provide: core_2.APP_FILTER,
useClass: telescope_exception_filter_1.TelescopeExceptionFilter,
},
],
exports: [telescope_service_1.TelescopeService],
}),
__metadata("design:paramtypes", [core_1.ModuleRef,
core_1.HttpAdapterHost])
], TelescopeModule);
//# sourceMappingURL=nest-telescope.module.js.map
;