@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,98 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import * as YAML from 'yaml';
4
- import { Stereotype, StereotypeTarget, MetadataEntry } from '../models/EntitySchema.js';
5
- import { logger } from '../utils/logger.js';
6
- import { config } from '../kernel/config.js';
7
-
8
- const DATA_DICTIONARIES_DIR = config.dataDir;
9
- const STEREOTYPES_FILE = path.join(DATA_DICTIONARIES_DIR, 'stereotypes.yaml');
10
-
11
- class StereotypeService {
12
- private readStereotypes(): Stereotype[] {
13
- if (!fs.existsSync(STEREOTYPES_FILE)) return [];
14
- const content = fs.readFileSync(STEREOTYPES_FILE, 'utf8');
15
- return YAML.parse(content) || [];
16
- }
17
-
18
- private writeStereotypes(stereotypes: Stereotype[]): void {
19
- fs.writeFileSync(STEREOTYPES_FILE, YAML.stringify(stereotypes), 'utf8');
20
- }
21
-
22
- async getAllStereotypes(appliesTo?: StereotypeTarget): Promise<Stereotype[]> {
23
- const all = this.readStereotypes();
24
- if (appliesTo) return all.filter((s) => s.appliesTo === appliesTo);
25
- return all;
26
- }
27
-
28
- async getStereotype(id: string): Promise<Stereotype | null> {
29
- const all = this.readStereotypes();
30
- return all.find((s) => s.id === id) || null;
31
- }
32
-
33
- async createStereotype(data: Stereotype): Promise<{ success: boolean; stereotype?: Stereotype; errors?: string[] }> {
34
- if (!data.id || !data.name || !data.appliesTo) {
35
- return { success: false, errors: ['id, name, and appliesTo are required'] };
36
- }
37
- if (!['package', 'entity', 'attribute'].includes(data.appliesTo)) {
38
- return { success: false, errors: ['appliesTo must be package, entity, or attribute'] };
39
- }
40
-
41
- const all = this.readStereotypes();
42
- if (all.find((s) => s.id === data.id)) {
43
- return { success: false, errors: [`Stereotype with id '${data.id}' already exists`] };
44
- }
45
-
46
- const stereotype: Stereotype = {
47
- id: data.id,
48
- name: data.name,
49
- description: data.description,
50
- appliesTo: data.appliesTo,
51
- metadataDefinitions: data.metadataDefinitions || [],
52
- };
53
-
54
- all.push(stereotype);
55
- this.writeStereotypes(all);
56
- return { success: true, stereotype };
57
- }
58
-
59
- async updateStereotype(id: string, data: Partial<Stereotype>): Promise<{ success: boolean; stereotype?: Stereotype; errors?: string[] }> {
60
- const all = this.readStereotypes();
61
- const index = all.findIndex((s) => s.id === id);
62
- if (index === -1) return { success: false, errors: ['Stereotype not found'] };
63
-
64
- all[index] = {
65
- ...all[index],
66
- name: data.name ?? all[index].name,
67
- description: data.description ?? all[index].description,
68
- appliesTo: data.appliesTo ?? all[index].appliesTo,
69
- metadataDefinitions: data.metadataDefinitions ?? all[index].metadataDefinitions,
70
- };
71
-
72
- this.writeStereotypes(all);
73
- return { success: true, stereotype: all[index] };
74
- }
75
-
76
- async deleteStereotype(id: string): Promise<{ success: boolean; errors?: string[] }> {
77
- const all = this.readStereotypes();
78
- const filtered = all.filter((s) => s.id !== id);
79
- if (filtered.length === all.length) return { success: false, errors: ['Stereotype not found'] };
80
- this.writeStereotypes(filtered);
81
- return { success: true };
82
- }
83
-
84
- validateMetadata(stereotype: Stereotype, metadata: MetadataEntry[] = []): string[] {
85
- const errors: string[] = [];
86
- for (const def of stereotype.metadataDefinitions) {
87
- if (def.required) {
88
- const entry = metadata.find((m) => m.name === def.name);
89
- if (!entry || entry.value === undefined || entry.value === '') {
90
- errors.push(`Required metadata '${def.name}' is missing (stereotype: ${stereotype.name})`);
91
- }
92
- }
93
- }
94
- return errors;
95
- }
96
- }
97
-
98
- export const stereotypeService = new StereotypeService();
@@ -1,135 +0,0 @@
1
- import { logger } from '../utils/logger.js';
2
- import { config } from '../kernel/config.js';
3
-
4
- /**
5
- * Interface for commit information
6
- */
7
- interface CommitInfo {
8
- hash: string;
9
- date: string;
10
- message: string;
11
- author_name: string;
12
- author_email: string;
13
- }
14
-
15
- // Lazy-loaded git service from @hamak/ui-remote-git-fs-backend
16
- let gitServiceInstance: any = null;
17
-
18
- async function getGitService() {
19
- if (gitServiceInstance) return gitServiceInstance;
20
- try {
21
- const gitModule = await import('@hamak/ui-remote-git-fs-backend');
22
- const workspaceRoots = new Map<string, string>([
23
- ['dictionaries', config.dataDir],
24
- ]);
25
- gitServiceInstance = gitModule.createGitService(workspaceRoots);
26
- return gitServiceInstance;
27
- } catch {
28
- logger.warn('Git service not available');
29
- return null;
30
- }
31
- }
32
-
33
- /**
34
- * Service for version control operations using @hamak/ui-remote-git-fs-backend
35
- */
36
- export class VersionService {
37
- /**
38
- * Commit all changes to the repository
39
- */
40
- async commitChanges(message: string): Promise<{
41
- success: boolean;
42
- errors: string[];
43
- commitHash?: string;
44
- timestamp?: Date;
45
- }> {
46
- try {
47
- const gitService = await getGitService();
48
- if (!gitService) {
49
- return { success: false, errors: ['Git service not available'] };
50
- }
51
-
52
- const status = await gitService.status('dictionaries', '.');
53
- if (!status.files || status.files.length === 0) {
54
- return { success: false, errors: ['No changes to commit'] };
55
- }
56
-
57
- const result = await gitService.commit('dictionaries', '.', { message });
58
-
59
- logger.info(`Changes committed: ${result.hash || 'unknown'}`);
60
-
61
- return {
62
- success: true,
63
- errors: [],
64
- commitHash: result.hash,
65
- timestamp: new Date(),
66
- };
67
- } catch (error) {
68
- logger.error(`Error committing changes: ${error}`);
69
- return {
70
- success: false,
71
- errors: [`Error committing changes: ${error}`],
72
- };
73
- }
74
- }
75
-
76
- /**
77
- * Get commit history
78
- */
79
- async getCommitHistory(limit: number = 10): Promise<CommitInfo[]> {
80
- try {
81
- const gitService = await getGitService();
82
- if (!gitService) return [];
83
-
84
- const logResult = await gitService.log('dictionaries', '.', { maxCount: limit });
85
-
86
- if (!logResult || !Array.isArray(logResult)) return [];
87
-
88
- return logResult.map((entry: any) => ({
89
- hash: entry.hash || entry.oid || '',
90
- date: entry.date || entry.timestamp || '',
91
- message: entry.message || '',
92
- author_name: entry.author_name || entry.author?.name || '',
93
- author_email: entry.author_email || entry.author?.email || '',
94
- }));
95
- } catch (error) {
96
- logger.error(`Error getting commit history: ${error}`);
97
- return [];
98
- }
99
- }
100
-
101
- /**
102
- * Revert to a previous commit
103
- */
104
- async revertToCommit(commitHash: string): Promise<{
105
- success: boolean;
106
- errors: string[];
107
- newCommitHash?: string;
108
- }> {
109
- try {
110
- const gitService = await getGitService();
111
- if (!gitService) {
112
- return { success: false, errors: ['Git service not available'] };
113
- }
114
-
115
- const result = await gitService.revert('dictionaries', '.', { commit: commitHash });
116
-
117
- logger.info(`Reverted to commit ${commitHash}`);
118
-
119
- return {
120
- success: true,
121
- errors: [],
122
- newCommitHash: result?.hash,
123
- };
124
- } catch (error) {
125
- logger.error(`Error reverting to commit: ${error}`);
126
- return {
127
- success: false,
128
- errors: [`Error reverting to commit: ${error}`],
129
- };
130
- }
131
- }
132
- }
133
-
134
- // Export a singleton instance
135
- export const versionService = new VersionService();
@@ -1,12 +0,0 @@
1
- // This file is automatically loaded by Jest
2
- // It sets up the testing environment
3
-
4
- // Global setup
5
- beforeAll(() => {
6
- // Any global setup before all tests
7
- });
8
-
9
- // Global teardown
10
- afterAll(() => {
11
- // Any global cleanup after all tests
12
- });
@@ -1,116 +0,0 @@
1
- // Mock implementation of file operations for testing
2
- import { Entity, AttributeType } from '../../models/EntitySchema.js';
3
-
4
- // Mock data
5
- const mockMicroservices = ['user-service', 'product-service', 'order-service'];
6
-
7
- const mockEntities: Record<string, string[]> = {
8
- 'user-service': ['User', 'Profile'],
9
- 'product-service': ['Product'],
10
- 'order-service': ['Order', 'OrderItem']
11
- };
12
-
13
- const mockEntityData: Record<string, Entity> = {
14
- 'user-service.User': {
15
- id: 'User',
16
- name: 'User',
17
- description: 'User entity',
18
- microservice: 'user-service',
19
- version: '1.0.0',
20
- attributes: [
21
- {
22
- name: 'id',
23
- description: 'User ID',
24
- type: AttributeType.STRING,
25
- required: true
26
- },
27
- {
28
- name: 'email',
29
- description: 'User email',
30
- type: AttributeType.STRING,
31
- format: 'email',
32
- required: true
33
- }
34
- ]
35
- },
36
- 'product-service.Product': {
37
- id: 'Product',
38
- name: 'Product',
39
- description: 'Product entity',
40
- microservice: 'product-service',
41
- version: '1.0.0',
42
- attributes: [
43
- {
44
- name: 'id',
45
- description: 'Product ID',
46
- type: AttributeType.STRING,
47
- required: true
48
- },
49
- {
50
- name: 'name',
51
- description: 'Product name',
52
- type: AttributeType.STRING,
53
- required: true
54
- },
55
- {
56
- name: 'price',
57
- description: 'Product price',
58
- type: AttributeType.NUMBER,
59
- required: true
60
- }
61
- ]
62
- }
63
- };
64
-
65
- // Mock functions
66
- export const listMicroservices = jest.fn().mockImplementation(async () => {
67
- return Promise.resolve(mockMicroservices);
68
- });
69
-
70
- export const listMicroserviceEntities = jest.fn().mockImplementation(async (microservice: string) => {
71
- return Promise.resolve(mockEntities[microservice] || []);
72
- });
73
-
74
- export const listAllEntities = jest.fn().mockImplementation(async () => {
75
- const allEntities: { microservice: string; entity: string }[] = [];
76
-
77
- for (const microservice of mockMicroservices) {
78
- for (const entity of mockEntities[microservice] || []) {
79
- allEntities.push({ microservice, entity });
80
- }
81
- }
82
-
83
- return Promise.resolve(allEntities);
84
- });
85
-
86
- export const readEntityFile = jest.fn().mockImplementation(async (microservice: string, entity: string) => {
87
- const key = `${microservice}.${entity}`;
88
- return Promise.resolve(mockEntityData[key] || null);
89
- });
90
-
91
- export const writeEntityFile = jest.fn().mockImplementation(async (entity: Entity) => {
92
- const key = `${entity.microservice}.${entity.id}`;
93
- mockEntityData[key] = entity;
94
- return Promise.resolve(true);
95
- });
96
-
97
- export const deleteEntityFile = jest.fn().mockImplementation(async (microservice: string, entity: string) => {
98
- const key = `${microservice}.${entity}`;
99
- if (mockEntityData[key]) {
100
- delete mockEntityData[key];
101
- return Promise.resolve(true);
102
- }
103
- return Promise.resolve(false);
104
- });
105
-
106
- export const createDirectory = jest.fn().mockImplementation(async (path: string) => {
107
- return Promise.resolve(true);
108
- });
109
-
110
- export const ensureDirectoryStructure = jest.fn().mockResolvedValue(undefined);
111
-
112
- export const listAllDictionaries = jest.fn().mockResolvedValue([]);
113
-
114
- export const writeDictionaryMetadata = jest.fn().mockResolvedValue(undefined);
115
-
116
- export const commitChanges = jest.fn().mockResolvedValue({ success: true });