Skip to main content

Customization Guide

Guide for customizing and extending NopeSight.

Architecture Overview

Technology Stack

  • Frontend: React 18, TypeScript, Material-UI
  • Backend: Node.js, Express, MongoDB
  • Queue: Bull/Redis
  • AI: AWS Bedrock, OpenAI

Design Patterns

  • RESTful API design
  • Event-driven architecture
  • Microservices ready
  • Plugin system

Custom CI Types

Creating New CI Types

  1. Define the Model
// backend/models/custom-ci.js
const customCISchema = new Schema({
name: { type: String, required: true },
type: { type: String, default: 'CustomDevice' },
customField1: String,
customField2: Number,
// ... additional fields
});
  1. Add to TableMetadata
// backend/scripts/add-custom-citype.js
const metadata = {
ciType: 'CustomDevice',
fields: [
{
name: 'customField1',
label: 'Custom Field 1',
type: 'string',
required: true
}
]
};
  1. Update Frontend
// frontend/src/types/cmdb.ts
export enum CIType {
// ... existing types
CustomDevice = 'CustomDevice'
}

// frontend/src/config/ci-types.ts
export const CI_TYPE_CONFIG = {
CustomDevice: {
icon: CustomIcon,
color: '#FF5722',
label: 'Custom Device'
}
};

Custom Fields

Dynamic Field System

// Add custom field via API
POST /api/cmdb/table-metadata
{
"ciType": "Server",
"fields": [{
"name": "businessUnit",
"label": "Business Unit",
"type": "select",
"options": ["Sales", "IT", "HR"],
"required": true
}]
}

Field Types

  • text
  • number
  • select
  • multiselect
  • date
  • boolean
  • json
  • relationship

UI Customization

Custom Components

// frontend/src/components/custom/MyWidget.tsx
import React from 'react';
import { Card, CardContent } from '@mui/material';

export const MyWidget: React.FC = () => {
return (
<Card>
<CardContent>
<h3>My Custom Widget</h3>
{/* Custom content */}
</CardContent>
</Card>
);
};

Theme Customization

// frontend/src/theme/custom-theme.ts
import { createTheme } from '@mui/material/styles';

export const customTheme = createTheme({
palette: {
primary: {
main: '#1976d2',
},
secondary: {
main: '#dc004e',
},
},
typography: {
fontFamily: 'Roboto, Arial, sans-serif',
},
});

API Extensions

Custom Endpoints

// backend/routes/custom.js
router.post('/custom-action', async (req, res) => {
try {
const result = await customService.performAction(req.body);
res.json({ success: true, data: result });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
});

Middleware

// backend/middleware/custom-auth.js
module.exports = (req, res, next) => {
// Custom authentication logic
if (req.headers['x-custom-token'] === process.env.CUSTOM_TOKEN) {
next();
} else {
res.status(401).json({ error: 'Unauthorized' });
}
};

Plugin System

Plugin Structure

// plugins/my-plugin/index.js
module.exports = {
name: 'my-plugin',
version: '1.0.0',
init: (app, services) => {
// Plugin initialization
app.use('/api/my-plugin', pluginRoutes);
},
hooks: {
'ci.created': async (ci) => {
// React to CI creation
},
'event.received': async (event) => {
// Process events
}
}
};

Event Hooks

  • ci.created
  • ci.updated
  • ci.deleted
  • relationship.created
  • event.received
  • report.generated

Custom Processors

Scan Data Processor

// backend/services/scanProcessors/custom_processor.js
class CustomProcessor {
async process(scanData) {
// Custom processing logic
const ci = {
name: scanData.hostname,
type: 'CustomDevice',
customData: this.extractCustomData(scanData)
};

return ci;
}
}

AI Integration

// backend/services/ai/customAIService.js
class CustomAIService {
async analyze(data) {
// Custom AI analysis
const prompt = this.buildPrompt(data);
const result = await claudeService.analyze(prompt);
return this.parseResult(result);
}
}

Custom Reports

Report Template

// backend/models/custom-report-template.js
const template = {
name: 'Custom Compliance Report',
type: 'compliance',
sections: [
{
title: 'Executive Summary',
query: { type: 'aggregation' },
visualization: 'chart'
}
],
schedule: '0 9 * * MON'
};

Report Generator

// backend/services/customReportGenerator.js
class CustomReportGenerator {
async generate(template, filters) {
const data = await this.fetchData(filters);
const analysis = await this.analyzeData(data);
return this.formatReport(analysis);
}
}

Testing

Unit Tests

// backend/tests/custom.test.js
describe('Custom Feature', () => {
it('should process custom data', async () => {
const result = await customService.process(testData);
expect(result).toHaveProperty('customField');
});
});

Integration Tests

// backend/tests/integration/custom-api.test.js
describe('Custom API', () => {
it('should handle custom endpoint', async () => {
const response = await request(app)
.post('/api/custom-action')
.send({ data: 'test' });

expect(response.status).toBe(200);
});
});

Deployment

Environment Configuration

# Custom environment variables
CUSTOM_FEATURE_ENABLED=true
CUSTOM_API_KEY=your-key
PLUGIN_DIR=/opt/nopesight/plugins

Build Process

// package.json
{
"scripts": {
"build:custom": "webpack --config webpack.custom.js",
"deploy:plugin": "npm run build && cp -r dist/* /opt/plugins/"
}
}

Best Practices

  1. Follow Conventions

    • Use consistent naming
    • Follow existing patterns
    • Document changes
  2. Performance

    • Optimize queries
    • Use caching
    • Implement pagination
  3. Security

    • Validate inputs
    • Sanitize outputs
    • Use authentication
  4. Maintainability

    • Write tests
    • Document code
    • Version control