@memberjunction/db-auto-doc 6.2.0-edge.4 → 6.2.0-edge.6

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 (183) hide show
  1. package/README.md +105 -0
  2. package/dist/api/DBAutoDocAPI.d.ts +2 -0
  3. package/dist/api/DBAutoDocAPI.d.ts.map +1 -1
  4. package/dist/api/DBAutoDocAPI.js +2 -1
  5. package/dist/api/DBAutoDocAPI.js.map +1 -1
  6. package/dist/commands/analyze.d.ts +1 -0
  7. package/dist/commands/analyze.d.ts.map +1 -1
  8. package/dist/commands/analyze.js +6 -0
  9. package/dist/commands/analyze.js.map +1 -1
  10. package/dist/commands/export.d.ts +28 -19
  11. package/dist/commands/export.d.ts.map +1 -1
  12. package/dist/commands/export.js +91 -12
  13. package/dist/commands/export.js.map +1 -1
  14. package/dist/core/AnalysisEngine.d.ts +39 -6
  15. package/dist/core/AnalysisEngine.d.ts.map +1 -1
  16. package/dist/core/AnalysisEngine.js +144 -50
  17. package/dist/core/AnalysisEngine.js.map +1 -1
  18. package/dist/core/AnalysisOrchestrator.d.ts +20 -1
  19. package/dist/core/AnalysisOrchestrator.d.ts.map +1 -1
  20. package/dist/core/AnalysisOrchestrator.js +144 -28
  21. package/dist/core/AnalysisOrchestrator.js.map +1 -1
  22. package/dist/core/PKProposalGate.d.ts +22 -0
  23. package/dist/core/PKProposalGate.d.ts.map +1 -0
  24. package/dist/core/PKProposalGate.js +52 -0
  25. package/dist/core/PKProposalGate.js.map +1 -0
  26. package/dist/database/Database.d.ts +8 -0
  27. package/dist/database/Database.d.ts.map +1 -1
  28. package/dist/database/Database.js +23 -1
  29. package/dist/database/Database.js.map +1 -1
  30. package/dist/discovery/ColumnNormalizer.d.ts +31 -0
  31. package/dist/discovery/ColumnNormalizer.d.ts.map +1 -1
  32. package/dist/discovery/ColumnNormalizer.js +68 -2
  33. package/dist/discovery/ColumnNormalizer.js.map +1 -1
  34. package/dist/discovery/Composer.d.ts +33 -2
  35. package/dist/discovery/Composer.d.ts.map +1 -1
  36. package/dist/discovery/Composer.js +126 -5
  37. package/dist/discovery/Composer.js.map +1 -1
  38. package/dist/discovery/DiscoveryEngine.d.ts +3 -0
  39. package/dist/discovery/DiscoveryEngine.d.ts.map +1 -1
  40. package/dist/discovery/DiscoveryEngine.js +1 -1
  41. package/dist/discovery/DiscoveryEngine.js.map +1 -1
  42. package/dist/discovery/EmbeddingProvider.d.ts +6 -1
  43. package/dist/discovery/EmbeddingProvider.d.ts.map +1 -1
  44. package/dist/discovery/EmbeddingProvider.js +11 -1
  45. package/dist/discovery/EmbeddingProvider.js.map +1 -1
  46. package/dist/discovery/EnumCandidateGate.d.ts +19 -0
  47. package/dist/discovery/EnumCandidateGate.d.ts.map +1 -1
  48. package/dist/discovery/EnumCandidateGate.js +47 -5
  49. package/dist/discovery/EnumCandidateGate.js.map +1 -1
  50. package/dist/discovery/FKGraphWalker.d.ts +35 -0
  51. package/dist/discovery/FKGraphWalker.d.ts.map +1 -1
  52. package/dist/discovery/FKGraphWalker.js +113 -12
  53. package/dist/discovery/FKGraphWalker.js.map +1 -1
  54. package/dist/discovery/IndexKeyEvidence.d.ts +36 -0
  55. package/dist/discovery/IndexKeyEvidence.d.ts.map +1 -0
  56. package/dist/discovery/IndexKeyEvidence.js +42 -0
  57. package/dist/discovery/IndexKeyEvidence.js.map +1 -0
  58. package/dist/discovery/JoinProbe.d.ts +148 -0
  59. package/dist/discovery/JoinProbe.d.ts.map +1 -0
  60. package/dist/discovery/JoinProbe.js +233 -0
  61. package/dist/discovery/JoinProbe.js.map +1 -0
  62. package/dist/discovery/LLMDiscoveryValidator.d.ts +10 -1
  63. package/dist/discovery/LLMDiscoveryValidator.d.ts.map +1 -1
  64. package/dist/discovery/LLMDiscoveryValidator.js +44 -12
  65. package/dist/discovery/LLMDiscoveryValidator.js.map +1 -1
  66. package/dist/discovery/LLMSanityChecker.d.ts.map +1 -1
  67. package/dist/discovery/LLMSanityChecker.js +10 -1
  68. package/dist/discovery/LLMSanityChecker.js.map +1 -1
  69. package/dist/discovery/OrganicKeyDetector.d.ts +29 -1
  70. package/dist/discovery/OrganicKeyDetector.d.ts.map +1 -1
  71. package/dist/discovery/OrganicKeyDetector.js +34 -5
  72. package/dist/discovery/OrganicKeyDetector.js.map +1 -1
  73. package/dist/discovery/OrganicKeyTranslator.d.ts +24 -5
  74. package/dist/discovery/OrganicKeyTranslator.d.ts.map +1 -1
  75. package/dist/discovery/OrganicKeyTranslator.js +32 -14
  76. package/dist/discovery/OrganicKeyTranslator.js.map +1 -1
  77. package/dist/discovery/PKDetector.d.ts +9 -0
  78. package/dist/discovery/PKDetector.d.ts.map +1 -1
  79. package/dist/discovery/PKDetector.js +86 -8
  80. package/dist/discovery/PKDetector.js.map +1 -1
  81. package/dist/discovery/SemanticPhase.d.ts +25 -0
  82. package/dist/discovery/SemanticPhase.d.ts.map +1 -1
  83. package/dist/discovery/SemanticPhase.js +55 -11
  84. package/dist/discovery/SemanticPhase.js.map +1 -1
  85. package/dist/discovery/StructuralPhase.d.ts +27 -5
  86. package/dist/discovery/StructuralPhase.d.ts.map +1 -1
  87. package/dist/discovery/StructuralPhase.js +42 -9
  88. package/dist/discovery/StructuralPhase.js.map +1 -1
  89. package/dist/discovery/TransitiveBridgeDetector.d.ts +5 -1
  90. package/dist/discovery/TransitiveBridgeDetector.d.ts.map +1 -1
  91. package/dist/discovery/TransitiveBridgeDetector.js +25 -3
  92. package/dist/discovery/TransitiveBridgeDetector.js.map +1 -1
  93. package/dist/discovery/embedding-provider-default.d.ts +25 -0
  94. package/dist/discovery/embedding-provider-default.d.ts.map +1 -0
  95. package/dist/discovery/embedding-provider-default.js +47 -0
  96. package/dist/discovery/embedding-provider-default.js.map +1 -0
  97. package/dist/drivers/BaseAutoDocDriver.d.ts +63 -0
  98. package/dist/drivers/BaseAutoDocDriver.d.ts.map +1 -1
  99. package/dist/drivers/BaseAutoDocDriver.js +3 -5
  100. package/dist/drivers/BaseAutoDocDriver.js.map +1 -1
  101. package/dist/drivers/MySQLDriver.d.ts +21 -1
  102. package/dist/drivers/MySQLDriver.d.ts.map +1 -1
  103. package/dist/drivers/MySQLDriver.js +64 -0
  104. package/dist/drivers/MySQLDriver.js.map +1 -1
  105. package/dist/drivers/PostgreSQLDriver.d.ts +43 -2
  106. package/dist/drivers/PostgreSQLDriver.d.ts.map +1 -1
  107. package/dist/drivers/PostgreSQLDriver.js +132 -19
  108. package/dist/drivers/PostgreSQLDriver.js.map +1 -1
  109. package/dist/drivers/SQLServerDriver.d.ts +28 -1
  110. package/dist/drivers/SQLServerDriver.d.ts.map +1 -1
  111. package/dist/drivers/SQLServerDriver.js +108 -1
  112. package/dist/drivers/SQLServerDriver.js.map +1 -1
  113. package/dist/drivers/probeErrors.d.ts +30 -0
  114. package/dist/drivers/probeErrors.d.ts.map +1 -0
  115. package/dist/drivers/probeErrors.js +94 -0
  116. package/dist/drivers/probeErrors.js.map +1 -0
  117. package/dist/generators/AdditionalSchemaInfoGenerator.d.ts +34 -18
  118. package/dist/generators/AdditionalSchemaInfoGenerator.d.ts.map +1 -1
  119. package/dist/generators/AdditionalSchemaInfoGenerator.js +130 -8
  120. package/dist/generators/AdditionalSchemaInfoGenerator.js.map +1 -1
  121. package/dist/generators/ErdClusterGenerator.d.ts +44 -0
  122. package/dist/generators/ErdClusterGenerator.d.ts.map +1 -0
  123. package/dist/generators/ErdClusterGenerator.js +216 -0
  124. package/dist/generators/ErdClusterGenerator.js.map +1 -0
  125. package/dist/generators/ErdClusterer.d.ts +130 -0
  126. package/dist/generators/ErdClusterer.d.ts.map +1 -0
  127. package/dist/generators/ErdClusterer.js +308 -0
  128. package/dist/generators/ErdClusterer.js.map +1 -0
  129. package/dist/generators/HTMLGenerator.d.ts +6 -0
  130. package/dist/generators/HTMLGenerator.d.ts.map +1 -1
  131. package/dist/generators/HTMLGenerator.js +41 -6
  132. package/dist/generators/HTMLGenerator.js.map +1 -1
  133. package/dist/generators/MermaidGenerator.d.ts +3 -0
  134. package/dist/generators/MermaidGenerator.d.ts.map +1 -1
  135. package/dist/generators/MermaidGenerator.js +4 -0
  136. package/dist/generators/MermaidGenerator.js.map +1 -1
  137. package/dist/generators/index.d.ts +2 -0
  138. package/dist/generators/index.d.ts.map +1 -1
  139. package/dist/generators/index.js +2 -0
  140. package/dist/generators/index.js.map +1 -1
  141. package/dist/prompts/PromptEngine.d.ts.map +1 -1
  142. package/dist/prompts/PromptEngine.js +10 -1
  143. package/dist/prompts/PromptEngine.js.map +1 -1
  144. package/dist/types/analysis.d.ts +2 -0
  145. package/dist/types/analysis.d.ts.map +1 -1
  146. package/dist/types/config.d.ts +128 -4
  147. package/dist/types/config.d.ts.map +1 -1
  148. package/dist/types/config.js +7 -1
  149. package/dist/types/config.js.map +1 -1
  150. package/dist/types/discovery.d.ts +41 -0
  151. package/dist/types/discovery.d.ts.map +1 -1
  152. package/dist/types/state.d.ts +29 -0
  153. package/dist/types/state.d.ts.map +1 -1
  154. package/dist/utils/call-deadline.d.ts +43 -0
  155. package/dist/utils/call-deadline.d.ts.map +1 -0
  156. package/dist/utils/call-deadline.js +81 -0
  157. package/dist/utils/call-deadline.js.map +1 -0
  158. package/dist/utils/config-loader.d.ts +5 -0
  159. package/dist/utils/config-loader.d.ts.map +1 -1
  160. package/dist/utils/config-loader.js +37 -0
  161. package/dist/utils/config-loader.js.map +1 -1
  162. package/dist/utils/index-hints.d.ts +43 -0
  163. package/dist/utils/index-hints.d.ts.map +1 -0
  164. package/dist/utils/index-hints.js +80 -0
  165. package/dist/utils/index-hints.js.map +1 -0
  166. package/dist/utils/index.d.ts +2 -0
  167. package/dist/utils/index.d.ts.map +1 -1
  168. package/dist/utils/index.js +2 -0
  169. package/dist/utils/index.js.map +1 -1
  170. package/dist/utils/llm-factory.d.ts +1 -0
  171. package/dist/utils/llm-factory.d.ts.map +1 -1
  172. package/dist/utils/llm-factory.js +6 -1
  173. package/dist/utils/llm-factory.js.map +1 -1
  174. package/dist/utils/seed-context.d.ts +23 -0
  175. package/dist/utils/seed-context.d.ts.map +1 -0
  176. package/dist/utils/seed-context.js +38 -0
  177. package/dist/utils/seed-context.js.map +1 -0
  178. package/package.json +5 -5
  179. package/prompts/fk-pruning-holistic.md +7 -0
  180. package/prompts/fk-pruning-table.md +20 -1
  181. package/prompts/pk-pruning-holistic.md +7 -0
  182. package/prompts/pk-pruning-table.md +17 -0
  183. package/prompts/table-analysis.md +11 -0
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Renders an ErdClusterPlan as one Mermaid ERD per cluster page, each wrapped in a standalone HTML
3
+ * page, plus an index (HTML and Markdown) that lists the subject areas, the reference tables and the
4
+ * tables no diagram shows. Every page stays well inside Mermaid's text limit by drawing primary and
5
+ * foreign key columns only (configurable).
6
+ */
7
+ /** Mermaid's default maxTextSize is 50,000; pages stay well below it, this is the viewer's ceiling. */
8
+ const VIEWER_MAX_TEXT_SIZE = 200000;
9
+ /** Mermaid's default maxEdges is 500; a hub page can carry more relationships than that. */
10
+ const VIEWER_MAX_EDGES = 5000;
11
+ /** Hub descriptions are long; the index shows this much of each. */
12
+ const INDEX_DESCRIPTION_CHARS = 160;
13
+ export class ErdClusterGenerator {
14
+ Generate(state, plan, options = {}) {
15
+ const columns = options.columns ?? 'keys';
16
+ const files = [];
17
+ for (const cluster of plan.Clusters) {
18
+ for (const page of cluster.Pages) {
19
+ const title = `${page.Title} — ${page.Tables.length} tables`;
20
+ const mermaid = this.RenderPage(plan, cluster, page, columns);
21
+ files.push({
22
+ BaseName: page.BaseName,
23
+ Title: title,
24
+ Cluster: cluster,
25
+ Page: page,
26
+ Mermaid: mermaid,
27
+ Html: this.renderPageHtml(state, plan, cluster, page, title, mermaid),
28
+ });
29
+ }
30
+ }
31
+ return {
32
+ Files: files,
33
+ IndexHtml: this.renderIndexHtml(state, plan, files),
34
+ IndexMarkdown: this.renderIndexMarkdown(state, plan, files),
35
+ };
36
+ }
37
+ /** The Mermaid source for one page: its tables and the FK edges between them. */
38
+ RenderPage(plan, cluster, page, columns = 'keys') {
39
+ const onPage = new Set(page.Tables);
40
+ const lines = ['erDiagram'];
41
+ for (const key of page.Tables) {
42
+ // Entity and relationship lines must agree on the name; the plan's display name is unique across schemas
43
+ lines.push(` ${this.identifier(plan.NameOf(key))} {`);
44
+ for (const column of plan.TableOf(key).columns) {
45
+ if (!this.showColumn(column, columns))
46
+ continue;
47
+ const flags = [column.isPrimaryKey && 'PK', column.isForeignKey && 'FK'].filter(Boolean).join(',');
48
+ const type = (column.dataType || 'unknown').replace(/\s+/g, '_');
49
+ lines.push(` ${type} ${this.identifier(column.name)}${flags ? ` "${flags}"` : ''}`);
50
+ }
51
+ lines.push(' }');
52
+ }
53
+ for (const edge of cluster.InternalEdges) {
54
+ if (onPage.has(edge.From) && onPage.has(edge.To)) {
55
+ const parent = this.identifier(plan.NameOf(edge.To));
56
+ const child = this.identifier(plan.NameOf(edge.From));
57
+ lines.push(` ${parent} ||--o{ ${child} : "${this.identifier(edge.FromColumn || '')}"`);
58
+ }
59
+ }
60
+ return lines.join('\n');
61
+ }
62
+ showColumn(column, mode) {
63
+ if (mode === 'none')
64
+ return false;
65
+ if (mode === 'all')
66
+ return true;
67
+ return column.isPrimaryKey || column.isForeignKey;
68
+ }
69
+ /** Mermaid entity and attribute names allow only word characters. */
70
+ identifier(name) {
71
+ return name.replace(/[^A-Za-z0-9_]/g, '_');
72
+ }
73
+ /** `label` plus the tables at the far end of `edges`, each with how many edges reach it. */
74
+ linkedAreas(plan, label, edges, farEnd) {
75
+ if (edges.length === 0)
76
+ return '';
77
+ const counts = new Map();
78
+ for (const e of edges)
79
+ counts.set(farEnd(e), (counts.get(farEnd(e)) ?? 0) + 1);
80
+ const items = [...counts]
81
+ .sort((a, b) => b[1] - a[1])
82
+ .map(([t, n]) => `${this.escape(plan.NameOf(t))} <span class="count">(${n})</span>`)
83
+ .join(', ');
84
+ return `<h3>${label}</h3><p class="refs">${items}</p>`;
85
+ }
86
+ renderPageHtml(state, plan, cluster, page, title, mermaid) {
87
+ const hub = plan.TableOf(cluster.Hub);
88
+ const pageLinks = cluster.Pages
89
+ .map(p => p.Number === page.Number ? `<strong>${p.Number}</strong>` : `<a href="${p.BaseName}.html">${p.Number}</a>`)
90
+ .join(' · ');
91
+ const otherPages = cluster.Pages.length > 1 ? `<p>Pages: ${pageLinks}</p>` : '';
92
+ const referenceItems = cluster.ReferenceTables
93
+ .map(r => `${this.escape(r.Table)} <span class="count">(${r.UsedBy})</span>`)
94
+ .join(', ');
95
+ const references = cluster.ReferenceTables.length > 0
96
+ ? `<h3>Reference tables used by this area</h3><p class="refs">${referenceItems}</p>`
97
+ : '';
98
+ return `<!DOCTYPE html>
99
+ <html lang="en">
100
+ <head>
101
+ <meta charset="UTF-8">
102
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
103
+ <title>${this.escape(title)} - ${this.escape(state.database.name)}</title>
104
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"><\/script>
105
+ <style>
106
+ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 1.5rem; color: #333; }
107
+ h1 { color: #667eea; margin-bottom: .25rem; }
108
+ .desc { max-width: 70rem; color: #555; }
109
+ .mermaid { overflow: auto; background: #f9f9f9; border: 1px solid #e0e0e0; border-radius: 4px; padding: 1rem; }
110
+ .refs { max-width: 70rem; line-height: 1.6; }
111
+ .count { color: #888; }
112
+ nav a { margin-right: 1rem; }
113
+ </style>
114
+ </head>
115
+ <body>
116
+ <nav><a href="index.html">All subject areas</a><a href="../documentation.html">Documentation</a></nav>
117
+ <h1>${this.escape(title)}</h1>
118
+ ${hub.description ? `<p class="desc">${this.escape(hub.description)}</p>` : ''}
119
+ ${otherPages}
120
+ <pre class="mermaid">
121
+ ${this.escape(mermaid)}
122
+ </pre>
123
+ ${references}
124
+ ${this.linkedAreas(plan, 'References tables in other areas', cluster.OutboundEdges, e => e.To)}
125
+ ${this.linkedAreas(plan, 'Referenced from other areas', cluster.InboundEdges, e => e.From)}
126
+ <script>mermaid.initialize({ startOnLoad: true, theme: 'default', securityLevel: 'loose', maxTextSize: ${VIEWER_MAX_TEXT_SIZE}, maxEdges: ${VIEWER_MAX_EDGES} });<\/script>
127
+ </body>
128
+ </html>`;
129
+ }
130
+ renderIndexHtml(state, plan, files) {
131
+ const rows = files.map(f => {
132
+ const hub = plan.TableOf(f.Cluster.Hub);
133
+ const description = this.escape((hub.description ?? '').slice(0, INDEX_DESCRIPTION_CHARS));
134
+ return `<tr><td><a href="${f.BaseName}.html">${this.escape(f.Title)}</a></td>`
135
+ + `<td>${f.Cluster.Tables.length}</td><td>${f.Cluster.InternalEdges.length}</td>`
136
+ + `<td>${f.Cluster.OutboundEdges.length} / ${f.Cluster.InboundEdges.length}</td><td>${description}</td></tr>`;
137
+ }).join('\n');
138
+ const list = (title, items) => items.length === 0
139
+ ? ''
140
+ : `<h2>${title} (${items.length})</h2><p class="refs">${items.map(i => this.escape(i)).join(', ')}</p>`;
141
+ const summary = this.planSummary(plan, 'html');
142
+ return `<!DOCTYPE html>
143
+ <html lang="en">
144
+ <head>
145
+ <meta charset="UTF-8">
146
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
147
+ <title>Subject areas - ${this.escape(state.database.name)}</title>
148
+ <style>
149
+ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 1.5rem; color: #333; max-width: 80rem; }
150
+ h1 { color: #667eea; }
151
+ table { border-collapse: collapse; width: 100%; }
152
+ th, td { border: 1px solid #ddd; padding: .4rem .6rem; text-align: left; vertical-align: top; }
153
+ th { background: #f4f4f8; }
154
+ .refs { line-height: 1.6; color: #555; }
155
+ .meta { color: #666; }
156
+ </style>
157
+ </head>
158
+ <body>
159
+ <p><a href="../documentation.html">Documentation</a></p>
160
+ <h1>Subject areas — ${this.escape(state.database.name)}</h1>
161
+ <p class="meta">${summary}</p>
162
+ <table>
163
+ <thead><tr><th>Subject area</th><th>Tables</th><th>FKs inside</th><th>Links out / in</th><th>Hub description</th></tr></thead>
164
+ <tbody>
165
+ ${rows}
166
+ </tbody>
167
+ </table>
168
+ ${list('Reference tables (listed, not drawn)', plan.ReferenceTables.map(r => `${r.Table} (${r.ReferencedBy})`))}
169
+ ${list('Tables with no foreign keys', plan.IsolatedTables)}
170
+ ${list('Connected tables outside every subject area', plan.UnassignedTables)}
171
+ ${list('Excluded by configuration', plan.ExcludedTables)}
172
+ </body>
173
+ </html>`;
174
+ }
175
+ renderIndexMarkdown(state, plan, files) {
176
+ const md = [
177
+ `# Subject areas — ${state.database.name}`,
178
+ '',
179
+ this.planSummary(plan, 'markdown'),
180
+ '',
181
+ '| Subject area | Tables | FKs inside | Links out / in | Hub description |',
182
+ '|---|---|---|---|---|',
183
+ ];
184
+ for (const f of files) {
185
+ const hub = plan.TableOf(f.Cluster.Hub);
186
+ const description = (hub.description ?? '').replace(/\|/g, '/').slice(0, INDEX_DESCRIPTION_CHARS);
187
+ const c = f.Cluster;
188
+ md.push(`| [${f.Title}](${f.BaseName}.html) | ${c.Tables.length} | ${c.InternalEdges.length} | ${c.OutboundEdges.length} / ${c.InboundEdges.length} | ${description} |`);
189
+ }
190
+ md.push('', '## Membership', '');
191
+ for (const c of plan.Clusters)
192
+ md.push(`**${c.HubName}**: ${c.Tables.map(plan.NameOf).join(', ')}`, '');
193
+ const section = (title, items) => {
194
+ if (items.length > 0)
195
+ md.push(`## ${title} (${items.length})`, '', items.join(', '), '');
196
+ };
197
+ section('Reference tables (listed, not drawn)', plan.ReferenceTables.map(r => `${r.Table} (${r.ReferencedBy})`));
198
+ section('Tables with no foreign keys', plan.IsolatedTables);
199
+ section('Connected tables outside every subject area', plan.UnassignedTables);
200
+ section('Excluded by configuration', plan.ExcludedTables);
201
+ return md.join('\n');
202
+ }
203
+ /** The one-paragraph description of how the plan was built, shared by both indexes. */
204
+ planSummary(plan, format) {
205
+ const covered = plan.Clusters.reduce((n, c) => n + c.Tables.length, 0);
206
+ const rows = plan.Options.lookupMaxRows.toLocaleString();
207
+ const head = `${plan.TotalTables} tables and ${plan.TotalEdges} foreign-key relationships. ${plan.Clusters.length} subject areas cover ${covered} tables`;
208
+ return format === 'html'
209
+ ? `${head}; hubs are tables referenced by at least ${plan.Options.hubMinInbound} others, reference tables are those that reference nothing and hold fewer than ${rows} rows.`
210
+ : `${head} (hubs: referenced by ≥ ${plan.Options.hubMinInbound}; reference tables: reference nothing and < ${rows} rows).`;
211
+ }
212
+ escape(text) {
213
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
214
+ }
215
+ }
216
+ //# sourceMappingURL=ErdClusterGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErdClusterGenerator.js","sourceRoot":"","sources":["../../src/generators/ErdClusterGenerator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Splits a database's foreign-key graph into hub-centred clusters ("subject areas") small enough
3
+ * to draw one at a time. Pure computation over the analysis state; rendering lives in
4
+ * ErdClusterGenerator.
5
+ *
6
+ * Method:
7
+ * 1. Reference (lookup) tables — tables that reference nothing and hold few rows — are set aside.
8
+ * Left in, a table such as a yes/no flag referenced by sixty others links every subject area to
9
+ * every other and the clusters collapse into one.
10
+ * 2. Hubs are the tables referenced by at least `hubMinInbound` non-reference tables, plus any
11
+ * names in `hubs`.
12
+ * 3. Every other connected table is assigned to its nearest hub (multi-source breadth-first search
13
+ * over the undirected FK graph).
14
+ * 4. A hub whose cluster is smaller than `minClusterSize` is folded into the neighbouring cluster
15
+ * its members link to most, so the index is not littered with two-table "areas".
16
+ * 5. A cluster larger than `pageSize` is paginated; the hub appears on every page.
17
+ *
18
+ * Tables are keyed `schema.table` with case preserved: same-named tables in different schemas are
19
+ * different tables, and so are `Customer` and `customer` on PostgreSQL.
20
+ */
21
+ import { DatabaseDocumentation, TableDefinition } from '../types/state.js';
22
+ /** Mirrors the `output.erd` keys of config.json (camelCase) so a config object can be passed straight through. */
23
+ export interface ErdClustererOptions {
24
+ hubMinInbound?: number;
25
+ lookupMaxRows?: number;
26
+ pageSize?: number;
27
+ minClusterSize?: number;
28
+ hubs?: string[];
29
+ excludeTables?: string[];
30
+ lookupTables?: string[];
31
+ }
32
+ /** One foreign key edge: `From.FromColumn` references `To.ToColumn`. Keys are `schema.table`. */
33
+ export interface ErdEdge {
34
+ From: string;
35
+ To: string;
36
+ FromColumn: string;
37
+ ToColumn: string;
38
+ }
39
+ export interface ErdClusterPage {
40
+ /** 1-based page number within the cluster. */
41
+ Number: number;
42
+ /** `schema.table` keys on this page; the hub is always first. */
43
+ Tables: string[];
44
+ /** File name (without extension) every renderer uses for this page, unique across the plan. */
45
+ BaseName: string;
46
+ /** Page title, e.g. `Customer (2 of 5)`. */
47
+ Title: string;
48
+ }
49
+ export interface ErdCluster {
50
+ /** `schema.table` key of the hub table. */
51
+ Hub: string;
52
+ /** Display name of the hub table. */
53
+ HubName: string;
54
+ /** `schema.table` keys of every table in the cluster, hub first. */
55
+ Tables: string[];
56
+ Pages: ErdClusterPage[];
57
+ /** FK edges with both ends inside the cluster. */
58
+ InternalEdges: ErdEdge[];
59
+ /** FK edges leaving the cluster (From inside, To in another cluster). */
60
+ OutboundEdges: ErdEdge[];
61
+ /** FK edges entering the cluster (To inside, From in another cluster). */
62
+ InboundEdges: ErdEdge[];
63
+ /** Reference tables used by members of this cluster, with how many members use each. */
64
+ ReferenceTables: Array<{
65
+ Table: string;
66
+ UsedBy: number;
67
+ }>;
68
+ }
69
+ export type ErdClustererSettings = Required<Pick<ErdClustererOptions, 'hubMinInbound' | 'lookupMaxRows' | 'pageSize' | 'minClusterSize'>>;
70
+ export interface ErdClusterPlan {
71
+ Clusters: ErdCluster[];
72
+ /** Settings that named tables the plan could not use (an unknown or edge-less hub, an unknown exclusion). */
73
+ Warnings: string[];
74
+ /** Reference tables set aside before clustering, with how many tables reference each. */
75
+ ReferenceTables: Array<{
76
+ Table: string;
77
+ ReferencedBy: number;
78
+ }>;
79
+ /** Tables with no foreign keys in either direction. */
80
+ IsolatedTables: string[];
81
+ /** Connected tables that reached no hub (small chains with no hub of their own). */
82
+ UnassignedTables: string[];
83
+ /** Tables removed by `excludeTables`. */
84
+ ExcludedTables: string[];
85
+ TotalTables: number;
86
+ TotalEdges: number;
87
+ Options: ErdClustererSettings;
88
+ /** Display name for a table key: the bare table name, or `schema.table` when another schema has a table of that name. */
89
+ NameOf(key: string): string;
90
+ /** The table definition for a key. */
91
+ TableOf(key: string): TableDefinition;
92
+ }
93
+ export declare class ErdClusterer {
94
+ Plan(state: DatabaseDocumentation, options?: ErdClustererOptions): ErdClusterPlan;
95
+ /** Defaults fill the gaps; every count must be at least 1 or the pagination and hub selection degenerate. */
96
+ private resolveSettings;
97
+ /** Index the tables, resolve exclusions and reference tables, and collect the FK graph. */
98
+ private buildGraph;
99
+ /** Distinct FK edges between known tables (a table may reference another through several columns). */
100
+ private collectEdges;
101
+ /**
102
+ * Resolve an FK target to a key. `dep.table` is usually the bare name within `dep.schema`, which also
103
+ * covers a table name that contains a dot (`Customer.bak`); the LLM sometimes writes `schema.table`
104
+ * instead, which the second lookup accepts.
105
+ */
106
+ private resolveTarget;
107
+ /** A configured table name may be given as `schema.table` or as a bare name (any schema, case-insensitive). */
108
+ private resolveNamed;
109
+ private isReferenceTable;
110
+ private link;
111
+ private neighbours;
112
+ private selectHubs;
113
+ /** Multi-source breadth-first search: every reachable table belongs to the hub nearest to it. */
114
+ private assignToNearestHub;
115
+ /** Fold each cluster below the minimum size into the neighbouring cluster its members link to most. */
116
+ private foldUndersizedClusters;
117
+ /**
118
+ * Folding only moves a small cluster into a larger neighbour, so two undersized clusters that
119
+ * link only to each other stay as they are. Say so rather than silently ignoring minClusterSize.
120
+ */
121
+ private warnAboutUndersizedClusters;
122
+ private buildCluster;
123
+ /**
124
+ * File names are decided once here so every renderer links to the same page. Two hubs whose names
125
+ * sanitise to the same identifier (`Order-Item`, `Order_Item`) get a numeric suffix instead of
126
+ * overwriting each other.
127
+ */
128
+ private assignPageFileNames;
129
+ }
130
+ //# sourceMappingURL=ErdClusterer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErdClusterer.d.ts","sourceRoot":"","sources":["../../src/generators/ErdClusterer.ts"],"names":[],"mappings":"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"}