@hamak/smart-data-dico 1.0.4 → 1.1.1

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 +82213 -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,393 +0,0 @@
1
- import { Validator } from 'jsonschema';
2
- import { generateUUID, isValidUUID } from '../utils/uuid.js';
3
- type Schema = any; // Using any as a workaround for missing type definitions
4
-
5
- /**
6
- * Supported attribute types in the data dictionary
7
- */
8
- export enum AttributeType {
9
- STRING = 'string',
10
- NUMBER = 'number',
11
- INTEGER = 'integer',
12
- BOOLEAN = 'boolean',
13
- DATETIME = 'datetime',
14
- DATE = 'date',
15
- TIME = 'time',
16
- DATE_TIME = 'date-time',
17
- TIMESTAMP = 'timestamp',
18
- DURATION = 'duration',
19
- ENUM = 'enum',
20
- OBJECT = 'object',
21
- ARRAY = 'array'
22
- }
23
-
24
- /**
25
- * Cardinality for relationship ends
26
- */
27
- export enum Cardinality {
28
- ONE = 'one',
29
- MANY = 'many'
30
- }
31
-
32
- /**
33
- * Metadata value types for typed metadata definitions
34
- */
35
- export enum MetadataValueType {
36
- STRING = 'string',
37
- NUMBER = 'number',
38
- BOOLEAN = 'boolean',
39
- DATE = 'date',
40
- FLAG = 'flag',
41
- RULE = 'rule',
42
- }
43
-
44
- export enum RuleSeverity {
45
- INFO = 'info',
46
- WARNING = 'warning',
47
- ERROR = 'error',
48
- }
49
-
50
- /**
51
- * A metadata definition (schema for metadata entries)
52
- */
53
- export interface MetadataDefinition {
54
- name: string;
55
- type: MetadataValueType;
56
- description?: string;
57
- required?: boolean;
58
- }
59
-
60
- /**
61
- * A typed metadata entry
62
- */
63
- export interface MetadataEntry {
64
- name: string;
65
- value: string | number | boolean;
66
- severity?: RuleSeverity;
67
- }
68
-
69
- export enum EntityStatus {
70
- DRAFT = 'draft',
71
- SUBMITTED = 'submitted',
72
- APPROVED = 'approved',
73
- RETURNED = 'returned',
74
- }
75
-
76
- export interface ReviewComment {
77
- id: string;
78
- author: string;
79
- timestamp: string;
80
- message: string;
81
- targetField?: string;
82
- resolved?: boolean;
83
- }
84
-
85
- export type StereotypeTarget = 'package' | 'entity' | 'attribute';
86
-
87
- export interface Stereotype {
88
- id: string;
89
- name: string;
90
- description?: string;
91
- appliesTo: StereotypeTarget;
92
- metadataDefinitions: MetadataDefinition[];
93
- }
94
-
95
- /**
96
- * A node in a perspective — annotates, sets frontier, or excludes a path
97
- */
98
- export interface PerspectiveNode {
99
- path: string;
100
- traverse?: boolean;
101
- exclude?: boolean;
102
- metadata?: MetadataEntry[];
103
- }
104
-
105
- /**
106
- * A perspective is a business view over a subset of the data model
107
- */
108
- export interface Perspective {
109
- uuid: string;
110
- name: string;
111
- description?: string;
112
- rootEntities: string[];
113
- nodes?: PerspectiveNode[];
114
- maxDepth?: number;
115
- metadata?: MetadataEntry[];
116
- createdAt?: string;
117
- updatedAt?: string;
118
- }
119
-
120
- /**
121
- * A resolved node from BFS traversal of a perspective
122
- */
123
- export interface ResolvedNode {
124
- entityUuid: string;
125
- entityName: string;
126
- service: string;
127
- path: string;
128
- hopDistance: number;
129
- isRoot: boolean;
130
- isFrontier: boolean;
131
- isManualInclusion: boolean;
132
- }
133
-
134
- /**
135
- * A perspective with its resolved entity graph
136
- */
137
- export interface ResolvedPerspective extends Perspective {
138
- resolvedNodes: ResolvedNode[];
139
- }
140
-
141
- /**
142
- * Grouped constraint fields for attributes
143
- */
144
- export interface AttributeConstraints {
145
- minLength?: number;
146
- maxLength?: number;
147
- pattern?: string;
148
- format?: string;
149
- minimum?: number;
150
- maximum?: number;
151
- precision?: number;
152
- scale?: number;
153
- enumValues?: string[];
154
- }
155
-
156
- /**
157
- * Interface for entity attribute definition
158
- */
159
- export interface Attribute {
160
- uuid: string;
161
- name: string;
162
- description: string;
163
- type: AttributeType;
164
- required: boolean;
165
- unique?: boolean;
166
- primaryKey?: boolean;
167
- defaultValue?: any;
168
- examples?: any[];
169
- constraints?: AttributeConstraints;
170
-
171
- // For object and array types
172
- items?: Attribute;
173
- properties?: Attribute[];
174
-
175
- // Typed metadata
176
- metadata?: MetadataEntry[];
177
- }
178
-
179
- /**
180
- * One end of a relationship
181
- */
182
- export interface RelationshipEnd {
183
- entity: string; // UUID of the entity
184
- cardinality: Cardinality;
185
- name?: string; // Navigation property name
186
- referenceAttributes?: string[];
187
- }
188
-
189
- /**
190
- * A relationship between two entities, stored at package level
191
- */
192
- export type RelationshipType = 'structural' | 'lineage';
193
-
194
- export interface Relationship {
195
- uuid: string;
196
- description?: string;
197
- type?: RelationshipType;
198
- source: RelationshipEnd;
199
- target: RelationshipEnd;
200
- metadata?: MetadataEntry[];
201
- }
202
-
203
- export interface LineageNode {
204
- entityUuid: string;
205
- entityName: string;
206
- service: string;
207
- direction: 'upstream' | 'downstream';
208
- depth: number;
209
- relationship: { uuid: string; description: string };
210
- }
211
-
212
- export interface LineageResult {
213
- entity: { uuid: string; name: string; service: string };
214
- upstream: LineageNode[];
215
- downstream: LineageNode[];
216
- }
217
-
218
- /**
219
- * Interface for entity definition
220
- */
221
- export interface Entity {
222
- uuid: string;
223
- name: string;
224
- description?: string;
225
- stereotype?: string;
226
- status?: EntityStatus;
227
- attributes: Attribute[];
228
- metadata?: MetadataEntry[];
229
- createdAt?: string;
230
- updatedAt?: string;
231
- }
232
-
233
- // Backward-compatible alias
234
- export type EntityAttribute = Attribute;
235
-
236
- /**
237
- * JSON Schema for validating entity definitions
238
- */
239
- export const entitySchema: Schema = {
240
- type: 'object',
241
- required: ['uuid', 'name', 'attributes'],
242
- properties: {
243
- uuid: { type: 'string', pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' },
244
- name: { type: 'string' },
245
- description: { type: 'string' },
246
- attributes: {
247
- type: 'array',
248
- items: {
249
- type: 'object',
250
- required: ['uuid', 'name', 'description', 'type', 'required'],
251
- properties: {
252
- uuid: { type: 'string', pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' },
253
- name: { type: 'string' },
254
- description: { type: 'string' },
255
- type: {
256
- type: 'string',
257
- enum: Object.values(AttributeType)
258
- },
259
- required: { type: 'boolean' },
260
- unique: { type: 'boolean' },
261
- primaryKey: { type: 'boolean' },
262
- defaultValue: { },
263
- examples: { type: 'array' },
264
- constraints: {
265
- type: 'object',
266
- properties: {
267
- minLength: { type: 'integer', minimum: 0 },
268
- maxLength: { type: 'integer', minimum: 0 },
269
- pattern: { type: 'string' },
270
- format: { type: 'string' },
271
- minimum: { type: 'number' },
272
- maximum: { type: 'number' },
273
- precision: { type: 'integer', minimum: 0 },
274
- scale: { type: 'integer', minimum: 0 },
275
- enumValues: {
276
- type: 'array',
277
- items: { type: 'string' }
278
- }
279
- }
280
- },
281
- items: { type: 'object' },
282
- properties: { type: 'array' },
283
- metadata: { type: 'array' }
284
- }
285
- }
286
- },
287
- metadata: { type: 'array' },
288
- createdAt: { type: 'string', format: 'date-time' },
289
- updatedAt: { type: 'string', format: 'date-time' }
290
- }
291
- };
292
-
293
- /**
294
- * JSON Schema for validating relationship definitions
295
- */
296
- export const relationshipSchema: Schema = {
297
- type: 'object',
298
- required: ['uuid', 'source', 'target'],
299
- properties: {
300
- uuid: { type: 'string', pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' },
301
- description: { type: 'string' },
302
- source: {
303
- type: 'object',
304
- required: ['entity', 'cardinality'],
305
- properties: {
306
- entity: { type: 'string' },
307
- cardinality: { type: 'string', enum: Object.values(Cardinality) },
308
- name: { type: 'string' },
309
- referenceAttributes: { type: 'array', items: { type: 'string' } }
310
- }
311
- },
312
- target: {
313
- type: 'object',
314
- required: ['entity', 'cardinality'],
315
- properties: {
316
- entity: { type: 'string' },
317
- cardinality: { type: 'string', enum: Object.values(Cardinality) },
318
- name: { type: 'string' },
319
- referenceAttributes: { type: 'array', items: { type: 'string' } }
320
- }
321
- },
322
- metadata: { type: 'array' }
323
- }
324
- };
325
-
326
- /**
327
- * Validates an entity definition against the schema
328
- */
329
- export function validateEntity(entity: Entity): { valid: boolean; errors: string[] } {
330
- const validator = new Validator();
331
- const result = validator.validate(entity, entitySchema);
332
-
333
- const errors: string[] = result.errors.map((error: any) => error.stack);
334
-
335
- // Additional UUID validation
336
- if (!isValidUUID(entity.uuid)) {
337
- errors.push('Entity UUID is invalid');
338
- }
339
-
340
- // Validate attribute UUIDs
341
- if (entity.attributes) {
342
- entity.attributes.forEach((attr, index) => {
343
- if (!isValidUUID(attr.uuid)) {
344
- errors.push(`Attribute ${index} UUID is invalid`);
345
- }
346
- });
347
- }
348
-
349
- return {
350
- valid: result.valid && errors.length === 0,
351
- errors
352
- };
353
- }
354
-
355
- /**
356
- * Validates a relationship definition against the schema
357
- */
358
- export function validateRelationship(relationship: Relationship): { valid: boolean; errors: string[] } {
359
- const validator = new Validator();
360
- const result = validator.validate(relationship, relationshipSchema);
361
-
362
- const errors: string[] = result.errors.map((error: any) => error.stack);
363
-
364
- if (!isValidUUID(relationship.uuid)) {
365
- errors.push('Relationship UUID is invalid');
366
- }
367
-
368
- return {
369
- valid: result.valid && errors.length === 0,
370
- errors
371
- };
372
- }
373
-
374
- /**
375
- * Creates a new entity with UUIDs for all components
376
- */
377
- export function createEntityWithUUIDs(entityData: Omit<Entity, 'uuid' | 'attributes'> & {
378
- attributes: Omit<Attribute, 'uuid'>[];
379
- }): Entity {
380
- return {
381
- ...entityData,
382
- uuid: generateUUID(),
383
- attributes: entityData.attributes.map(attr => ({
384
- ...attr,
385
- uuid: generateUUID(),
386
- properties: attr.properties ? attr.properties.map(prop => ({
387
- ...prop,
388
- uuid: prop.uuid || generateUUID()
389
- })) : attr.properties,
390
- items: attr.items ? { ...attr.items, uuid: attr.items.uuid || generateUUID() } : attr.items
391
- }))
392
- };
393
- }
@@ -1,92 +0,0 @@
1
- import { Dictionary, DictionaryEntry } from '../Dictionary.js';
2
-
3
- describe('Dictionary Model', () => {
4
- describe('Dictionary Interface', () => {
5
- it('should create a valid Dictionary object', () => {
6
- const dictionary: Dictionary = {
7
- id: 'test-dict-1',
8
- name: 'Test Dictionary',
9
- description: 'A test dictionary',
10
- version: '1.0.0',
11
- createdAt: new Date(),
12
- updatedAt: new Date(),
13
- rootPackage: { id: 'root', name: 'Root', entities: [], subPackages: [] },
14
- };
15
-
16
- expect(dictionary).toBeDefined();
17
- expect(dictionary.id).toBe('test-dict-1');
18
- expect(dictionary.name).toBe('Test Dictionary');
19
- expect(dictionary.description).toBe('A test dictionary');
20
- expect(dictionary.version).toBe('1.0.0');
21
- expect(dictionary.createdAt).toBeInstanceOf(Date);
22
- expect(dictionary.updatedAt).toBeInstanceOf(Date);
23
- });
24
-
25
- it('should create a Dictionary with only required fields', () => {
26
- const dictionary: Dictionary = {
27
- id: 'test-dict-2',
28
- name: 'Minimal Dictionary',
29
- rootPackage: { id: 'root', name: 'Root', entities: [], subPackages: [] },
30
- };
31
-
32
- expect(dictionary).toBeDefined();
33
- expect(dictionary.id).toBe('test-dict-2');
34
- expect(dictionary.name).toBe('Minimal Dictionary');
35
- expect(dictionary.description).toBeUndefined();
36
- expect(dictionary.version).toBeUndefined();
37
- expect(dictionary.createdAt).toBeUndefined();
38
- expect(dictionary.updatedAt).toBeUndefined();
39
- });
40
- });
41
-
42
- describe('DictionaryEntry Interface', () => {
43
- it('should create a valid DictionaryEntry object', () => {
44
- const entry: DictionaryEntry = {
45
- id: 'entry-1',
46
- name: 'Test Entry',
47
- description: 'A test entry',
48
- type: 'string',
49
- format: 'email',
50
- required: true,
51
- defaultValue: 'test@example.com',
52
- examples: ['user@example.com', 'admin@example.com'],
53
- metadata: {
54
- source: 'user',
55
- lastUpdated: '2023-01-01',
56
- },
57
- };
58
-
59
- expect(entry).toBeDefined();
60
- expect(entry.id).toBe('entry-1');
61
- expect(entry.name).toBe('Test Entry');
62
- expect(entry.description).toBe('A test entry');
63
- expect(entry.type).toBe('string');
64
- expect(entry.format).toBe('email');
65
- expect(entry.required).toBe(true);
66
- expect(entry.defaultValue).toBe('test@example.com');
67
- expect(entry.examples).toHaveLength(2);
68
- expect(entry.examples).toContain('user@example.com');
69
- expect(entry.metadata).toHaveProperty('source', 'user');
70
- });
71
-
72
- it('should create a DictionaryEntry with only required fields', () => {
73
- const entry: DictionaryEntry = {
74
- id: 'entry-2',
75
- name: 'Minimal Entry',
76
- description: 'A minimal entry',
77
- type: 'number',
78
- };
79
-
80
- expect(entry).toBeDefined();
81
- expect(entry.id).toBe('entry-2');
82
- expect(entry.name).toBe('Minimal Entry');
83
- expect(entry.description).toBe('A minimal entry');
84
- expect(entry.type).toBe('number');
85
- expect(entry.format).toBeUndefined();
86
- expect(entry.required).toBeUndefined();
87
- expect(entry.defaultValue).toBeUndefined();
88
- expect(entry.examples).toBeUndefined();
89
- expect(entry.metadata).toBeUndefined();
90
- });
91
- });
92
- });
@@ -1,119 +0,0 @@
1
- import { AttributeType, validateEntity } from '../EntitySchema.js';
2
-
3
- describe('EntitySchema', () => {
4
- describe('validateEntity', () => {
5
- it('should validate a valid entity', () => {
6
- const validEntity = {
7
- uuid: 'a38d1597-cc4f-4934-bb08-c876c023f693',
8
- name: 'Test Entity',
9
- attributes: [
10
- {
11
- uuid: 'b49e2608-dd5f-4045-aa09-d464c234e694',
12
- name: 'id',
13
- description: 'Primary identifier',
14
- type: AttributeType.STRING,
15
- required: true,
16
- primaryKey: true,
17
- },
18
- {
19
- uuid: 'c5af3719-ee6f-4156-bb1a-e575d345f7a5',
20
- name: 'name',
21
- description: 'Entity name',
22
- type: AttributeType.STRING,
23
- required: true,
24
- },
25
- ],
26
- };
27
-
28
- const result = validateEntity(validEntity);
29
- expect(result.valid).toBe(true);
30
- expect(result.errors).toHaveLength(0);
31
- });
32
-
33
- it('should invalidate an entity with missing required fields', () => {
34
- const invalidEntity = {
35
- // Missing uuid
36
- // Missing name
37
- description: 'A test entity',
38
- attributes: [],
39
- };
40
-
41
- const result = validateEntity(invalidEntity as any);
42
- expect(result.valid).toBe(false);
43
- expect(result.errors.length).toBeGreaterThan(0);
44
- });
45
-
46
- it('should validate an entity with constraints', () => {
47
- const entityWithConstraints = {
48
- uuid: 'd6b0482a-ff70-4267-8c2b-f686e456f8b6',
49
- name: 'Test Entity',
50
- description: 'A test entity',
51
- attributes: [
52
- {
53
- uuid: 'e7c1593b-aa81-4378-9d3c-a797f567a9c7',
54
- name: 'email',
55
- description: 'Email address',
56
- type: AttributeType.STRING,
57
- required: true,
58
- constraints: {
59
- maxLength: 255,
60
- pattern: '^[^@]+@[^@]+$',
61
- format: 'email',
62
- },
63
- },
64
- ],
65
- };
66
-
67
- const result = validateEntity(entityWithConstraints);
68
- expect(result.valid).toBe(true);
69
- expect(result.errors).toHaveLength(0);
70
- });
71
-
72
- it('should invalidate an entity with invalid attribute type', () => {
73
- const entityWithInvalidAttribute = {
74
- uuid: 'a38d1597-cc4f-4934-bb08-c876c023f693',
75
- name: 'Test Entity',
76
- description: 'A test entity',
77
- attributes: [
78
- {
79
- uuid: 'b49e2608-dd5f-4045-aa09-d464c234e694',
80
- name: 'id',
81
- description: 'Primary identifier',
82
- type: 'invalid-type', // Invalid type
83
- required: true,
84
- },
85
- ],
86
- };
87
-
88
- const result = validateEntity(entityWithInvalidAttribute as any);
89
- expect(result.valid).toBe(false);
90
- expect(result.errors.length).toBeGreaterThan(0);
91
- });
92
-
93
- it('should validate an entity with metadata entries', () => {
94
- const entityWithMetadata = {
95
- uuid: 'a38d1597-cc4f-4934-bb08-c876c023f693',
96
- name: 'Test Entity',
97
- attributes: [
98
- {
99
- uuid: 'b49e2608-dd5f-4045-aa09-d464c234e694',
100
- name: 'id',
101
- description: 'Primary identifier',
102
- type: AttributeType.STRING,
103
- required: true,
104
- metadata: [
105
- { name: 'sensitive', value: true },
106
- ],
107
- },
108
- ],
109
- metadata: [
110
- { name: 'owner', value: 'team-a' },
111
- ],
112
- };
113
-
114
- const result = validateEntity(entityWithMetadata);
115
- expect(result.valid).toBe(true);
116
- expect(result.errors).toHaveLength(0);
117
- });
118
- });
119
- });