modscape 1.0.8 → 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.
- package/package.json +1 -1
- package/src/export.js +84 -11
- package/src/index.js +1 -1
- package/visualizer/package.json +2 -1
- package/visualizer-dist/assets/index-B4th5tqq.js +63 -0
- package/visualizer-dist/assets/index-DLjsShXS.css +1 -0
- package/visualizer-dist/index.html +2 -2
- package/visualizer-dist/assets/index-D-n9UqHA.css +0 -1
- package/visualizer-dist/assets/index-_wTHYing.js +0 -56
package/package.json
CHANGED
package/src/export.js
CHANGED
|
@@ -15,6 +15,7 @@ function normalizeSchema(data) {
|
|
|
15
15
|
tables: Array.isArray(data.tables) ? data.tables : [],
|
|
16
16
|
relationships: Array.isArray(data.relationships) ? data.relationships : [],
|
|
17
17
|
domains: Array.isArray(data.domains) ? data.domains : [],
|
|
18
|
+
annotations: Array.isArray(data.annotations) ? data.annotations : [],
|
|
18
19
|
layout: data.layout || {}
|
|
19
20
|
};
|
|
20
21
|
|
|
@@ -30,11 +31,18 @@ function normalizeSchema(data) {
|
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
const columns = (Array.isArray(table.columns) ? table.columns : []).map(col => ({
|
|
35
|
+
...col,
|
|
36
|
+
id: col.id || 'unknown',
|
|
37
|
+
logical: col.logical || { name: col.id || 'unknown', type: 'string' },
|
|
38
|
+
physical: col.physical || { name: '', type: '' }
|
|
39
|
+
}));
|
|
40
|
+
|
|
33
41
|
return {
|
|
34
42
|
...table,
|
|
35
43
|
id: table.id || 'unknown',
|
|
36
44
|
name: table.name || table.id || 'Unnamed Table',
|
|
37
|
-
columns
|
|
45
|
+
columns,
|
|
38
46
|
sampleData: Array.isArray(sampleData) ? sampleData : []
|
|
39
47
|
};
|
|
40
48
|
});
|
|
@@ -47,7 +55,31 @@ function normalizeSchema(data) {
|
|
|
47
55
|
* Spaces and hyphens are replaced with underscores.
|
|
48
56
|
*/
|
|
49
57
|
function sanitize(str) {
|
|
50
|
-
|
|
58
|
+
if (!str) return 'unknown';
|
|
59
|
+
// Mermaid ER/Flowchart labels can be wrapped in quotes for better compatibility
|
|
60
|
+
return str.replace(/[^a-zA-Z0-9_\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf]/g, '_');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Generates Mermaid Data Lineage syntax.
|
|
65
|
+
*/
|
|
66
|
+
function generateMermaidLineage(schema) {
|
|
67
|
+
let mermaid = 'graph TD\n';
|
|
68
|
+
let hasLineage = false;
|
|
69
|
+
|
|
70
|
+
schema.tables.forEach(table => {
|
|
71
|
+
if (table.lineage?.upstream && table.lineage.upstream.length > 0) {
|
|
72
|
+
hasLineage = true;
|
|
73
|
+
const targetName = sanitize(table.name);
|
|
74
|
+
table.lineage.upstream.forEach(upId => {
|
|
75
|
+
const sourceTable = schema.tables.find(t => t.id === upId);
|
|
76
|
+
const sourceName = sanitize(sourceTable?.name || upId);
|
|
77
|
+
mermaid += ` ${sourceName} --> ${targetName}\n`;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return hasLineage ? mermaid : null;
|
|
51
83
|
}
|
|
52
84
|
|
|
53
85
|
/**
|
|
@@ -88,6 +120,24 @@ function generateMermaidER(schema) {
|
|
|
88
120
|
return mermaid;
|
|
89
121
|
}
|
|
90
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Generates the Sticky Notes section.
|
|
125
|
+
*/
|
|
126
|
+
function generateNotesSection(schema) {
|
|
127
|
+
if (!schema.annotations || schema.annotations.length === 0) return null;
|
|
128
|
+
|
|
129
|
+
let md = '## Sticky Notes\n\n';
|
|
130
|
+
schema.annotations.forEach(note => {
|
|
131
|
+
md += `> **[Note]** ${note.text}\n`;
|
|
132
|
+
if (note.targetId) {
|
|
133
|
+
md += `> *Attached to: ${note.targetId} (${note.targetType})*\n`;
|
|
134
|
+
}
|
|
135
|
+
md += '\n';
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return md;
|
|
139
|
+
}
|
|
140
|
+
|
|
91
141
|
/**
|
|
92
142
|
* Generates the full Markdown document.
|
|
93
143
|
*/
|
|
@@ -95,10 +145,21 @@ export function generateMarkdown(schema, modelName) {
|
|
|
95
145
|
let md = `# ${modelName} Data Model Definition\n\n`;
|
|
96
146
|
|
|
97
147
|
// Mermaid ER Diagram
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
148
|
+
if (schema.relationships && schema.relationships.length > 0) {
|
|
149
|
+
md += '## ER Diagram\n\n';
|
|
150
|
+
md += '```mermaid\n';
|
|
151
|
+
md += generateMermaidER(schema);
|
|
152
|
+
md += '```\n\n';
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Mermaid Data Lineage
|
|
156
|
+
const lineageMermaid = generateMermaidLineage(schema);
|
|
157
|
+
if (lineageMermaid) {
|
|
158
|
+
md += '## Data Lineage\n\n';
|
|
159
|
+
md += '```mermaid\n';
|
|
160
|
+
md += lineageMermaid;
|
|
161
|
+
md += '```\n\n';
|
|
162
|
+
}
|
|
102
163
|
|
|
103
164
|
// Domains
|
|
104
165
|
if (schema.domains && schema.domains.length > 0) {
|
|
@@ -123,20 +184,26 @@ export function generateMarkdown(schema, modelName) {
|
|
|
123
184
|
md += `**Description**: ${table.conceptual.description}\n\n`;
|
|
124
185
|
}
|
|
125
186
|
if (table.appearance?.type) {
|
|
126
|
-
md += `**Type**: ${table.appearance.type}\n\n`;
|
|
187
|
+
md += `**Type**: ${table.appearance.type.toUpperCase()}\n\n`;
|
|
127
188
|
}
|
|
128
189
|
|
|
129
|
-
// Columns Table
|
|
190
|
+
// Columns Table (Enhanced with Physical info)
|
|
130
191
|
if (table.columns && table.columns.length > 0) {
|
|
131
192
|
md += '#### Column Definitions\n\n';
|
|
132
|
-
md += '|
|
|
133
|
-
md += '| --- | --- | --- | --- | --- |\n';
|
|
193
|
+
md += '| Logical Name | Physical Name | Logical Type | Physical Type | Key | Description |\n';
|
|
194
|
+
md += '| --- | --- | --- | --- | --- | --- |\n';
|
|
134
195
|
table.columns.forEach(col => {
|
|
135
196
|
const key = [
|
|
136
197
|
col.logical?.isPrimaryKey ? 'PK' : '',
|
|
137
198
|
col.logical?.isForeignKey ? 'FK' : ''
|
|
138
199
|
].filter(Boolean).join(', ');
|
|
139
|
-
|
|
200
|
+
const logicalName = col.logical?.name || col.id;
|
|
201
|
+
const physicalName = col.physical?.name || '-';
|
|
202
|
+
const logicalType = col.logical?.type || '-';
|
|
203
|
+
const physicalType = col.physical?.type || '-';
|
|
204
|
+
const description = col.logical?.description || '-';
|
|
205
|
+
|
|
206
|
+
md += `| ${logicalName} | ${physicalName} | ${logicalType} | ${physicalType} | ${key || '-'} | ${description} |\n`;
|
|
140
207
|
});
|
|
141
208
|
md += '\n';
|
|
142
209
|
}
|
|
@@ -157,6 +224,12 @@ export function generateMarkdown(schema, modelName) {
|
|
|
157
224
|
}
|
|
158
225
|
});
|
|
159
226
|
|
|
227
|
+
// Sticky Notes Section
|
|
228
|
+
const notesSection = generateNotesSection(schema);
|
|
229
|
+
if (notesSection) {
|
|
230
|
+
md += notesSection;
|
|
231
|
+
}
|
|
232
|
+
|
|
160
233
|
return md;
|
|
161
234
|
}
|
|
162
235
|
|
package/src/index.js
CHANGED
package/visualizer/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "visualizer",
|
|
3
3
|
"private": true,
|
|
4
|
-
"version": "1.0
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "vite",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"clsx": "^2.1.1",
|
|
21
21
|
"codemirror": "^6.0.2",
|
|
22
22
|
"dagre": "^0.8.5",
|
|
23
|
+
"html-to-image": "^1.11.13",
|
|
23
24
|
"js-yaml": "^4.1.1",
|
|
24
25
|
"lucide-react": "^0.575.0",
|
|
25
26
|
"react": "^19.2.0",
|