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
- 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
});
- Add to TableMetadata
// backend/scripts/add-custom-citype.js
const metadata = {
ciType: 'CustomDevice',
fields: [
{
name: 'customField1',
label: 'Custom Field 1',
type: 'string',
required: true
}
]
};
- 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
-
Follow Conventions
- Use consistent naming
- Follow existing patterns
- Document changes
-
Performance
- Optimize queries
- Use caching
- Implement pagination
-
Security
- Validate inputs
- Sanitize outputs
- Use authentication
-
Maintainability
- Write tests
- Document code
- Version control