- Fix query parameter type issues (string | string[] to string) in controllers - Add public getDatabaseAdapter() method to SchemaRepository for db access - Fix SchemaSyncService export and import issues - Fix referenceObject vs referenceObjectType property name - Add missing jiraAssetsClient import in normalizedCacheStore - Fix duplicate properties in object literals - Add type annotations for implicit any types - Fix type predicate issues with generics - Fix method calls (getEnabledObjectTypes, syncAllSchemas) - Fix type mismatches (ObjectTypeRecord vs expected types) - Fix Buffer type issue in biaMatchingService - Export SchemaSyncService class for ServiceFactory
128 lines
4.1 KiB
TypeScript
128 lines
4.1 KiB
TypeScript
import { Router } from 'express';
|
|
import { schemaCacheService } from '../services/schemaCacheService.js';
|
|
import { schemaSyncService } from '../services/SchemaSyncService.js';
|
|
import { schemaMappingService } from '../services/schemaMappingService.js';
|
|
import { logger } from '../services/logger.js';
|
|
import { jiraAssetsClient } from '../services/jiraAssetsClient.js';
|
|
import { requireAuth, requirePermission } from '../middleware/authorization.js';
|
|
|
|
const router = Router();
|
|
|
|
// All routes require authentication and search permission
|
|
router.use(requireAuth);
|
|
router.use(requirePermission('search'));
|
|
|
|
/**
|
|
* GET /api/schema
|
|
* Returns the complete Jira Assets schema with object types, attributes, and links
|
|
* Data is fetched from database (via cache service)
|
|
*/
|
|
router.get('/', async (req, res) => {
|
|
try {
|
|
// Get schema from cache (which fetches from database)
|
|
const schema = await schemaCacheService.getSchema();
|
|
|
|
// Optionally fetch Jira counts for comparison (can be slow, so make it optional)
|
|
let jiraCounts: Record<string, number> | undefined;
|
|
const includeJiraCounts = req.query.includeJiraCounts === 'true';
|
|
|
|
if (includeJiraCounts) {
|
|
const typeNames = Object.keys(schema.objectTypes);
|
|
logger.info(`Schema: Fetching object counts from Jira Assets for ${typeNames.length} object types...`);
|
|
|
|
jiraCounts = {};
|
|
// Fetch counts in parallel for better performance, using schema mappings
|
|
const countPromises = typeNames.map(async (typeName) => {
|
|
try {
|
|
// Get schema ID for this type
|
|
const schemaId = await schemaMappingService.getSchemaId(typeName);
|
|
const count = await jiraAssetsClient.getObjectCount(typeName, schemaId);
|
|
jiraCounts![typeName] = count;
|
|
return { typeName, count };
|
|
} catch (error) {
|
|
logger.warn(`Schema: Failed to get count for ${typeName}`, error);
|
|
// Use 0 as fallback if API call fails
|
|
jiraCounts![typeName] = 0;
|
|
return { typeName, count: 0 };
|
|
}
|
|
});
|
|
|
|
await Promise.all(countPromises);
|
|
logger.info(`Schema: Fetched counts for ${Object.keys(jiraCounts).length} object types from Jira Assets`);
|
|
}
|
|
|
|
const response = {
|
|
...schema,
|
|
jiraCounts,
|
|
};
|
|
|
|
res.json(response);
|
|
} catch (error) {
|
|
logger.error('Failed to get schema:', error);
|
|
res.status(500).json({ error: 'Failed to get schema' });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* GET /api/schema/object-type/:typeName
|
|
* Returns details for a specific object type
|
|
*/
|
|
router.get('/object-type/:typeName', async (req, res) => {
|
|
try {
|
|
const { typeName } = req.params;
|
|
|
|
// Get schema from cache
|
|
const schema = await schemaCacheService.getSchema();
|
|
const typeDef = schema.objectTypes[typeName];
|
|
|
|
if (!typeDef) {
|
|
return res.status(404).json({ error: `Object type '${typeName}' not found` });
|
|
}
|
|
|
|
res.json(typeDef);
|
|
} catch (error) {
|
|
logger.error('Failed to get object type:', error);
|
|
res.status(500).json({ error: 'Failed to get object type' });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* POST /api/schema/discover
|
|
* Manually trigger schema synchronization from Jira API
|
|
* Requires manage_settings permission
|
|
*/
|
|
router.post('/discover', requirePermission('manage_settings'), async (req, res) => {
|
|
try {
|
|
logger.info('Schema: Manual schema sync triggered');
|
|
const result = await schemaSyncService.syncAll();
|
|
schemaCacheService.invalidate(); // Invalidate cache
|
|
|
|
res.json({
|
|
message: 'Schema synchronization completed',
|
|
...result,
|
|
});
|
|
} catch (error) {
|
|
logger.error('Failed to sync schema:', error);
|
|
res.status(500).json({
|
|
error: 'Failed to sync schema',
|
|
details: error instanceof Error ? error.message : String(error),
|
|
});
|
|
}
|
|
});
|
|
|
|
/**
|
|
* GET /api/schema/sync-progress
|
|
* Get current sync progress
|
|
*/
|
|
router.get('/sync-progress', requirePermission('manage_settings'), async (req, res) => {
|
|
try {
|
|
const progress = schemaSyncService.getProgress();
|
|
res.json(progress);
|
|
} catch (error) {
|
|
logger.error('Failed to get sync progress:', error);
|
|
res.status(500).json({ error: 'Failed to get sync progress' });
|
|
}
|
|
});
|
|
|
|
export default router;
|