Overview of Device Management Architecture
In modern enterprise environments, managing hardware assets efficiently is critical for operational stability. A robust device management system must handle the lifecycle of hardware, from registration and real-time status tracking to scheduled maintenance and analytical reporting. Using TypeScript across the full stack provides the type safety and structural integrity needed to manage complex data relations and asynchronous workflows.
A standard implementation follows a multi-tier architecture:
- Client Tier: A reactive user interface built with React and TypeScript.
- Application Tier: A Node.js environment using Express to handle business logic and API routing.
- Persistence Tier: A relational database like MySQL, managed through TypeORM for structured data handling.
Core Data Structures
Defining clear interfaces is the first step in ensuring consistency between the backend and the frontend. We define the primary asset and its operational status.
enum AssetStatus {
OPERATIONAL = 'operational',
DOWN = 'down',
MAINTENANCE = 'maintenance'
}
interface HardwareAsset {
uid: string;
modelName: string;
category: string;
operationalStatus: AssetStatus;
lastInspected: Date;
nextServiceDue: Date;
}
interface ServiceLog {
logId: number;
assetUid: string;
performedAt: Date;
technicianNotes: string;
}
Backend Implementation with Express and TypeORM
The backend serves as the bridge between the database and the client. Using TypeORM's repository patern, we can create clean, testable controllers for asset management.
import { Router, Request, Response } from 'express';
import { getRepository } from 'typeorm';
import { AssetEntity } from './entities/AssetEntity';
const assetRouter = Router();
// Retrieve all assets from the inventory
assetRouter.get('/inventory', async (req: Request, res: Response) => {
const assetRepo = getRepository(AssetEntity);
const inventory = await assetRepo.find();
res.status(200).json(inventory);
});
// Register a new hardware unit
assetRouter.post('/inventory', async (req: Request, res: Response) => {
const assetRepo = getRepository(AssetEntity);
const newUnit = assetRepo.create(req.body);
const savedUnit = await assetRepo.save(newUnit);
res.status(201).json(savedUnit);
});
// Update asset details by ID
assetRouter.patch('/inventory/:id', async (req: Request, res: Response) => {
const assetRepo = getRepository(AssetEntity);
const targetId = req.params.id;
try {
await assetRepo.update(targetId, req.body);
res.status(200).send({ message: 'Asset updated successfully' });
} catch (error) {
res.status(500).send({ error: 'Update failed' });
}
});
export default assetRouter;
Automated Status Monitoring
To ensure high availability, the system should include a background worker that monitors device health. Using node-cron, we can schedule periodic checks to identify assets that have gone offline.
import cron from 'node-cron';
import { getRepository } from 'typeorm';
import { AssetEntity } from './entities/AssetEntity';
// Run health check every 30 minutes
cron.schedule('*/30 * * * *', async () => {
const assetRepo = getRepository(AssetEntity);
const offlineAssets = await assetRepo.find({ where: { operationalStatus: 'down' } });
offlineAssets.forEach(asset => {
console.error(`Alert: Asset ${asset.modelName} (UID: ${asset.uid}) is currently unresponsive.`);
// Logic for triggering SMS or Email notifications would go here
});
});
Service Logging and Maintainance Tracking
Historical records are vital for auditing and predicting hardware failure. The service log module tracks every intervention performed on a device.
import { Router } from 'express';
import { getRepository } from 'typeorm';
import { ServiceLogEntity } from './entities/ServiceLogEntity';
const serviceRouter = Router();
serviceRouter.post('/log-entry', async (req, res) => {
const logRepo = getRepository(ServiceLogEntity);
const entry = logRepo.create({
assetUid: req.body.assetId,
performedAt: new Date(),
technicianNotes: req.body.notes
});
await logRepo.save(entry);
res.status(201).json(entry);
});
serviceRouter.get('/history/:assetId', async (req, res) => {
const logRepo = getRepository(ServiceLogEntity);
const history = await logRepo.find({
where: { assetUid: req.params.assetId },
order: { performedAt: 'DESC' }
});
res.json(history);
});
Frontend Development with React and TypeScript
The frontend provides an interface for users to interact with the asset data. We use hooks to manage state and Axios for API communication.
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const AssetDashboard: React.FC = () => {
const [inventory, setInventory] = useState<HardwareAsset[]>([]);
const loadInventory = async () => {
const { data } = await axios.get('/api/inventory');
setInventory(data);
};
useEffect(() => {
loadInventory();
}, []);
return (
<div className="dashboard">
<h2>Hardware Inventory Management</h2>
<table>
<thead>
<tr>
<th>Model</th>
<th>Status</th>
<th>Next Service</th>
</tr>
</thead>
<tbody>
{inventory.map(item => (
<tr key={item.uid}>
<td>{item.modelName}</td>
<td>{item.operationalStatus}</td>
<td>{new Date(item.nextServiceDue).toLocaleDateString()}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
Data Aggregation and Reporting
Managers often require high-level summaries. We can implement a reporting endpoint that aggregates the current state of the entire fleet.
assetRouter.get('/summary-report', async (req, res) => {
const assetRepo = getRepository(AssetEntity);
const allItems = await assetRepo.find();
const stats = {
totalUnits: allItems.length,
operationalCount: allItems.filter(a => a.operationalStatus === AssetStatus.OPERATIONAL).length,
maintenanceRequired: allItems.filter(a => a.operationalStatus === AssetStatus.MAINTENANCE).length,
failureRate: (allItems.filter(a => a.operationalStatus === AssetStatus.DOWN).length / allItems.length) * 100
};
res.json(stats);
});