Fix all req.params and req.query type errors

- Add getParamString helper function for req.params
- Replace all req.params destructuring with getParamString
- Fix remaining req.query.* direct usage errors
- All TypeScript compilation errors now resolved
This commit is contained in:
2026-01-14 16:50:33 +01:00
parent 81d477ec8c
commit f51e9b8574
6 changed files with 241 additions and 34 deletions

View File

@@ -6,7 +6,7 @@ import { logger } from '../services/logger.js';
import { calculateRequiredEffortApplicationManagementWithBreakdown } from '../services/effortCalculation.js';
import { findBIAMatch, loadBIAData, clearBIACache, calculateSimilarity } from '../services/biaMatchingService.js';
import { calculateApplicationCompleteness } from '../services/dataCompletenessConfig.js';
import { getQueryString } from '../utils/queryHelpers.js';
import { getQueryString, getParamString } from '../utils/queryHelpers.js';
import type { SearchFilters, ReferenceValue, ClassificationResult, ApplicationDetails, ApplicationStatus } from '../types/index.js';
import type { Server, Flows, Certificate, Domain, AzureSubscription, CMDBObjectTypeName } from '../generated/jira-types.js';
@@ -323,7 +323,7 @@ router.get('/bia-comparison', async (req: Request, res: Response) => {
// - mode=edit: Force refresh from Jira for editing (includes _jiraUpdatedAt for conflict detection)
router.get('/:id', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const id = getParamString(req, 'id');
const mode = getQueryString(req, 'mode');
// Don't treat special routes as application IDs
@@ -359,7 +359,7 @@ router.get('/:id', async (req: Request, res: Response) => {
// Update application with conflict detection
router.put('/:id', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const id = getParamString(req, 'id');
const { updates, _jiraUpdatedAt } = req.body as {
updates?: {
applicationFunctions?: ReferenceValue[];
@@ -471,7 +471,7 @@ router.put('/:id', async (req: Request, res: Response) => {
// Force update (ignore conflicts)
router.put('/:id/force', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const id = getParamString(req, 'id');
const updates = req.body;
const application = await dataService.getApplicationById(id);
@@ -552,7 +552,7 @@ router.post('/calculate-effort', async (req: Request, res: Response) => {
// Get application classification history
router.get('/:id/history', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const id = getParamString(req, 'id');
const history = await databaseService.getClassificationsByApplicationId(id);
res.json(history);
} catch (error) {
@@ -564,7 +564,8 @@ router.get('/:id/history', async (req: Request, res: Response) => {
// Get related objects for an application (from cache)
router.get('/:id/related/:objectType', async (req: Request, res: Response) => {
try {
const { id, objectType } = req.params;
const id = getParamString(req, 'id');
const objectType = getParamString(req, 'objectType');
// Map object type string to CMDBObjectTypeName
const typeMap: Record<string, CMDBObjectTypeName> = {

View File

@@ -8,7 +8,7 @@ import { Router, Request, Response } from 'express';
import { cacheStore } from '../services/cacheStore.js';
import { syncEngine } from '../services/syncEngine.js';
import { logger } from '../services/logger.js';
import { getQueryString } from '../utils/queryHelpers.js';
import { getQueryString, getParamString } from '../utils/queryHelpers.js';
import { OBJECT_TYPES } from '../generated/jira-schema.js';
import type { CMDBObjectTypeName } from '../generated/jira-types.js';
@@ -77,13 +77,12 @@ router.post('/sync', async (req: Request, res: Response) => {
// Trigger sync for a specific object type
router.post('/sync/:objectType', async (req: Request, res: Response) => {
try {
const { objectType } = req.params;
const objectType = getParamString(req, 'objectType');
// Validate object type - convert to string if array
const objectTypeStr = Array.isArray(objectType) ? objectType[0] : objectType;
if (!OBJECT_TYPES[objectTypeStr]) {
// Validate object type
if (!OBJECT_TYPES[objectType]) {
res.status(400).json({
error: `Unknown object type: ${objectTypeStr}`,
error: `Unknown object type: ${objectType}`,
supportedTypes: Object.keys(OBJECT_TYPES),
});
return;
@@ -91,22 +90,23 @@ router.post('/sync/:objectType', async (req: Request, res: Response) => {
logger.info(`Manual sync triggered for ${objectType}`);
const result = await syncEngine.syncType(objectTypeStr as CMDBObjectTypeName);
const result = await syncEngine.syncType(objectType as CMDBObjectTypeName);
res.json({
status: 'completed',
objectType: objectTypeStr,
objectType: objectType,
stats: result,
});
} catch (error) {
const objectType = getParamString(req, 'objectType');
const errorMessage = error instanceof Error ? error.message : 'Failed to sync object type';
logger.error(`Failed to sync object type ${req.params.objectType}`, error);
logger.error(`Failed to sync object type ${objectType}`, error);
// Return 409 (Conflict) if sync is already in progress, otherwise 500
const statusCode = errorMessage.includes('already in progress') ? 409 : 500;
res.status(statusCode).json({
error: errorMessage,
objectType: req.params.objectType,
objectType: objectType,
});
}
});
@@ -114,12 +114,11 @@ router.post('/sync/:objectType', async (req: Request, res: Response) => {
// Clear cache for a specific type
router.delete('/clear/:objectType', async (req: Request, res: Response) => {
try {
const { objectType } = req.params;
const objectTypeStr = Array.isArray(objectType) ? objectType[0] : objectType;
const objectType = getParamString(req, 'objectType');
if (!OBJECT_TYPES[objectTypeStr]) {
if (!OBJECT_TYPES[objectType]) {
res.status(400).json({
error: `Unknown object type: ${objectTypeStr}`,
error: `Unknown object type: ${objectType}`,
supportedTypes: Object.keys(OBJECT_TYPES),
});
return;
@@ -135,7 +134,8 @@ router.delete('/clear/:objectType', async (req: Request, res: Response) => {
deletedCount: deleted,
});
} catch (error) {
logger.error(`Failed to clear cache for ${req.params.objectType}`, error);
const objectType = getParamString(req, 'objectType');
logger.error(`Failed to clear cache for ${objectType}`, error);
res.status(500).json({ error: 'Failed to clear cache' });
}
});

View File

@@ -4,14 +4,14 @@ import { dataService } from '../services/dataService.js';
import { databaseService } from '../services/database.js';
import { logger } from '../services/logger.js';
import { config } from '../config/env.js';
import { getQueryString, getQueryNumber } from '../utils/queryHelpers.js';
import { getQueryString, getQueryNumber, getParamString } from '../utils/queryHelpers.js';
const router = Router();
// Get AI classification for an application
router.post('/suggest/:id', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const id = getParamString(req, 'id');
// Get provider from query parameter or request body, default to config
const provider = (getQueryString(req, 'provider') as AIProvider) || (req.body.provider as AIProvider) || config.defaultAIProvider;
@@ -53,7 +53,7 @@ router.get('/taxonomy', (req: Request, res: Response) => {
// Get function by code
router.get('/function/:code', (req: Request, res: Response) => {
try {
const { code } = req.params;
const code = getParamString(req, 'code');
const func = aiService.getFunctionByCode(code);
if (!func) {
@@ -112,7 +112,7 @@ router.get('/ai-status', (req: Request, res: Response) => {
// Get the AI prompt for an application (for debugging/copy-paste)
router.get('/prompt/:id', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const id = getParamString(req, 'id');
const application = await dataService.getApplicationById(id);
if (!application) {
@@ -131,7 +131,7 @@ router.get('/prompt/:id', async (req: Request, res: Response) => {
// Chat with AI about an application
router.post('/chat/:id', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const id = getParamString(req, 'id');
const { message, conversationId, provider: requestProvider } = req.body;
if (!message || typeof message !== 'string' || message.trim().length === 0) {
@@ -168,7 +168,7 @@ router.post('/chat/:id', async (req: Request, res: Response) => {
// Get conversation history
router.get('/chat/conversation/:conversationId', (req: Request, res: Response) => {
try {
const { conversationId } = req.params;
const conversationId = getParamString(req, 'conversationId');
const messages = aiService.getConversationHistory(conversationId);
if (messages.length === 0) {
@@ -186,7 +186,7 @@ router.get('/chat/conversation/:conversationId', (req: Request, res: Response) =
// Clear a conversation
router.delete('/chat/conversation/:conversationId', (req: Request, res: Response) => {
try {
const { conversationId } = req.params;
const conversationId = getParamString(req, 'conversationId');
const deleted = aiService.clearConversation(conversationId);
if (!deleted) {

View File

@@ -7,7 +7,7 @@
import { Router, Request, Response } from 'express';
import { cmdbService } from '../services/cmdbService.js';
import { logger } from '../services/logger.js';
import { getQueryString, getQueryNumber } from '../utils/queryHelpers.js';
import { getQueryString, getQueryNumber, getParamString } from '../utils/queryHelpers.js';
import { OBJECT_TYPES } from '../generated/jira-schema.js';
import type { CMDBObject, CMDBObjectTypeName } from '../generated/jira-types.js';
@@ -32,7 +32,7 @@ router.get('/', (req: Request, res: Response) => {
// Get all objects of a type
router.get('/:type', async (req: Request, res: Response) => {
try {
const { type } = req.params;
const type = getParamString(req, 'type');
const limit = getQueryNumber(req, 'limit', 1000);
const offset = getQueryNumber(req, 'offset', 0);
const search = getQueryString(req, 'search');
@@ -71,7 +71,8 @@ router.get('/:type', async (req: Request, res: Response) => {
// Get a specific object by ID
router.get('/:type/:id', async (req: Request, res: Response) => {
try {
const { type, id } = req.params;
const type = getParamString(req, 'type');
const id = getParamString(req, 'id');
const forceRefresh = getQueryString(req, 'refresh') === 'true';
// Validate type
@@ -102,7 +103,9 @@ router.get('/:type/:id', async (req: Request, res: Response) => {
// Get related objects
router.get('/:type/:id/related/:relationType', async (req: Request, res: Response) => {
try {
const { type, id, relationType } = req.params;
const type = getParamString(req, 'type');
const id = getParamString(req, 'id');
const relationType = getParamString(req, 'relationType');
const attribute = getQueryString(req, 'attribute');
// Validate types
@@ -139,7 +142,9 @@ router.get('/:type/:id/related/:relationType', async (req: Request, res: Respons
// Get objects referencing this object (inbound references)
router.get('/:type/:id/referenced-by/:sourceType', async (req: Request, res: Response) => {
try {
const { type, id, sourceType } = req.params;
const type = getParamString(req, 'type');
const id = getParamString(req, 'id');
const sourceType = getParamString(req, 'sourceType');
const attribute = getQueryString(req, 'attribute');
// Validate types

View File

@@ -1,5 +1,5 @@
/**
* Helper functions for Express request query parameters
* Helper functions for Express request query and params
*/
import { Request } from 'express';
@@ -32,3 +32,12 @@ export function getQueryBoolean(req: Request, key: string, defaultValue = false)
if (value === undefined) return defaultValue;
return value === 'true' || value === '1';
}
/**
* Get a route parameter as a string, handling both string and string[] types
*/
export function getParamString(req: Request, key: string): string {
const value = req.params[key];
if (Array.isArray(value)) return value[0] as string;
return value as string;
}