@hamak/smart-data-dico 1.0.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 (50) hide show
  1. package/README.md +292 -0
  2. package/backend/package.json +51 -0
  3. package/backend/src/__tests__/integration/api.test.ts +149 -0
  4. package/backend/src/__tests__/setup.ts +24 -0
  5. package/backend/src/__tests__/utils/testUtils.ts +76 -0
  6. package/backend/src/adapters/EntityFileAdapter.ts +154 -0
  7. package/backend/src/adapters/YamlFileInfoEnricher.ts +52 -0
  8. package/backend/src/controllers/authController.ts +131 -0
  9. package/backend/src/controllers/diagramController.ts +143 -0
  10. package/backend/src/controllers/dictionaryController.ts +306 -0
  11. package/backend/src/controllers/importExportController.ts +64 -0
  12. package/backend/src/controllers/perspectiveController.ts +90 -0
  13. package/backend/src/controllers/serviceController.ts +418 -0
  14. package/backend/src/controllers/stereotypeController.ts +59 -0
  15. package/backend/src/controllers/versionController.ts +226 -0
  16. package/backend/src/kernel/config.ts +43 -0
  17. package/backend/src/middleware/auth.ts +128 -0
  18. package/backend/src/middleware/jwtAuth.ts +100 -0
  19. package/backend/src/models/Dictionary.ts +38 -0
  20. package/backend/src/models/EntitySchema.ts +393 -0
  21. package/backend/src/models/__tests__/Dictionary.test.ts +92 -0
  22. package/backend/src/models/__tests__/EntitySchema.test.ts +119 -0
  23. package/backend/src/routes/index.ts +120 -0
  24. package/backend/src/scripts/migrate-to-uuid.ts +24 -0
  25. package/backend/src/server.ts +140 -0
  26. package/backend/src/services/__mocks__/entityService.ts +38 -0
  27. package/backend/src/services/__mocks__/serviceService.ts +88 -0
  28. package/backend/src/services/__mocks__/versionService.ts +38 -0
  29. package/backend/src/services/__tests__/dictionaryService.test.ts +74 -0
  30. package/backend/src/services/diagramService.ts +165 -0
  31. package/backend/src/services/dictionaryService.ts +582 -0
  32. package/backend/src/services/entityService.ts +102 -0
  33. package/backend/src/services/exportService.ts +172 -0
  34. package/backend/src/services/importService.ts +208 -0
  35. package/backend/src/services/perspectiveService.ts +276 -0
  36. package/backend/src/services/qualityService.ts +121 -0
  37. package/backend/src/services/serviceService.ts +763 -0
  38. package/backend/src/services/stereotypeService.ts +98 -0
  39. package/backend/src/services/versionService.ts +135 -0
  40. package/backend/src/setupTests.ts +12 -0
  41. package/backend/src/utils/__mocks__/fileOperations.ts +116 -0
  42. package/backend/src/utils/fileOperations.ts +602 -0
  43. package/backend/src/utils/logger.ts +38 -0
  44. package/backend/src/utils/migration.ts +254 -0
  45. package/backend/src/utils/swagger.ts +358 -0
  46. package/backend/src/utils/uuid.ts +41 -0
  47. package/backend/tsconfig.json +20 -0
  48. package/bin/cli.js +129 -0
  49. package/data-dictionaries/stereotypes.yaml +91 -0
  50. package/package.json +42 -0
package/bin/cli.js ADDED
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname, join, resolve } from 'path';
5
+ import { existsSync, mkdirSync, cpSync } from 'fs';
6
+ import { spawn } from 'child_process';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const PKG_ROOT = join(__dirname, '..');
11
+
12
+ // Parse CLI arguments
13
+ const args = process.argv.slice(2);
14
+ const flags = {};
15
+ for (let i = 0; i < args.length; i++) {
16
+ if (args[i] === '--port' && args[i + 1]) { flags.port = args[++i]; }
17
+ else if (args[i] === '--data-dir' && args[i + 1]) { flags.dataDir = args[++i]; }
18
+ else if (args[i] === '--no-open') { flags.noOpen = true; }
19
+ else if (args[i] === '--help' || args[i] === '-h') { flags.help = true; }
20
+ }
21
+
22
+ if (flags.help) {
23
+ console.log(`
24
+ smart-data-dico - Collaborative Data Dictionary Management
25
+
26
+ Usage:
27
+ smart-data-dico [options]
28
+ npx smart-data-dico [options]
29
+
30
+ Options:
31
+ --port <number> Server port (default: 3001)
32
+ --data-dir <path> Data directory path (default: ./data-dictionaries)
33
+ --no-open Don't open browser automatically
34
+ -h, --help Show this help
35
+
36
+ Examples:
37
+ smart-data-dico
38
+ smart-data-dico --port 4000
39
+ smart-data-dico --data-dir ~/my-dictionaries
40
+ `);
41
+ process.exit(0);
42
+ }
43
+
44
+ const port = flags.port || process.env.PORT || '3001';
45
+ const dataDir = resolve(flags.dataDir || process.env.DATA_DIR || './data-dictionaries');
46
+
47
+ // Ensure data directory exists
48
+ if (!existsSync(dataDir)) {
49
+ mkdirSync(dataDir, { recursive: true });
50
+ console.log(`Created data directory: ${dataDir}`);
51
+
52
+ const defaultStereotypes = join(PKG_ROOT, 'data-dictionaries', 'stereotypes.yaml');
53
+ if (existsSync(defaultStereotypes)) {
54
+ cpSync(defaultStereotypes, join(dataDir, 'stereotypes.yaml'));
55
+ console.log('Copied default stereotypes');
56
+ }
57
+
58
+ mkdirSync(join(dataDir, 'microservices'), { recursive: true });
59
+ mkdirSync(join(dataDir, 'perspectives'), { recursive: true });
60
+ }
61
+
62
+ const serverTs = join(PKG_ROOT, 'backend', 'src', 'server.ts');
63
+ const frontendDist = join(PKG_ROOT, 'frontend', 'dist');
64
+
65
+ if (!existsSync(serverTs)) {
66
+ console.error('Error: Backend source not found.');
67
+ process.exit(1);
68
+ }
69
+
70
+ console.log(`
71
+ Smart Data Dictionary
72
+
73
+ Port: ${port}
74
+ Data: ${dataDir}
75
+ Profile: ${process.env.PROFILE || 'local'}
76
+ Frontend: ${existsSync(frontendDist) ? 'bundled' : 'dev (use frontend dev server on :3000)'}
77
+ `);
78
+
79
+ // Find tsx binary — check local node_modules first, then global
80
+ const tsxPaths = [
81
+ join(PKG_ROOT, 'node_modules', '.bin', 'tsx'),
82
+ join(PKG_ROOT, 'backend', 'node_modules', '.bin', 'tsx'),
83
+ ];
84
+ let tsxBin = tsxPaths.find(p => existsSync(p)) || 'npx';
85
+ const tsxArgs = tsxBin === 'npx' ? ['tsx', serverTs] : [serverTs];
86
+
87
+ const child = spawn(tsxBin, tsxArgs, {
88
+ cwd: join(PKG_ROOT, 'backend'),
89
+ env: {
90
+ ...process.env,
91
+ PORT: port,
92
+ NODE_ENV: existsSync(frontendDist) ? 'production' : 'development',
93
+ PROFILE: process.env.PROFILE || 'local',
94
+ DATA_DIR: dataDir,
95
+ },
96
+ stdio: 'inherit',
97
+ });
98
+
99
+ child.on('error', (err) => {
100
+ console.error('Failed to start server:', err.message);
101
+ process.exit(1);
102
+ });
103
+
104
+ child.on('exit', (code) => process.exit(code || 0));
105
+
106
+ // Open browser after short delay
107
+ if (!flags.noOpen) {
108
+ setTimeout(async () => {
109
+ const url = `http://localhost:${port}`;
110
+ console.log(`Opening ${url} ...`);
111
+ try {
112
+ const { exec } = await import('child_process');
113
+ const cmd = process.platform === 'darwin' ? 'open' :
114
+ process.platform === 'win32' ? 'start' : 'xdg-open';
115
+ exec(`${cmd} ${url}`);
116
+ } catch {
117
+ console.log(`Open ${url} in your browser`);
118
+ }
119
+ }, 3000);
120
+ }
121
+
122
+ process.on('SIGINT', () => {
123
+ console.log('\nShutting down...');
124
+ child.kill('SIGINT');
125
+ });
126
+
127
+ process.on('SIGTERM', () => {
128
+ child.kill('SIGTERM');
129
+ });
@@ -0,0 +1,91 @@
1
+ - id: aggregate-root
2
+ name: Aggregate Root
3
+ appliesTo: entity
4
+ description: Root entity of an aggregate boundary
5
+ metadataDefinitions:
6
+ - name: bounded-context
7
+ type: string
8
+ required: true
9
+ description: Name of the bounded context this aggregate belongs to
10
+ - name: invariants
11
+ type: rule
12
+ description: Business invariants enforced by this aggregate
13
+
14
+ - id: reference-data
15
+ name: Reference Data
16
+ appliesTo: entity
17
+ description: Slowly-changing lookup/reference data
18
+ metadataDefinitions:
19
+ - name: cacheable
20
+ type: flag
21
+ required: true
22
+ description: Whether this data can be cached
23
+ - name: update-frequency
24
+ type: string
25
+ description: How often this data changes (daily, weekly, rarely)
26
+
27
+ - id: event
28
+ name: Domain Event
29
+ appliesTo: entity
30
+ description: An event that represents something that happened in the domain
31
+ metadataDefinitions:
32
+ - name: event-source
33
+ type: string
34
+ required: true
35
+ description: The aggregate or service that emits this event
36
+ - name: idempotent
37
+ type: flag
38
+ description: Whether processing this event is idempotent
39
+
40
+ - id: value-object
41
+ name: Value Object
42
+ appliesTo: entity
43
+ description: An immutable object defined by its attributes rather than identity
44
+ metadataDefinitions:
45
+ - name: immutable
46
+ type: flag
47
+ required: true
48
+
49
+ - id: pii
50
+ name: PII
51
+ appliesTo: attribute
52
+ description: Personally Identifiable Information
53
+ metadataDefinitions:
54
+ - name: pii-category
55
+ type: string
56
+ required: true
57
+ description: "Category: direct, indirect, or sensitive"
58
+ - name: retention-days
59
+ type: number
60
+ description: Data retention period in days
61
+ - name: encryption-required
62
+ type: flag
63
+ description: Whether this field must be encrypted at rest
64
+
65
+ - id: indexed
66
+ name: Indexed
67
+ appliesTo: attribute
68
+ description: Database-indexed attribute
69
+ metadataDefinitions:
70
+ - name: index-type
71
+ type: string
72
+ description: "Index type: btree, hash, gin, gist"
73
+ - name: unique-index
74
+ type: flag
75
+ description: Whether the index enforces uniqueness
76
+
77
+ - id: deprecated
78
+ name: Deprecated
79
+ appliesTo: attribute
80
+ description: Attribute scheduled for removal
81
+ metadataDefinitions:
82
+ - name: deprecated-since
83
+ type: date
84
+ required: true
85
+ description: Date when this attribute was deprecated
86
+ - name: replacement
87
+ type: string
88
+ description: Name of the replacement attribute
89
+ - name: removal-target
90
+ type: date
91
+ description: Target date for removal
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@hamak/smart-data-dico",
3
+ "version": "1.0.0",
4
+ "description": "Collaborative data dictionary management system — model, document, and govern your data landscape",
5
+ "type": "module",
6
+ "bin": {
7
+ "smart-data-dico": "bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "build": "cd frontend && npm run build",
11
+ "start": "node bin/cli.js",
12
+ "prepublishOnly": "npm run build"
13
+ },
14
+ "files": [
15
+ "bin/",
16
+ "backend/src/",
17
+ "backend/package.json",
18
+ "backend/tsconfig.json",
19
+ "frontend/dist/",
20
+ "data-dictionaries/stereotypes.yaml"
21
+ ],
22
+ "dependencies": {
23
+ "tsx": "^4.0.0"
24
+ },
25
+ "keywords": [
26
+ "data-dictionary",
27
+ "data-modeling",
28
+ "data-governance",
29
+ "schema-management",
30
+ "yaml",
31
+ "git"
32
+ ],
33
+ "author": "",
34
+ "license": "MIT",
35
+ "engines": {
36
+ "node": ">=18.0.0"
37
+ },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/amah/smart-data-dico.git"
41
+ }
42
+ }