- Restore blue PageHeader on Dashboard (/app-components) - Update homepage (/) with subtle header design without blue bar - Add uniform PageHeader styling to application edit page - Fix Rapporten link on homepage to point to /reports overview - Improve header descriptions spacing for better readability
30 KiB
Refactor Plan - Phase 1: Architecture Analysis
Created: 2025-01-XX
Status: Phase 1 - Analysis Only (No functional changes)
Executive Summary
This document provides a comprehensive analysis of the current architecture and a plan for refactoring the CMDB Insight codebase to improve maintainability, reduce duplication, and establish clearer separation of concerns.
Scope: This is Phase 1 - analysis and planning only. No code changes will be made in this phase.
Table of Contents
- Current Architecture Map
- Pain Points & Duplication
- Target Architecture
- Migration Steps
- Explicit Deletion List
- API Payload Contract & Recursion Insights
Current Architecture Map
File/Folder Structure
backend/src/
├── services/
│ ├── jiraAssets.ts # High-level Jira Assets service (business logic, ~3454 lines)
│ ├── jiraAssetsClient.ts # Low-level Jira Assets API client (~646 lines)
│ ├── schemaDiscoveryService.ts # Discovers schema from Jira API (~520 lines)
│ ├── schemaCacheService.ts # Caches schema metadata
│ ├── schemaConfigurationService.ts # Manages enabled object types
│ ├── schemaMappingService.ts # Maps object types to schema IDs
│ ├── syncEngine.ts # Background sync service (full/incremental) (~630 lines)
│ ├── normalizedCacheStore.ts # EAV pattern DB store (~1695 lines)
│ ├── cmdbService.ts # Universal schema-driven CMDB service (~531 lines)
│ ├── queryBuilder.ts # Dynamic SQL query builder (~278 lines)
│ ├── cacheStore.old.ts # Legacy cache store (deprecated)
│ └── database/
│ ├── normalized-schema.ts # DB schema definitions (Postgres/SQLite)
│ ├── factory.ts # Database adapter factory
│ ├── interface.ts # Database adapter interface
│ ├── postgresAdapter.ts # PostgreSQL adapter
│ ├── sqliteAdapter.ts # SQLite adapter
│ ├── migrate-to-normalized-schema.ts
│ └── fix-object-types-constraints.ts
├── routes/
│ ├── applications.ts # Application-specific endpoints (~780 lines)
│ ├── objects.ts # Generic object endpoints (~185 lines)
│ ├── cache.ts # Cache/sync endpoints (~165 lines)
│ ├── schema.ts # Schema endpoints (~107 lines)
│ └── schemaConfiguration.ts # Schema configuration endpoints
├── generated/
│ ├── jira-types.ts # Generated TypeScript types (~934 lines)
│ └── jira-schema.ts # Generated schema metadata (~895 lines)
└── scripts/
├── discover-schema.ts # Schema discovery CLI
├── generate-types-from-db.ts # Type generation from DB (~485 lines)
└── generate-schema.ts # Legacy schema generation
Module Responsibilities
1. Jira Assets API Client Calls
Primary Files:
-
services/jiraAssetsClient.ts- Low-level HTTP client- Methods:
getObject(),searchObjects(),getAllObjectsOfType(),updateObject(),parseObject() - Handles authentication (service account token for reads, user PAT for writes)
- API detection (Data Center vs Cloud)
- Object parsing from Jira format to CMDB format
- Methods:
-
services/jiraAssets.ts- High-level business logic wrapper- Application-specific methods (e.g.,
getApplications(),updateApplication()) - Dashboard data aggregation
- Reference data caching
- Team dashboard calculations
- Legacy API methods
- Application-specific methods (e.g.,
Dependencies:
- Uses
schemaCacheServicefor type lookups - Uses
schemaMappingServicefor schema ID resolution
2. Schema Discovery/Sync
Primary Files:
-
services/schemaDiscoveryService.ts- Discovers object types from Jira API (
/objectschema/{id}/objecttypes/flat) - Discovers attributes for each object type (
/objecttype/{id}/attributes) - Stores schema in database (
object_types,attributestables) - Provides lookup methods:
getAttribute(),getAttributesForType(),getObjectType()
- Discovers object types from Jira API (
-
services/schemaCacheService.ts- Caches schema from database
- Provides runtime schema access
-
services/schemaConfigurationService.ts- Manages enabled/disabled object types
- Schema-to-object-type mapping
- Configuration validation
-
services/schemaMappingService.ts- Maps object type names to schema IDs
- Legacy compatibility
Scripts:
scripts/discover-schema.ts- CLI tool to trigger schema discoveryscripts/generate-types-from-db.ts- Generates TypeScript types from database
3. Object Sync/Import
Primary Files:
services/syncEngine.tsfullSync()- Syncs all enabled object typesincrementalSync()- Periodic sync of updated objectssyncType()- Sync single object typesyncObject()- Sync single object- Uses
jiraAssetsClient.getAllObjectsOfType()for fetching - Uses
normalizedCacheStore.batchUpsertObjects()for storage
Flow:
- Fetch objects from Jira via
jiraAssetsClient - Parse objects via
jiraAssetsClient.parseObject() - Store objects via
normalizedCacheStore.batchUpsertObjects() - Extract relations via
normalizedCacheStore.extractAndStoreRelations()
4. DB Normalization Store (EAV)
Primary Files:
-
services/normalizedCacheStore.ts(~1695 lines)- Storage:
normalizeObject(),batchUpsertObjects(),upsertObject() - Retrieval:
getObject(),getObjects(),reconstructObject(),loadAttributeValues() - Relations:
extractAndStoreRelations(),getRelatedObjects(),getReferencingObjects() - Query:
queryWithFilters()(usesqueryBuilder)
- Storage:
-
services/database/normalized-schema.ts- Defines EAV schema:
objects,attributes,attribute_values,object_relations
- Defines EAV schema:
EAV Pattern:
objectstable: Minimal metadata (id, objectKey, label, type, timestamps)attributestable: Schema metadata (jira_attr_id, field_name, type, is_multiple, etc.)attribute_valuestable: Actual values (text_value, number_value, boolean_value, reference_object_id, array_index)object_relationstable: Extracted relationships (source_id, target_id, attribute_id)
5. Backend API Endpoints
Primary Files:
-
routes/applications.ts- Application-specific endpointsPOST /applications/search- Search with filtersGET /applications/:id- Get application detailsPUT /applications/:id- Update applicationGET /applications/:id/related/:type- Get related objects- Dashboard endpoints (
/team-dashboard,/team-portfolio-health)
-
routes/objects.ts- Generic object endpointsGET /objects- List supported typesGET /objects/:type- Get all objects of typeGET /objects/:type/:id- Get single objectGET /objects/:type/:id/related/:relationType- Get related objects
-
routes/cache.ts- Cache managementPOST /cache/sync- Trigger full syncPOST /cache/sync/:objectType- Sync single typePOST /cache/refresh-application/:id- Refresh single object
-
routes/schema.ts- Schema endpointsGET /schema- Get schema metadataGET /schema/types- List object typesGET /schema/types/:type- Get type definition
Service Layer:
- Routes delegate to
cmdbService,dataService,syncEngine cmdbServiceprovides unified interface (read/write with conflict detection)dataServiceprovides application-specific business logic
6. Query Builder (Object Reconstruction)
Primary Files:
services/queryBuilder.tsbuildWhereClause()- Builds WHERE conditions from filtersbuildFilterCondition()- Handles different attribute types (text, reference, number, etc.)buildOrderBy()- ORDER BY clausebuildPagination()- LIMIT/OFFSET clause
Usage:
- Used by
normalizedCacheStore.queryWithFilters()to build dynamic SQL - Handles complex filters (exact match, exists, contains, reference filters)
7. Generated Types/Reflect Scripts
Primary Files:
scripts/generate-types-from-db.ts- Reads from
object_typesandattributestables - Generates
generated/jira-types.ts(TypeScript interfaces) - Generates
generated/jira-schema.ts(Schema metadata with lookup maps)
- Reads from
Generated Output:
jira-types.ts: TypeScript interfaces for each object type (e.g.,ApplicationComponent,Server)jira-schema.ts:OBJECT_TYPESrecord, lookup maps (TYPE_ID_TO_NAME,JIRA_NAME_TO_TYPE), helper functions
Pain Points & Duplication
1. Dual API Clients (jiraAssets.ts vs jiraAssetsClient.ts)
Issue: Two separate services handling Jira API calls:
jiraAssetsClient.ts- Low-level, focused on API communicationjiraAssets.ts- High-level, contains business logic + API calls
Problems:
- Duplication of API request logic
- Inconsistent error handling
- Mixed concerns (business logic + infrastructure)
jiraAssets.tsis huge (~3454 lines) and hard to maintain
Location:
backend/src/services/jiraAssets.ts- Contains both API calls and business logicbackend/src/services/jiraAssetsClient.ts- Clean separation but incomplete
2. Schema Discovery/Caching Duplication
Issue: Multiple services handling schema metadata:
schemaDiscoveryService.ts- Discovers and stores schemaschemaCacheService.ts- Caches schema from DBschemaConfigurationService.ts- Manages enabled typesschemaMappingService.ts- Maps types to schema IDs
Problems:
- Unclear boundaries between services
- Potential for stale cache
- Complex initialization dependencies
Location:
backend/src/services/schema*.tsfiles
3. Mixed Responsibilities in normalizedCacheStore.ts
Issue: Large file (~1695 lines) handling multiple concerns:
- Database operations (EAV storage/retrieval)
- Object reconstruction (TypeScript object building)
- Reference resolution (fetching missing referenced objects)
- Relation extraction
Problems:
- Hard to test individual concerns
- Difficult to optimize specific operations
- Violates single responsibility principle
Location:
backend/src/services/normalizedCacheStore.ts
4. Application-Specific Logic in Generic Services
Issue: Application-specific business logic scattered:
routes/applications.ts- Application-specific endpoints (~780 lines)services/dataService.ts- Application business logicservices/jiraAssets.ts- Application aggregation logicservices/cmdbService.ts- Generic service used by applications
Problems:
- Hard to extend to other object types
- Tight coupling between routes and services
- Business logic mixed with data access
Location:
backend/src/routes/applications.tsbackend/src/services/dataService.ts
5. Type Generation Pipeline Complexity
Issue: Multiple scripts and services involved in type generation:
scripts/discover-schema.ts- Triggers schema discoveryservices/schemaDiscoveryService.ts- Discovers schemascripts/generate-types-from-db.ts- Generates TypeScript filesgenerated/jira-types.ts- Generated output (must be regenerated when schema changes)
Problems:
- Unclear workflow
- Manual steps required
- Generated files can get out of sync
Location:
backend/scripts/discover-schema.tsbackend/scripts/generate-types-from-db.tsbackend/src/generated/*.ts
6. Legacy Code (cacheStore.old.ts)
Issue: Old cache store still present in codebase:
services/cacheStore.old.ts- Deprecated implementation
Problems:
- Confusing for new developers
- Takes up space
- No longer used
Location:
backend/src/services/cacheStore.old.ts
7. Inconsistent Error Handling
Issue: Different error handling patterns across services:
- Some use try/catch with logger
- Some throw errors
- Some return null/undefined
- Inconsistent error messages
Problems:
- Hard to debug issues
- Inconsistent API responses
- No centralized error handling
Location:
- Throughout codebase
Target Architecture
Domain/Infrastructure/Services/API Separation
backend/src/
├── domain/ # Domain models & business logic
│ ├── cmdb/
│ │ ├── Object.ts # CMDBObject base interface
│ │ ├── ObjectType.ts # ObjectTypeDefinition
│ │ ├── Attribute.ts # AttributeDefinition
│ │ └── Reference.ts # ObjectReference
│ ├── schema/
│ │ ├── Schema.ts # Schema domain model
│ │ └── SchemaDiscovery.ts # Schema discovery business logic
│ └── sync/
│ ├── SyncEngine.ts # Sync orchestration logic
│ └── SyncStrategy.ts # Sync strategies (full, incremental)
│
├── infrastructure/ # External integrations & infrastructure
│ ├── jira/
│ │ ├── JiraAssetsClient.ts # Low-level HTTP client (pure API calls)
│ │ ├── JiraAssetsApi.ts # API contract definitions
│ │ └── JiraResponseParser.ts # Response parsing utilities
│ └── database/
│ ├── adapters/ # Database adapters (Postgres, SQLite)
│ ├── schema/ # Schema definitions
│ └── migrations/ # Database migrations
│
├── services/ # Application services (use cases)
│ ├── cmdb/
│ │ ├── CmdbReadService.ts # Read operations
│ │ ├── CmdbWriteService.ts # Write operations with conflict detection
│ │ └── CmdbQueryService.ts # Query operations
│ ├── schema/
│ │ ├── SchemaService.ts # Schema CRUD operations
│ │ └── SchemaDiscoveryService.ts # Schema discovery orchestration
│ └── sync/
│ └── SyncService.ts # Sync orchestration
│
├── repositories/ # Data access layer
│ ├── ObjectRepository.ts # Object CRUD (uses EAV store)
│ ├── AttributeRepository.ts # Attribute value access
│ ├── RelationRepository.ts # Relationship access
│ └── SchemaRepository.ts # Schema metadata access
│
├── stores/ # Storage implementations
│ ├── NormalizedObjectStore.ts # EAV pattern implementation
│ ├── ObjectReconstructor.ts # Object reconstruction from EAV
│ └── RelationExtractor.ts # Relation extraction logic
│
├── api/ # HTTP API layer
│ ├── routes/
│ │ ├── objects.ts # Generic object endpoints
│ │ ├── schema.ts # Schema endpoints
│ │ └── sync.ts # Sync endpoints
│ ├── handlers/ # Request handlers (thin layer)
│ │ ├── ObjectHandler.ts
│ │ ├── SchemaHandler.ts
│ │ └── SyncHandler.ts
│ └── middleware/ # Auth, validation, etc.
│
├── queries/ # Query builders
│ ├── ObjectQueryBuilder.ts # SQL query construction
│ └── FilterBuilder.ts # Filter condition builder
│
└── scripts/ # CLI tools
├── discover-schema.ts # Schema discovery CLI
└── generate-types.ts # Type generation CLI
Key Principles
- Domain Layer: Pure business logic, no infrastructure dependencies
- Infrastructure Layer: External integrations (Jira API, database)
- Services Layer: Orchestrates domain logic and infrastructure
- Repository Layer: Data access abstraction
- Store Layer: Storage implementations (EAV, caching)
- API Layer: Thin HTTP handlers that delegate to services
Migration Steps
Step 1: Extract Jira API Client (Infrastructure)
Goal: Create pure infrastructure client with no business logic
- Consolidate
jiraAssetsClient.tsandjiraAssets.tsAPI methods into singleJiraAssetsClient - Extract API contract types to
infrastructure/jira/JiraAssetsApi.ts - Move response parsing to
infrastructure/jira/JiraResponseParser.ts - Remove business logic from API client (delegate to services)
Files to Create:
infrastructure/jira/JiraAssetsClient.tsinfrastructure/jira/JiraAssetsApi.tsinfrastructure/jira/JiraResponseParser.ts
Files to Modify:
services/jiraAssets.ts- Remove API calls, keep business logicservices/jiraAssetsClient.ts- Merge into infrastructure client
Files to Delete:
- None (yet - deprecate old files after migration)
Step 2: Extract Schema Domain & Services
Goal: Separate schema discovery business logic from infrastructure
- Create
domain/schema/with domain models - Move schema discovery logic to
services/schema/SchemaDiscoveryService.ts - Consolidate schema caching in
services/schema/SchemaService.ts - Remove duplication between
schemaCacheService,schemaConfigurationService,schemaMappingService
Files to Create:
domain/schema/Schema.tsservices/schema/SchemaService.tsservices/schema/SchemaDiscoveryService.ts
Files to Modify:
services/schemaDiscoveryService.ts- Split into domain + serviceservices/schemaCacheService.ts- Merge into SchemaServiceservices/schemaConfigurationService.ts- Merge into SchemaServiceservices/schemaMappingService.ts- Merge into SchemaService
Files to Delete:
services/schemaCacheService.ts(after merge)services/schemaMappingService.ts(after merge)
Step 3: Extract Repository Layer
Goal: Abstract data access from business logic
- Create
repositories/ObjectRepository.ts- Interface for object CRUD - Create
repositories/AttributeRepository.ts- Interface for attribute access - Create
repositories/RelationRepository.ts- Interface for relationships - Implement repositories using
NormalizedObjectStore
Files to Create:
repositories/ObjectRepository.tsrepositories/AttributeRepository.tsrepositories/RelationRepository.tsrepositories/SchemaRepository.ts
Files to Modify:
services/normalizedCacheStore.ts- Extract repository implementations
Step 4: Extract Store Implementations
Goal: Separate storage implementations from business logic
- Extract EAV storage to
stores/NormalizedObjectStore.ts - Extract object reconstruction to
stores/ObjectReconstructor.ts - Extract relation extraction to
stores/RelationExtractor.ts
Files to Create:
stores/NormalizedObjectStore.ts- EAV storage/retrievalstores/ObjectReconstructor.ts- TypeScript object reconstructionstores/RelationExtractor.ts- Relation extraction from objects
Files to Modify:
services/normalizedCacheStore.ts- Split into store classes
Step 5: Extract Query Builders
Goal: Separate query construction from execution
- Move
queryBuilder.tstoqueries/ObjectQueryBuilder.ts - Extract filter building to
queries/FilterBuilder.ts
Files to Create:
queries/ObjectQueryBuilder.tsqueries/FilterBuilder.ts
Files to Modify:
services/queryBuilder.ts- Move to queries/
Step 6: Extract CMDB Services
Goal: Separate read/write/query concerns
- Create
services/cmdb/CmdbReadService.ts- Read operations - Create
services/cmdb/CmdbWriteService.ts- Write operations with conflict detection - Create
services/cmdb/CmdbQueryService.ts- Query operations
Files to Create:
services/cmdb/CmdbReadService.tsservices/cmdb/CmdbWriteService.tsservices/cmdb/CmdbQueryService.ts
Files to Modify:
services/cmdbService.ts- Split into read/write/query services
Step 7: Extract Sync Service
Goal: Separate sync orchestration from storage
- Create
domain/sync/SyncEngine.ts- Sync business logic - Create
services/sync/SyncService.ts- Sync orchestration
Files to Create:
domain/sync/SyncEngine.tsservices/sync/SyncService.ts
Files to Modify:
services/syncEngine.ts- Split into domain + service
Step 8: Refactor API Routes
Goal: Thin HTTP handlers delegating to services
- Create
api/handlers/directory - Move route logic to handlers
- Routes become thin wrappers around handlers
Files to Create:
api/handlers/ObjectHandler.tsapi/handlers/SchemaHandler.tsapi/handlers/SyncHandler.ts
Files to Modify:
routes/applications.ts- Extract handlersroutes/objects.ts- Extract handlersroutes/cache.ts- Extract handlersroutes/schema.ts- Extract handlers
Step 9: Clean Up Legacy Code
Goal: Remove deprecated files
Files to Delete:
services/cacheStore.old.ts- Deprecated service files after migration complete
Step 10: Update Type Generation
Goal: Simplify type generation workflow
- Consolidate type generation logic
- Add automatic type generation on schema discovery
- Update documentation
Files to Modify:
scripts/generate-types-from-db.ts- Enhance with auto-discoveryscripts/discover-schema.ts- Auto-generate types after discovery
Explicit Deletion List
Phase 2 (After Migration Complete)
-
backend/src/services/cacheStore.old.ts- Reason: Legacy implementation, replaced by
normalizedCacheStore.ts - Deprecation date: TBD
- Reason: Legacy implementation, replaced by
-
backend/src/services/jiraAssets.ts(after extracting business logic)- Reason: API calls moved to infrastructure layer, business logic to services
- Replacement:
infrastructure/jira/JiraAssetsClient.ts+services/cmdb/Cmdb*Service.ts
-
backend/src/services/schemaCacheService.ts(after consolidation)- Reason: Merged into
services/schema/SchemaService.ts
- Reason: Merged into
-
backend/src/services/schemaMappingService.ts(after consolidation)- Reason: Merged into
services/schema/SchemaService.ts
- Reason: Merged into
-
backend/scripts/generate-schema.ts(if still present)- Reason: Replaced by
generate-types-from-db.ts
- Reason: Replaced by
Notes
- Keep old files until migration is complete and tested
- Mark as deprecated with
@deprecatedJSDoc comments - Add migration guide for each deprecated file
API Payload Contract & Recursion Insights
Jira Assets API Payload Structure
The Jira Assets API returns objects with the following nested structure:
interface JiraAssetsSearchResponse {
objectEntries: JiraAssetsObject[]; // Top-level array of objects
// ... pagination metadata
}
interface JiraAssetsObject {
id: number;
objectKey: string;
label: string;
objectType: {
id: number;
name: string;
};
attributes: JiraAssetsAttribute[]; // Array of attributes
updated?: string;
created?: string;
}
interface JiraAssetsAttribute {
objectTypeAttributeId: number;
objectTypeAttribute?: {
id: number;
name: string;
};
objectAttributeValues: Array<{ // Union type of value representations
value?: string; // For scalar values (text, number, etc.)
displayValue?: string; // Human-readable value
referencedObject?: { // For reference attributes
id: number;
objectKey: string;
label: string;
// ⚠️ CRITICAL: referencedObject may include attributes (level 2)
attributes?: JiraAssetsAttribute[]; // Recursive structure
};
status?: { // For status attributes
name: string;
};
// ... other type-specific fields
}>;
}
Key Insights
1. Recursive Structure
Issue: referencedObject may include attributes[] array (level 2 recursion).
Current Handling:
jiraAssetsClient.tsusesincludeAttributesDeep=2parameter- This causes referenced objects to include their attributes
- Referenced objects' attributes may themselves contain referenced objects (level 3, 4, etc.)
- Cycles are possible (Object A references Object B, Object B references Object A)
Current Code Location:
backend/src/services/jiraAssetsClient.ts:222-includeAttributesDeep=2backend/src/services/jiraAssetsClient.ts:259-260- Search with deep attributesbackend/src/services/jiraAssetsClient.ts:285-286- POST search with deep attributes
Impact:
- Response payloads can be very large (deeply nested)
- Memory usage increases with depth
- Parsing becomes more complex
2. Shallow Referenced Objects
Issue: When attributes[] is absent on a shallow referencedObject, do not wipe attributes.
Current Behavior:
- Some code paths may clear attributes if
attributesis missing - This is incorrect - absence of
attributesarray does not mean "no attributes" - It simply means "attributes not included in this response"
Critical Rule:
// ❌ WRONG: Don't do this
if (!referencedObject.attributes) {
referencedObject.attributes = []; // This wipes existing attributes!
}
// ✅ CORRECT: Preserve existing attributes if missing from response
if (referencedObject.attributes === undefined) {
// Don't modify - attributes simply not included in this response
// Keep any existing attributes that were previously loaded
}
Code Locations to Review:
backend/src/services/jiraAssetsClient.ts:parseObject()- Object parsingbackend/src/services/jiraAssetsClient.ts:parseAttributeValue()- Reference parsingbackend/src/services/normalizedCacheStore.ts:loadAttributeValues()- Reference reconstruction
3. Attribute Values Union Type
Issue: objectAttributeValues is a union type - different value representations based on attribute type.
Value Types:
- Scalar (text, number, boolean):
{ value?: string, displayValue?: string } - Reference:
{ referencedObject?: { id, objectKey, label, attributes? } } - Status:
{ status?: { name: string } } - Date/Datetime:
{ value?: string }(ISO string)
Current Handling:
jiraAssetsClient.ts:parseAttributeValue()uses switch onattrDef.type- Different parsing logic for each type
- Reference types extract
referencedObject, others usevalueordisplayValue
Code Location:
backend/src/services/jiraAssetsClient.ts:521-628-parseAttributeValue()method
4. Cycles and Recursion Depth
Issue: Recursive references can create cycles.
Examples:
- Application A references Team X
- Team X references Application A (via some attribute)
- This creates a cycle at depth 2
Current Handling:
- No explicit cycle detection
includeAttributesDeep=2limits depth but doesn't prevent cycles- Potential for infinite loops during reconstruction
Recommendation:
- Add cycle detection during object reconstruction
- Use visited set to track processed object IDs
- Limit recursion depth explicitly (not just via API parameter)
Code Locations:
backend/src/services/normalizedCacheStore.ts:loadAttributeValues()- Reference resolutionbackend/src/services/normalizedCacheStore.ts:reconstructObject()- Object reconstruction
Refactoring Considerations
- Create dedicated parser module for handling recursive payloads
- Add cycle detection utility
- Separate shallow vs deep parsing logic
- Preserve attribute state when attributes array is absent
- Document recursion depth limits clearly
Appendix: Module Dependency Graph
┌─────────────────────────────────────────────────────────┐
│ API Routes │
│ (applications.ts, objects.ts, cache.ts, schema.ts) │
└────────────┬────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Application Services │
│ (cmdbService.ts, dataService.ts) │
└────────────┬────────────────────────────────────────────┘
│
┌────────┴────────┐
▼ ▼
┌────────────┐ ┌──────────────────────────────┐
│ Sync │ │ Normalized Cache Store │
│ Engine │ │ (EAV Pattern) │
└─────┬──────┘ └──────────┬───────────────────┘
│ │
│ ▼
│ ┌─────────────────┐
│ │ Query Builder │
│ └─────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Jira Assets Client │
│ (jiraAssetsClient.ts, jiraAssets.ts) │
└────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Schema Services │
│ (schemaDiscovery, schemaCache, etc.) │
└─────────────────────────────────────────┘
Next Steps (Phase 2)
- Review and approve this plan
- Create detailed task breakdown for each migration step
- Set up feature branch for refactoring
- Implement changes incrementally with tests
- Update documentation as we go
End of Phase 1 - Analysis Document