@hamak/smart-data-dico 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/backend/dist/server.mjs +82212 -0
  2. package/bin/cli.js +28 -17
  3. package/package.json +28 -27
  4. package/backend/package.json +0 -51
  5. package/backend/src/__tests__/integration/api.test.ts +0 -149
  6. package/backend/src/__tests__/setup.ts +0 -24
  7. package/backend/src/__tests__/utils/testUtils.ts +0 -76
  8. package/backend/src/adapters/EntityFileAdapter.ts +0 -154
  9. package/backend/src/adapters/YamlFileInfoEnricher.ts +0 -52
  10. package/backend/src/controllers/authController.ts +0 -131
  11. package/backend/src/controllers/diagramController.ts +0 -143
  12. package/backend/src/controllers/dictionaryController.ts +0 -306
  13. package/backend/src/controllers/importExportController.ts +0 -64
  14. package/backend/src/controllers/perspectiveController.ts +0 -90
  15. package/backend/src/controllers/serviceController.ts +0 -418
  16. package/backend/src/controllers/stereotypeController.ts +0 -59
  17. package/backend/src/controllers/versionController.ts +0 -226
  18. package/backend/src/kernel/config.ts +0 -43
  19. package/backend/src/middleware/auth.ts +0 -128
  20. package/backend/src/middleware/jwtAuth.ts +0 -100
  21. package/backend/src/models/Dictionary.ts +0 -38
  22. package/backend/src/models/EntitySchema.ts +0 -393
  23. package/backend/src/models/__tests__/Dictionary.test.ts +0 -92
  24. package/backend/src/models/__tests__/EntitySchema.test.ts +0 -119
  25. package/backend/src/routes/index.ts +0 -120
  26. package/backend/src/scripts/migrate-to-uuid.ts +0 -24
  27. package/backend/src/server.ts +0 -158
  28. package/backend/src/services/__mocks__/entityService.ts +0 -38
  29. package/backend/src/services/__mocks__/serviceService.ts +0 -88
  30. package/backend/src/services/__mocks__/versionService.ts +0 -38
  31. package/backend/src/services/__tests__/dictionaryService.test.ts +0 -74
  32. package/backend/src/services/diagramService.ts +0 -165
  33. package/backend/src/services/dictionaryService.ts +0 -582
  34. package/backend/src/services/entityService.ts +0 -102
  35. package/backend/src/services/exportService.ts +0 -172
  36. package/backend/src/services/importService.ts +0 -208
  37. package/backend/src/services/perspectiveService.ts +0 -276
  38. package/backend/src/services/qualityService.ts +0 -121
  39. package/backend/src/services/serviceService.ts +0 -763
  40. package/backend/src/services/stereotypeService.ts +0 -98
  41. package/backend/src/services/versionService.ts +0 -135
  42. package/backend/src/setupTests.ts +0 -12
  43. package/backend/src/utils/__mocks__/fileOperations.ts +0 -116
  44. package/backend/src/utils/fileOperations.ts +0 -602
  45. package/backend/src/utils/logger.ts +0 -38
  46. package/backend/src/utils/migration.ts +0 -254
  47. package/backend/src/utils/swagger.ts +0 -358
  48. package/backend/src/utils/uuid.ts +0 -41
  49. package/backend/tsconfig.json +0 -20
@@ -1,120 +0,0 @@
1
- import { Router } from 'express';
2
-
3
- import { getCurrentUser, login } from '../controllers/authController.js';
4
- import { diagramController } from '../controllers/diagramController.js';
5
- import { createDictionary, getDictionaries, getDictionaryById, getDictionaryEntries, getEntityAttributes, getPackageByPath, getPackageHierarchy, getRelatedEntities, getTabularData, saveEntity, listAllPackagesAndEntities, getFlatEntitiesAndAttributes, getEntityHierarchy, createRootPackage, createPackageAtPath, updatePackageAtPath, deletePackageAtPath } from '../controllers/dictionaryController.js';
6
- import { createEntity, deleteEntity, getAllServices, getEntitySchema, getGraphData, getServiceEntities, searchEntities, updateEntity, getPackageRelationships, createRelationship, updateRelationship, deleteRelationship, getImpactAnalysis, getLineage, submitEntity, approveEntity, returnEntity, getEntityComments, addEntityComment, resolveEntityComment } from '../controllers/serviceController.js';
7
- import { getAllStereotypes, getStereotype, createStereotype, updateStereotype, deleteStereotype } from '../controllers/stereotypeController.js';
8
- import { getAllPerspectives, getPerspective, createPerspective, updatePerspective, deletePerspective, resolvePerspective, getPerspectiveGraph, upsertPerspectiveNode } from '../controllers/perspectiveController.js';
9
- import { commitChanges, getCommitHistory, revertToCommit } from '../controllers/versionController.js';
10
- import { importJsonSchema, importSqlDdl, exportJsonSchema, exportMarkdown, getQualityReport } from '../controllers/importExportController.js';
11
- import { authenticate, UserRole } from '../middleware/auth.js';
12
- import { authorizeJwt, verifyToken } from '../middleware/jwtAuth.js';
13
-
14
- const router = Router();
15
-
16
- // API status route
17
- router.get('/api/status', (req, res) => {
18
- res.json({ status: 'operational' });
19
- });
20
-
21
- router.get('/api/packages/hierarchy/:rootPackage', getPackageHierarchy);
22
- router.get('/api/packages/tabular/:rootPackage', getTabularData);
23
-
24
- // Package CRUD routes
25
- router.post('/api/packages', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), createRootPackage);
26
- router.post('/api/packages/:rootPackage/subpackages/*', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), createPackageAtPath);
27
- router.put('/api/packages/:rootPackage/path/*', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), updatePackageAtPath);
28
- router.delete('/api/packages/:rootPackage/path/*', authorizeJwt([UserRole.ADMIN]), deletePackageAtPath);
29
-
30
- router.get('/api/packages/:rootPackage/path/*', getPackageByPath);
31
-
32
- // Auth routes
33
- router.post('/api/auth/login', login);
34
- router.get('/api/auth/me', verifyToken, getCurrentUser);
35
-
36
- // Legacy Dictionary routes
37
- router.get('/api/dictionaries', getDictionaries);
38
- router.post('/api/dictionaries', createDictionary);
39
- router.get('/api/dictionaries/:id', getDictionaryById);
40
- router.get('/api/dictionaries/:id/entries', getDictionaryEntries);
41
- router.get('/api/entities/:microservice/:entityName/attributes', getEntityAttributes);
42
- router.get('/api/entities/:microservice/:entityName/related', getRelatedEntities);
43
- router.post('/api/entities', saveEntity);
44
-
45
- // Data Dictionary/Entity/Package API extensions
46
- router.get('/api/packages/all', listAllPackagesAndEntities);
47
- router.get('/api/entities/flat', getFlatEntitiesAndAttributes);
48
- router.get('/api/entities/hierarchy/:microservice/:entityName', getEntityHierarchy);
49
-
50
- // New Service/Entity API routes
51
- router.get('/api/services', getAllServices);
52
- router.get('/api/services/:service/entities', getServiceEntities);
53
- router.get('/api/services/:service/entities/:entity', getEntitySchema);
54
- router.post('/api/services/:service/entities', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), createEntity);
55
- router.put('/api/services/:service/entities/:entity', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), updateEntity);
56
- router.delete('/api/services/:service/entities/:entity', authorizeJwt([UserRole.ADMIN]), deleteEntity);
57
-
58
- // Entity review workflow
59
- router.post('/api/services/:service/entities/:entity/submit', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), submitEntity);
60
- router.post('/api/services/:service/entities/:entity/approve', authorizeJwt([UserRole.ADMIN]), approveEntity);
61
- router.post('/api/services/:service/entities/:entity/return', authorizeJwt([UserRole.ADMIN]), returnEntity);
62
- router.get('/api/services/:service/entities/:entity/comments', getEntityComments);
63
- router.post('/api/services/:service/entities/:entity/comments', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), addEntityComment);
64
- router.put('/api/services/:service/entities/:entity/comments/:id', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), resolveEntityComment);
65
-
66
- // Package-level relationship CRUD routes
67
- router.get('/api/packages/:packageName/relationships', getPackageRelationships);
68
- router.post('/api/packages/:packageName/relationships', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), createRelationship);
69
- router.put('/api/packages/:packageName/relationships/:uuid', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), updateRelationship);
70
- router.delete('/api/packages/:packageName/relationships/:uuid', authorizeJwt([UserRole.ADMIN]), deleteRelationship);
71
-
72
- // Stereotype API
73
- router.get('/api/stereotypes', getAllStereotypes);
74
- router.get('/api/stereotypes/:id', getStereotype);
75
- router.post('/api/stereotypes', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), createStereotype);
76
- router.put('/api/stereotypes/:id', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), updateStereotype);
77
- router.delete('/api/stereotypes/:id', authorizeJwt([UserRole.ADMIN]), deleteStereotype);
78
-
79
- // Perspective API
80
- router.get('/api/perspectives', getAllPerspectives);
81
- router.get('/api/perspectives/:id', getPerspective);
82
- router.post('/api/perspectives', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), createPerspective);
83
- router.put('/api/perspectives/:id', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), updatePerspective);
84
- router.delete('/api/perspectives/:id', authorizeJwt([UserRole.ADMIN]), deletePerspective);
85
- router.get('/api/perspectives/:id/resolve', resolvePerspective);
86
- router.get('/api/perspectives/:id/graph', getPerspectiveGraph);
87
- router.put('/api/perspectives/:id/nodes', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), upsertPerspectiveNode);
88
-
89
- // Search API
90
- router.get('/api/search', searchEntities);
91
-
92
- // Impact analysis & lineage
93
- router.get('/api/entities/:uuid/impact', getImpactAnalysis);
94
- router.get('/api/entities/:uuid/lineage', getLineage);
95
-
96
- // Import/Export
97
- router.post('/api/import/json-schema', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), importJsonSchema);
98
- router.post('/api/import/sql-ddl', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), importSqlDdl);
99
- router.get('/api/export/json-schema/:service', exportJsonSchema);
100
- router.get('/api/export/markdown/:service', exportMarkdown);
101
-
102
- // Quality
103
- router.get('/api/quality/report', getQualityReport);
104
-
105
- // Graph API for visualization
106
- router.get('/api/graph/:service', getGraphData);
107
-
108
- // Version control API
109
- router.post('/api/commit', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), commitChanges);
110
- router.get('/api/history', getCommitHistory);
111
- router.post('/api/revert', authorizeJwt([UserRole.ADMIN]), revertToCommit);
112
-
113
- // Diagram layout API
114
- router.get('/api/diagrams', diagramController.listDiagramLayouts.bind(diagramController));
115
- router.post('/api/diagrams', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), diagramController.saveDiagramLayout.bind(diagramController));
116
- router.get('/api/diagrams/:id', diagramController.loadDiagramLayout.bind(diagramController));
117
- router.put('/api/diagrams/:id', authorizeJwt([UserRole.ADMIN, UserRole.EDITOR]), diagramController.updateDiagramLayout.bind(diagramController));
118
- router.delete('/api/diagrams/:id', authorizeJwt([UserRole.ADMIN]), diagramController.deleteDiagramLayout.bind(diagramController));
119
-
120
- export default router;
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env ts-node
2
-
3
- import { runAllMigrations } from '../utils/migration.js';
4
- import { logger } from '../utils/logger.js';
5
-
6
- /**
7
- * Migration script to convert existing entities to UUID format
8
- */
9
- async function main() {
10
- try {
11
- logger.info('Starting migration to UUID format...');
12
- await runAllMigrations();
13
- logger.info('Migration completed successfully!');
14
- process.exit(0);
15
- } catch (error) {
16
- logger.error('Migration failed:', error);
17
- process.exit(1);
18
- }
19
- }
20
-
21
- // Run the migration if this script is executed directly
22
- if (require.main === module) {
23
- main();
24
- }
@@ -1,158 +0,0 @@
1
- import express, { Request, Response } from 'express';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import cors from 'cors';
5
- import dotenv from 'dotenv';
6
- import routes from './routes/index.js';
7
- import { setupSwagger } from './utils/swagger.js';
8
- import { logger } from './utils/logger.js';
9
- import { config } from './kernel/config.js';
10
- import { initializeFileSystem, getFileRouter } from './adapters/EntityFileAdapter.js';
11
- import { createYamlFileInfoEnricher } from './adapters/YamlFileInfoEnricher.js';
12
-
13
- // Load environment variables
14
- dotenv.config();
15
-
16
- // Initialize Express app
17
- const app = express();
18
- const port = config.port;
19
-
20
- // Middleware
21
- app.use(cors());
22
- // Access logging middleware
23
- app.use((req: Request, res: Response, next) => {
24
- const start = process.hrtime();
25
- res.on('finish', () => {
26
- const diff = process.hrtime(start);
27
- const executionTimeMs = Number((diff[0] * 1e3 + diff[1] / 1e6).toFixed(2));
28
- logger.info('HTTP Access', {
29
- method: req.method,
30
- path: req.originalUrl,
31
- status: res.statusCode,
32
- executionTimeMs
33
- });
34
- });
35
- next();
36
- });
37
-
38
- app.use(express.json());
39
-
40
- // API welcome route (only in dev — production serves frontend at /)
41
- if (!config.isProduction) {
42
- app.get('/', (req: Request, res: Response) => {
43
- res.json({ message: 'Welcome to the Data Dictionary Management System API' });
44
- });
45
- }
46
-
47
- // Health check endpoint
48
- app.get('/health', (req: Request, res: Response) => {
49
- res.json({ status: 'ok' });
50
- });
51
-
52
- // API routes
53
- app.use(routes);
54
-
55
- // Setup Swagger documentation
56
- setupSwagger(app);
57
-
58
- // =============================================================================
59
- // Framework Filesystem & Git Routes (Phase 1)
60
- // =============================================================================
61
-
62
- async function mountFrameworkRoutes() {
63
- try {
64
- // Initialize filesystem framework
65
- const { enricherRegistry } = await initializeFileSystem();
66
-
67
- // Register YAML entity enricher
68
- const yamlEnricher = createYamlFileInfoEnricher();
69
- enricherRegistry.register(yamlEnricher);
70
-
71
- // Initialize git service and routes
72
- try {
73
- const gitModule = await import('@hamak/ui-remote-git-fs-backend');
74
- const workspaceRoots = new Map<string, string>([
75
- ['dictionaries', config.dataDir],
76
- ]);
77
-
78
- const gitService = gitModule.createGitService(workspaceRoots);
79
- const gitEnricher = gitModule.createGitFileInfoEnricher({
80
- gitService,
81
- workspaceRoots,
82
- });
83
- enricherRegistry.register(gitEnricher);
84
-
85
- const gitRoutes = gitModule.createGitRoutes({ gitService, debug: !config.isProduction });
86
- app.use('/api/git', gitRoutes as any);
87
- app.use('/api/git', gitModule.gitErrorHandler as any);
88
-
89
- logger.info('Git routes mounted at /api/git');
90
- } catch (gitError) {
91
- logger.warn(`Git integration not available: ${gitError}`);
92
- }
93
-
94
- // Mount filesystem routes
95
- const fsRouter = getFileRouter();
96
- app.use('/fs', fsRouter);
97
-
98
- logger.info('Filesystem routes mounted at /fs');
99
- } catch (error) {
100
- logger.warn(`Framework filesystem not initialized: ${error}`);
101
- }
102
- }
103
-
104
- // Mount framework routes (non-blocking — existing routes work regardless)
105
- mountFrameworkRoutes().catch((err) => {
106
- logger.warn(`Failed to mount framework routes: ${err}`);
107
- });
108
-
109
-
110
- // Serve frontend static files in production (BEFORE error handler)
111
- if (config.isProduction) {
112
- // Check multiple possible frontend dist locations
113
- const candidates = [
114
- path.join(process.cwd(), 'public'), // Docker (copied to public/)
115
- path.join(process.cwd(), '..', 'frontend', 'dist'), // npm package / monorepo
116
- path.join(process.cwd(), 'frontend', 'dist'), // alt layout
117
- ];
118
- const publicDir = candidates.find(d => {
119
- try { return fs.statSync(d).isDirectory(); } catch { return false; }
120
- });
121
-
122
- if (publicDir) {
123
- app.use(express.static(publicDir));
124
- // SPA fallback — only for navigation requests, not assets/API
125
- app.get('*', (req, res, next) => {
126
- if (req.path.startsWith('/api') || req.path.startsWith('/fs') || req.path.startsWith('/api-docs') || req.path.includes('.')) {
127
- return next();
128
- }
129
- res.sendFile(path.join(publicDir, 'index.html'));
130
- });
131
- logger.info(`Serving frontend from ${publicDir}`);
132
- } else {
133
- logger.warn('Frontend dist not found. API-only mode.');
134
- }
135
- }
136
-
137
- // Error handling middleware (after static files)
138
- app.use((err: any, req: Request, res: Response, _next: any) => {
139
- logger.error(`Unhandled error: ${err.message}`);
140
- res.status(500).json({
141
- message: 'Internal server error',
142
- error: config.isProduction ? undefined : err.message
143
- });
144
- });
145
-
146
- // Start server only when run directly (not when imported by tests)
147
- const isMainModule = process.argv[1] && (
148
- process.argv[1].endsWith('server.ts') || process.argv[1].endsWith('server.js')
149
- );
150
-
151
- if (isMainModule) {
152
- app.listen(port, () => {
153
- logger.info(`Server running on port ${port}`);
154
- logger.info(`API documentation available at http://localhost:${port}/api-docs`);
155
- });
156
- }
157
-
158
- export default app;
@@ -1,38 +0,0 @@
1
- import { Entity, AttributeType } from '../../models/EntitySchema.js';
2
-
3
- const mockEntities: Record<string, Entity> = {
4
- 'user-service.User': {
5
- uuid: 'a38d1597-cc4f-4934-bb08-c876c023f693',
6
- name: 'User',
7
- description: 'User entity',
8
- attributes: [
9
- { uuid: 'b49e2608-dd5f-4045-aa09-d464c234e694', name: 'id', description: 'User ID', type: AttributeType.STRING, required: true, primaryKey: true },
10
- { uuid: 'c5af3719-ee6f-4156-bb1a-e575d345f7a5', name: 'email', description: 'User email', type: AttributeType.STRING, required: true },
11
- ],
12
- } as Entity,
13
- };
14
-
15
- // Mock entity service matching actual EntityService API
16
- class EntityServiceMock {
17
- validateEntity(entity: Entity) {
18
- return { valid: true, errors: [] as string[] };
19
- }
20
-
21
- async validateRelationships(packageName: string, relationships: any[]) {
22
- return { valid: true, errors: [] as string[] };
23
- }
24
-
25
- async saveEntity(entity: Entity, packageName: string) {
26
- return { success: true, errors: [] as string[] };
27
- }
28
-
29
- async getEntity(packageName: string, entityName: string): Promise<Entity | null> {
30
- return mockEntities[`${packageName}.${entityName}`] || null;
31
- }
32
-
33
- async getRelatedEntities(packageName: string, entityName: string): Promise<Entity[]> {
34
- return [];
35
- }
36
- }
37
-
38
- export const entityService = new EntityServiceMock();
@@ -1,88 +0,0 @@
1
- import { AttributeType } from '../../models/EntitySchema.js';
2
-
3
- // Mock service service matching actual ServiceService API
4
- class ServiceServiceMock {
5
- async getAllServices(): Promise<string[]> {
6
- return ['user-service', 'product-service', 'order-service'];
7
- }
8
-
9
- async getServiceEntities(service: string) {
10
- const serviceEntities: Record<string, any[]> = {
11
- 'user-service': [
12
- {
13
- uuid: 'a38d1597-cc4f-4934-bb08-c876c023f693',
14
- name: 'User', description: 'User entity',
15
- attributes: [
16
- { uuid: 'b49e2608-dd5f-4045-aa09-d464c234e694', name: 'id', description: 'User ID', type: AttributeType.STRING, required: true, primaryKey: true },
17
- { uuid: 'c5af3719-ee6f-4156-bb1a-e575d345f7a5', name: 'email', description: 'User email', type: AttributeType.STRING, required: true },
18
- ],
19
- },
20
- ],
21
- 'product-service': [],
22
- 'order-service': [],
23
- };
24
- return serviceEntities[service] || [];
25
- }
26
-
27
- async getEntitySchema(service: string, entity: string) {
28
- if (service === 'user-service' && entity === 'User') {
29
- return {
30
- uuid: 'a38d1597-cc4f-4934-bb08-c876c023f693',
31
- name: 'User', description: 'User entity',
32
- attributes: [
33
- { uuid: 'b49e2608-dd5f-4045-aa09-d464c234e694', name: 'id', description: 'User ID', type: AttributeType.STRING, required: true, primaryKey: true },
34
- { uuid: 'c5af3719-ee6f-4156-bb1a-e575d345f7a5', name: 'email', description: 'User email', type: AttributeType.STRING, required: true },
35
- ],
36
- };
37
- }
38
- return null;
39
- }
40
-
41
- async createEntity(service: string, entity: any) {
42
- return { success: true, errors: [] };
43
- }
44
-
45
- async updateEntity(service: string, entity: any) {
46
- return { success: true, errors: [] };
47
- }
48
-
49
- async deleteEntity(service: string, entityName: string) {
50
- return { success: true, errors: [] };
51
- }
52
-
53
- async searchEntities(query: string) {
54
- return [
55
- { entity: 'User', service: 'user-service', matches: ['name', 'description'] },
56
- ];
57
- }
58
-
59
- async getGraphData(service: string) {
60
- return {
61
- nodes: [
62
- { id: 'User', label: 'User', type: 'entity' },
63
- { id: 'Profile', label: 'Profile', type: 'entity' },
64
- ],
65
- edges: [
66
- { source: 'User', target: 'Profile', label: 'hasOne' },
67
- ],
68
- };
69
- }
70
-
71
- async getPackageRelationships(packageName: string) {
72
- return [];
73
- }
74
-
75
- async createRelationship(packageName: string, relationship: any) {
76
- return { success: true, errors: [], relationship };
77
- }
78
-
79
- async updateRelationship(packageName: string, uuid: string, relationship: any) {
80
- return { success: true, errors: [] };
81
- }
82
-
83
- async deleteRelationship(packageName: string, uuid: string) {
84
- return { success: true, errors: [] };
85
- }
86
- }
87
-
88
- export const serviceService = new ServiceServiceMock();
@@ -1,38 +0,0 @@
1
- // Mock version service matching actual VersionService API
2
- class VersionServiceMock {
3
- async commitChanges(message: string) {
4
- return {
5
- success: true,
6
- errors: [] as string[],
7
- commitHash: 'mock-commit-hash-abc123',
8
- timestamp: new Date('2026-01-01T12:00:00Z'),
9
- };
10
- }
11
-
12
- async getCommitHistory(limit: number = 10) {
13
- return [
14
- {
15
- hash: 'mock-commit-1',
16
- message: 'Initial commit',
17
- author: 'Test User',
18
- date: '2023-01-01T12:00:00Z',
19
- },
20
- {
21
- hash: 'mock-commit-2',
22
- message: 'Update User entity',
23
- author: 'Test User',
24
- date: '2023-01-02T12:00:00Z',
25
- },
26
- ];
27
- }
28
-
29
- async revertToCommit(commitHash: string) {
30
- return {
31
- success: true,
32
- errors: [] as string[],
33
- newCommitHash: 'mock-revert-hash-def456',
34
- };
35
- }
36
- }
37
-
38
- export const versionService = new VersionServiceMock();
@@ -1,74 +0,0 @@
1
- import { listMicroserviceEntities, listAllDictionaries, readEntityFile } from '../../utils/fileOperations.js';
2
- import { dictionaryService } from '../dictionaryService.js';
3
-
4
- // Mock dependencies
5
- jest.mock('../../utils/fileOperations');
6
- jest.mock('../../utils/logger');
7
-
8
- describe('DictionaryService', () => {
9
- beforeEach(() => {
10
- jest.clearAllMocks();
11
- });
12
-
13
- describe('getAllDictionaries', () => {
14
- it('should return all dictionaries', async () => {
15
- (listAllDictionaries as jest.Mock).mockResolvedValue(['microservices/svc-a', 'microservices/svc-b']);
16
-
17
- const dictionaries = await dictionaryService.getAllDictionaries();
18
-
19
- expect(listAllDictionaries).toHaveBeenCalledTimes(1);
20
- // getDictionaryById creates dictionaries from microservices/ IDs
21
- expect(dictionaries).toHaveLength(2);
22
- });
23
-
24
- it('should return empty array on error', async () => {
25
- (listAllDictionaries as jest.Mock).mockRejectedValueOnce(new Error('Test error'));
26
-
27
- const dictionaries = await dictionaryService.getAllDictionaries();
28
-
29
- expect(listAllDictionaries).toHaveBeenCalledTimes(1);
30
- expect(dictionaries).toHaveLength(0);
31
- });
32
- });
33
-
34
- describe('getEntityAttributes', () => {
35
- it('should return attributes for an entity', async () => {
36
- (readEntityFile as jest.Mock).mockResolvedValue({
37
- id: 'User',
38
- uuid: 'a38d1597-cc4f-4934-bb08-c876c023f693',
39
- name: 'User',
40
- microservice: 'user-service',
41
- version: '1.0.0',
42
- attributes: [
43
- { uuid: 'b49e2608-dd5f-4045-aa09-d464c234e694', name: 'id', type: 'string', description: 'ID', required: true },
44
- { uuid: 'c5af3719-ee6f-4156-bb1a-e575d345f7a5', name: 'email', type: 'string', description: 'Email', required: true },
45
- ],
46
- });
47
-
48
- const attributes = await dictionaryService.getEntityAttributes('user-service', 'User');
49
-
50
- expect(readEntityFile).toHaveBeenCalledWith('user-service', 'User');
51
- expect(attributes).toHaveLength(2);
52
- expect(attributes[0].name).toBe('id');
53
- expect(attributes[1].name).toBe('email');
54
- });
55
-
56
- it('should return empty array for non-existent entity', async () => {
57
- (readEntityFile as jest.Mock).mockResolvedValue(null);
58
-
59
- const attributes = await dictionaryService.getEntityAttributes('user-service', 'NonExistent');
60
-
61
- expect(readEntityFile).toHaveBeenCalledWith('user-service', 'NonExistent');
62
- expect(attributes).toHaveLength(0);
63
- });
64
-
65
- it('should return empty array on error', async () => {
66
- (readEntityFile as jest.Mock).mockRejectedValueOnce(new Error('Test error'));
67
-
68
- const attributes = await dictionaryService.getEntityAttributes('user-service', 'User');
69
-
70
- expect(readEntityFile).toHaveBeenCalledWith('user-service', 'User');
71
- expect(attributes).toHaveLength(0);
72
- });
73
- });
74
- });