@hamak/smart-data-dico 1.0.3 → 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 (52) hide show
  1. package/backend/dist/server.mjs +82212 -0
  2. package/bin/cli.js +28 -17
  3. package/frontend/dist/assets/index-1b53cffe.js +431 -0
  4. package/frontend/dist/assets/index-fa72a51a.css +1 -0
  5. package/frontend/dist/index.html +15 -0
  6. package/package.json +28 -27
  7. package/backend/package.json +0 -51
  8. package/backend/src/__tests__/integration/api.test.ts +0 -149
  9. package/backend/src/__tests__/setup.ts +0 -24
  10. package/backend/src/__tests__/utils/testUtils.ts +0 -76
  11. package/backend/src/adapters/EntityFileAdapter.ts +0 -154
  12. package/backend/src/adapters/YamlFileInfoEnricher.ts +0 -52
  13. package/backend/src/controllers/authController.ts +0 -131
  14. package/backend/src/controllers/diagramController.ts +0 -143
  15. package/backend/src/controllers/dictionaryController.ts +0 -306
  16. package/backend/src/controllers/importExportController.ts +0 -64
  17. package/backend/src/controllers/perspectiveController.ts +0 -90
  18. package/backend/src/controllers/serviceController.ts +0 -418
  19. package/backend/src/controllers/stereotypeController.ts +0 -59
  20. package/backend/src/controllers/versionController.ts +0 -226
  21. package/backend/src/kernel/config.ts +0 -43
  22. package/backend/src/middleware/auth.ts +0 -128
  23. package/backend/src/middleware/jwtAuth.ts +0 -100
  24. package/backend/src/models/Dictionary.ts +0 -38
  25. package/backend/src/models/EntitySchema.ts +0 -393
  26. package/backend/src/models/__tests__/Dictionary.test.ts +0 -92
  27. package/backend/src/models/__tests__/EntitySchema.test.ts +0 -119
  28. package/backend/src/routes/index.ts +0 -120
  29. package/backend/src/scripts/migrate-to-uuid.ts +0 -24
  30. package/backend/src/server.ts +0 -158
  31. package/backend/src/services/__mocks__/entityService.ts +0 -38
  32. package/backend/src/services/__mocks__/serviceService.ts +0 -88
  33. package/backend/src/services/__mocks__/versionService.ts +0 -38
  34. package/backend/src/services/__tests__/dictionaryService.test.ts +0 -74
  35. package/backend/src/services/diagramService.ts +0 -165
  36. package/backend/src/services/dictionaryService.ts +0 -582
  37. package/backend/src/services/entityService.ts +0 -102
  38. package/backend/src/services/exportService.ts +0 -172
  39. package/backend/src/services/importService.ts +0 -208
  40. package/backend/src/services/perspectiveService.ts +0 -276
  41. package/backend/src/services/qualityService.ts +0 -121
  42. package/backend/src/services/serviceService.ts +0 -763
  43. package/backend/src/services/stereotypeService.ts +0 -98
  44. package/backend/src/services/versionService.ts +0 -135
  45. package/backend/src/setupTests.ts +0 -12
  46. package/backend/src/utils/__mocks__/fileOperations.ts +0 -116
  47. package/backend/src/utils/fileOperations.ts +0 -602
  48. package/backend/src/utils/logger.ts +0 -38
  49. package/backend/src/utils/migration.ts +0 -254
  50. package/backend/src/utils/swagger.ts +0 -358
  51. package/backend/src/utils/uuid.ts +0 -41
  52. package/backend/tsconfig.json +0 -20
@@ -1,154 +0,0 @@
1
- /**
2
- * EntityFileAdapter
3
- *
4
- * Wraps @hamak/filesystem-server-impl's WorkspaceManager to provide
5
- * the same API as current fileOperations.ts functions.
6
- * Uses dynamic imports since the framework packages are ESM-only.
7
- */
8
-
9
- import path from 'path';
10
- import YAML from 'yaml';
11
- import { logger } from '../utils/logger.js';
12
- import { Entity, validateEntity } from '../models/EntitySchema.js';
13
- import { generateEntityFilename } from '../utils/uuid.js';
14
- import { config } from '../kernel/config.js';
15
-
16
- // Lazy-loaded framework modules (ESM)
17
- let WorkspaceManager: any;
18
- let FileRouter: any;
19
- let FileInfoEnricherRegistry: any;
20
-
21
- let workspaceManager: any = null;
22
- let enricherRegistry: any = null;
23
- let fileRouter: any = null;
24
-
25
- /**
26
- * Initialize the framework filesystem components.
27
- * Must be called once at startup (async because of ESM dynamic imports).
28
- */
29
- export async function initializeFileSystem(): Promise<{
30
- workspaceManager: any;
31
- fileRouter: any;
32
- enricherRegistry: any;
33
- }> {
34
- if (workspaceManager) {
35
- return { workspaceManager, fileRouter, enricherRegistry };
36
- }
37
-
38
- const fsModule = await import('@hamak/filesystem-server-impl');
39
- WorkspaceManager = fsModule.WorkspaceManager;
40
- FileRouter = fsModule.FileRouter;
41
- FileInfoEnricherRegistry = fsModule.FileInfoEnricherRegistry;
42
-
43
- const baseDirectory = config.dataDir;
44
-
45
- const workspacesConfig: Record<string, string> = {
46
- dictionaries: '.',
47
- };
48
-
49
- workspaceManager = new WorkspaceManager(workspacesConfig, { baseDirectory });
50
- enricherRegistry = new FileInfoEnricherRegistry();
51
- fileRouter = new FileRouter(workspaceManager, { enricherRegistry });
52
-
53
- logger.info('Framework filesystem initialized', { baseDirectory });
54
-
55
- return { workspaceManager, fileRouter, enricherRegistry };
56
- }
57
-
58
- /**
59
- * Get the Express router for the /fs endpoint.
60
- */
61
- export function getFileRouter(): any {
62
- if (!fileRouter) {
63
- throw new Error('FileRouter not initialized. Call initializeFileSystem() first.');
64
- }
65
- return fileRouter.router;
66
- }
67
-
68
- /**
69
- * Get the enricher registry for registering file info enrichers.
70
- */
71
- export function getEnricherRegistry(): any {
72
- if (!enricherRegistry) {
73
- throw new Error('EnricherRegistry not initialized. Call initializeFileSystem() first.');
74
- }
75
- return enricherRegistry;
76
- }
77
-
78
- /**
79
- * Get the workspace manager instance.
80
- */
81
- export function getWorkspaceManager(): any {
82
- if (!workspaceManager) {
83
- throw new Error('WorkspaceManager not initialized. Call initializeFileSystem() first.');
84
- }
85
- return workspaceManager;
86
- }
87
-
88
- /**
89
- * Read an entity file using WorkspaceManager.
90
- */
91
- export async function readEntityViaAdapter(
92
- packageName: string,
93
- entityName: string
94
- ): Promise<Entity | null> {
95
- if (!workspaceManager) {
96
- return null;
97
- }
98
-
99
- try {
100
- const dirPath = `microservices/${packageName}`;
101
- const files = await workspaceManager.listFiles('dictionaries', dirPath);
102
-
103
- for (const file of files) {
104
- if (!file.name.endsWith('.yaml') && !file.name.endsWith('.yml')) {
105
- continue;
106
- }
107
- if (file.name === 'metadata.yaml' || file.name === 'relationships.yaml') {
108
- continue;
109
- }
110
-
111
- const filePath = `${dirPath}/${file.name}`;
112
- const content = await workspaceManager.readFile('dictionaries', filePath);
113
- const entity = YAML.parse(content) as Entity;
114
-
115
- if (entity.name === entityName) {
116
- return entity;
117
- }
118
- }
119
-
120
- return null;
121
- } catch (error) {
122
- logger.error(`EntityFileAdapter.readEntity error: ${error}`);
123
- return null;
124
- }
125
- }
126
-
127
- /**
128
- * Write an entity file using WorkspaceManager.
129
- */
130
- export async function writeEntityViaAdapter(entity: Entity, packageName: string): Promise<boolean> {
131
- if (!workspaceManager) {
132
- return false;
133
- }
134
-
135
- try {
136
- const validation = validateEntity(entity);
137
- if (!validation.valid) {
138
- logger.error(`Invalid entity: ${validation.errors.join(', ')}`);
139
- return false;
140
- }
141
-
142
- const filename = generateEntityFilename(entity.uuid, entity.name);
143
- const filePath = `microservices/${packageName}/${filename}`;
144
- const yamlContent = YAML.stringify(entity);
145
-
146
- await workspaceManager.writeFile('dictionaries', filePath, yamlContent);
147
- logger.info(`Entity written via adapter: ${filePath}`);
148
-
149
- return true;
150
- } catch (error) {
151
- logger.error(`EntityFileAdapter.writeEntity error: ${error}`);
152
- return false;
153
- }
154
- }
@@ -1,52 +0,0 @@
1
- /**
2
- * YamlFileInfoEnricher
3
- *
4
- * FileInfoEnricher that parses .yaml files and adds entity metadata
5
- * (entity name, uuid) to the file info response.
6
- */
7
-
8
- import YAML from 'yaml';
9
- import { logger } from '../utils/logger.js';
10
-
11
- export interface YamlEnrichedData {
12
- entityName?: string;
13
- entityUuid?: string;
14
- }
15
-
16
- /**
17
- * Creates a YAML file info enricher compatible with
18
- * @hamak/filesystem-server-impl's FileInfoEnricherRegistry.
19
- */
20
- export function createYamlFileInfoEnricher() {
21
- return {
22
- name: 'yaml-entity',
23
- extensionKey: 'entity',
24
-
25
- canEnrich(fileInfo: any): boolean {
26
- const name: string = fileInfo?.name || '';
27
- return name.endsWith('.yaml') || name.endsWith('.yml');
28
- },
29
-
30
- async enrich(fileInfo: any, context: any): Promise<YamlEnrichedData | null> {
31
- try {
32
- const content = context?.content;
33
- if (!content) {
34
- return null;
35
- }
36
-
37
- const parsed = YAML.parse(content);
38
- if (!parsed || typeof parsed !== 'object') {
39
- return null;
40
- }
41
-
42
- return {
43
- entityName: parsed.name,
44
- entityUuid: parsed.uuid,
45
- };
46
- } catch (error) {
47
- logger.debug(`YamlFileInfoEnricher: could not parse ${fileInfo?.name}: ${error}`);
48
- return null;
49
- }
50
- },
51
- };
52
- }
@@ -1,131 +0,0 @@
1
- import { Request, Response } from 'express';
2
- import jwt, { SignOptions } from 'jsonwebtoken';
3
- import { logger } from '../utils/logger.js';
4
- import { User, UserRole } from '../middleware/auth.js';
5
-
6
- // Mock user database - imported from auth middleware
7
- // In a real application, this would be in a separate database module
8
- const users: Record<string, { password: string; user: User }> = {
9
- 'admin': {
10
- password: 'admin123',
11
- user: {
12
- id: '1',
13
- username: 'admin',
14
- role: UserRole.ADMIN
15
- }
16
- },
17
- 'editor': {
18
- password: 'editor123',
19
- user: {
20
- id: '2',
21
- username: 'editor',
22
- role: UserRole.EDITOR
23
- }
24
- },
25
- 'viewer': {
26
- password: 'viewer123',
27
- user: {
28
- id: '3',
29
- username: 'viewer',
30
- role: UserRole.VIEWER
31
- }
32
- }
33
- };
34
-
35
- // JWT secret key - should be in environment variables in production
36
- const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
37
- // Token expiration time (default: 24 hours)
38
- const TOKEN_EXPIRATION = process.env.TOKEN_EXPIRATION || '24h';
39
-
40
- /**
41
- * Login controller
42
- * Validates username and password, generates JWT token
43
- * @param req Express request
44
- * @param res Express response
45
- */
46
- export const login = (req: Request, res: Response) => {
47
- try {
48
- const { username, password } = req.body;
49
-
50
- // Validate request body
51
- if (!username || !password) {
52
- return res.status(400).json({
53
- message: 'Bad request',
54
- error: 'Username and password are required'
55
- });
56
- }
57
-
58
- // Validate credentials
59
- const userRecord = users[username];
60
-
61
- if (!userRecord || userRecord.password !== password) {
62
- logger.info(`Failed login attempt for user: ${username}`);
63
- return res.status(401).json({
64
- message: 'Authentication failed',
65
- error: 'Invalid username or password'
66
- });
67
- }
68
-
69
- // Generate JWT token
70
- const payload = {
71
- id: userRecord.user.id,
72
- username: userRecord.user.username,
73
- role: userRecord.user.role
74
- };
75
- const options: SignOptions = { expiresIn: TOKEN_EXPIRATION as any };
76
- const token = jwt.sign(payload, JWT_SECRET, options);
77
-
78
- logger.info(`User logged in: ${username}`);
79
-
80
- // Return token and user info
81
- return res.status(200).json({
82
- message: 'Authentication successful',
83
- token,
84
- user: {
85
- id: userRecord.user.id,
86
- username: userRecord.user.username,
87
- role: userRecord.user.role
88
- }
89
- });
90
- } catch (error: any) {
91
- logger.error(`Login error: ${error.message}`);
92
- return res.status(500).json({
93
- message: 'Internal server error',
94
- error: process.env.NODE_ENV === 'production' ? undefined : error.message
95
- });
96
- }
97
- };
98
-
99
- /**
100
- * Get current user controller
101
- * Returns user information based on JWT token
102
- * @param req Express request
103
- * @param res Express response
104
- */
105
- export const getCurrentUser = (req: Request, res: Response) => {
106
- try {
107
- // User should be attached to request by JWT middleware
108
- const user = (req as any).user;
109
-
110
- if (!user) {
111
- return res.status(401).json({
112
- message: 'Authentication required',
113
- error: 'User not authenticated'
114
- });
115
- }
116
-
117
- return res.status(200).json({
118
- user: {
119
- id: user.id,
120
- username: user.username,
121
- role: user.role
122
- }
123
- });
124
- } catch (error: any) {
125
- logger.error(`Get current user error: ${error.message}`);
126
- return res.status(500).json({
127
- message: 'Internal server error',
128
- error: process.env.NODE_ENV === 'production' ? undefined : error.message
129
- });
130
- }
131
- };
@@ -1,143 +0,0 @@
1
- import { Request, Response } from 'express';
2
- import { diagramService, DiagramLayout } from '../services/diagramService.js';
3
- import { logger } from '../utils/logger.js';
4
-
5
- export class DiagramController {
6
- async saveDiagramLayout(req: Request, res: Response): Promise<void> {
7
- try {
8
- const layoutData = req.body as Omit<DiagramLayout, 'createdAt' | 'updatedAt'>;
9
-
10
- if (!layoutData.id || !layoutData.name) {
11
- res.status(400).json({
12
- message: 'Missing required fields: id and name are required'
13
- });
14
- return;
15
- }
16
-
17
- const savedLayout = await diagramService.saveDiagramLayout(layoutData);
18
-
19
- res.status(201).json({
20
- message: 'Diagram layout saved successfully',
21
- data: savedLayout
22
- });
23
- } catch (error) {
24
- logger.error('Error in saveDiagramLayout:', error);
25
- res.status(500).json({
26
- message: 'Failed to save diagram layout',
27
- error: error instanceof Error ? error.message : 'Unknown error'
28
- });
29
- }
30
- }
31
-
32
- async loadDiagramLayout(req: Request, res: Response): Promise<void> {
33
- try {
34
- const { id } = req.params;
35
-
36
- if (!id) {
37
- res.status(400).json({
38
- message: 'Diagram layout ID is required'
39
- });
40
- return;
41
- }
42
-
43
- const layout = await diagramService.loadDiagramLayout(id);
44
-
45
- if (!layout) {
46
- res.status(404).json({
47
- message: 'Diagram layout not found'
48
- });
49
- return;
50
- }
51
-
52
- res.json({
53
- message: 'Diagram layout loaded successfully',
54
- data: layout
55
- });
56
- } catch (error) {
57
- logger.error('Error in loadDiagramLayout:', error);
58
- res.status(500).json({
59
- message: 'Failed to load diagram layout',
60
- error: error instanceof Error ? error.message : 'Unknown error'
61
- });
62
- }
63
- }
64
-
65
- async updateDiagramLayout(req: Request, res: Response): Promise<void> {
66
- try {
67
- const { id } = req.params;
68
- const updates = req.body;
69
-
70
- if (!id) {
71
- res.status(400).json({
72
- message: 'Diagram layout ID is required'
73
- });
74
- return;
75
- }
76
-
77
- const updatedLayout = await diagramService.updateDiagramLayout(id, updates);
78
-
79
- res.json({
80
- message: 'Diagram layout updated successfully',
81
- data: updatedLayout
82
- });
83
- } catch (error) {
84
- logger.error('Error in updateDiagramLayout:', error);
85
- if (error instanceof Error && error.message === 'Diagram layout not found') {
86
- res.status(404).json({
87
- message: 'Diagram layout not found'
88
- });
89
- } else {
90
- res.status(500).json({
91
- message: 'Failed to update diagram layout',
92
- error: error instanceof Error ? error.message : 'Unknown error'
93
- });
94
- }
95
- }
96
- }
97
-
98
- async deleteDiagramLayout(req: Request, res: Response): Promise<void> {
99
- try {
100
- const { id } = req.params;
101
-
102
- if (!id) {
103
- res.status(400).json({
104
- message: 'Diagram layout ID is required'
105
- });
106
- return;
107
- }
108
-
109
- await diagramService.deleteDiagramLayout(id);
110
-
111
- res.json({
112
- message: 'Diagram layout deleted successfully'
113
- });
114
- } catch (error) {
115
- logger.error('Error in deleteDiagramLayout:', error);
116
- res.status(500).json({
117
- message: 'Failed to delete diagram layout',
118
- error: error instanceof Error ? error.message : 'Unknown error'
119
- });
120
- }
121
- }
122
-
123
- async listDiagramLayouts(req: Request, res: Response): Promise<void> {
124
- try {
125
- const { service } = req.query;
126
-
127
- const layouts = await diagramService.listDiagramLayouts(service as string);
128
-
129
- res.json({
130
- message: 'Diagram layouts retrieved successfully',
131
- data: layouts
132
- });
133
- } catch (error) {
134
- logger.error('Error in listDiagramLayouts:', error);
135
- res.status(500).json({
136
- message: 'Failed to list diagram layouts',
137
- error: error instanceof Error ? error.message : 'Unknown error'
138
- });
139
- }
140
- }
141
- }
142
-
143
- export const diagramController = new DiagramController();