@softtechai/quickmcp 1.0.8

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 (163) hide show
  1. package/README.md +553 -0
  2. package/dist/client/MCPClient.d.ts +24 -0
  3. package/dist/client/MCPClient.d.ts.map +1 -0
  4. package/dist/client/MCPClient.js +211 -0
  5. package/dist/client/MCPClient.js.map +1 -0
  6. package/dist/client/MCPClientUnified.d.ts +31 -0
  7. package/dist/client/MCPClientUnified.d.ts.map +1 -0
  8. package/dist/client/MCPClientUnified.js +275 -0
  9. package/dist/client/MCPClientUnified.js.map +1 -0
  10. package/dist/client/MCPTestRunner.d.ts +44 -0
  11. package/dist/client/MCPTestRunner.d.ts.map +1 -0
  12. package/dist/client/MCPTestRunner.js +220 -0
  13. package/dist/client/MCPTestRunner.js.map +1 -0
  14. package/dist/client/MCPTestRunnerUnified.d.ts +48 -0
  15. package/dist/client/MCPTestRunnerUnified.d.ts.map +1 -0
  16. package/dist/client/MCPTestRunnerUnified.js +183 -0
  17. package/dist/client/MCPTestRunnerUnified.js.map +1 -0
  18. package/dist/database/json-manager.d.ts +55 -0
  19. package/dist/database/json-manager.d.ts.map +1 -0
  20. package/dist/database/json-manager.js +128 -0
  21. package/dist/database/json-manager.js.map +1 -0
  22. package/dist/database/sqlite-manager.d.ts +53 -0
  23. package/dist/database/sqlite-manager.d.ts.map +1 -0
  24. package/dist/database/sqlite-manager.js +193 -0
  25. package/dist/database/sqlite-manager.js.map +1 -0
  26. package/dist/dynamic-mcp-executor.d.ts +14 -0
  27. package/dist/dynamic-mcp-executor.d.ts.map +1 -0
  28. package/dist/dynamic-mcp-executor.js +274 -0
  29. package/dist/dynamic-mcp-executor.js.map +1 -0
  30. package/dist/generators/MCPServerGenerator-new.d.ts +37 -0
  31. package/dist/generators/MCPServerGenerator-new.d.ts.map +1 -0
  32. package/dist/generators/MCPServerGenerator-new.js +287 -0
  33. package/dist/generators/MCPServerGenerator-new.js.map +1 -0
  34. package/dist/generators/MCPServerGenerator.d.ts +42 -0
  35. package/dist/generators/MCPServerGenerator.d.ts.map +1 -0
  36. package/dist/generators/MCPServerGenerator.js +494 -0
  37. package/dist/generators/MCPServerGenerator.js.map +1 -0
  38. package/dist/generators/database/sqlite-manager.d.ts +52 -0
  39. package/dist/generators/database/sqlite-manager.js +143 -0
  40. package/dist/generators/generators/MCPServerGenerator.d.ts +37 -0
  41. package/dist/generators/generators/MCPServerGenerator.js +396 -0
  42. package/dist/index.d.ts +7 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +23 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/integrated-mcp-server-new.d.ts +12 -0
  47. package/dist/integrated-mcp-server-new.d.ts.map +1 -0
  48. package/dist/integrated-mcp-server-new.js +253 -0
  49. package/dist/integrated-mcp-server-new.js.map +1 -0
  50. package/dist/integrated-mcp-server.d.ts +25 -0
  51. package/dist/integrated-mcp-server.d.ts.map +1 -0
  52. package/dist/integrated-mcp-server.js +541 -0
  53. package/dist/integrated-mcp-server.js.map +1 -0
  54. package/dist/mcp-inspector-server.d.ts +3 -0
  55. package/dist/mcp-inspector-server.d.ts.map +1 -0
  56. package/dist/mcp-inspector-server.js +119 -0
  57. package/dist/mcp-inspector-server.js.map +1 -0
  58. package/dist/mcp-sdk-server.d.ts +3 -0
  59. package/dist/mcp-sdk-server.d.ts.map +1 -0
  60. package/dist/mcp-sdk-server.js +90 -0
  61. package/dist/mcp-sdk-server.js.map +1 -0
  62. package/dist/mcp-server.d.ts +3 -0
  63. package/dist/mcp-server.d.ts.map +1 -0
  64. package/dist/mcp-server.js +300 -0
  65. package/dist/mcp-server.js.map +1 -0
  66. package/dist/parsers/CsvParser.d.ts +7 -0
  67. package/dist/parsers/CsvParser.d.ts.map +1 -0
  68. package/dist/parsers/CsvParser.js +98 -0
  69. package/dist/parsers/CsvParser.js.map +1 -0
  70. package/dist/parsers/DatabaseParser.d.ts +18 -0
  71. package/dist/parsers/DatabaseParser.d.ts.map +1 -0
  72. package/dist/parsers/DatabaseParser.js +372 -0
  73. package/dist/parsers/DatabaseParser.js.map +1 -0
  74. package/dist/parsers/ExcelParser.d.ts +8 -0
  75. package/dist/parsers/ExcelParser.d.ts.map +1 -0
  76. package/dist/parsers/ExcelParser.js +119 -0
  77. package/dist/parsers/ExcelParser.js.map +1 -0
  78. package/dist/parsers/index.d.ts +13 -0
  79. package/dist/parsers/index.d.ts.map +1 -0
  80. package/dist/parsers/index.js +88 -0
  81. package/dist/parsers/index.js.map +1 -0
  82. package/dist/parsers/parsers/ExcelParser.js +118 -0
  83. package/dist/parsers/types/index.js +2 -0
  84. package/dist/quickmcp-unified-bridge.d.ts +13 -0
  85. package/dist/quickmcp-unified-bridge.d.ts.map +1 -0
  86. package/dist/quickmcp-unified-bridge.js +176 -0
  87. package/dist/quickmcp-unified-bridge.js.map +1 -0
  88. package/dist/server/ServerManager.d.ts +37 -0
  89. package/dist/server/ServerManager.d.ts.map +1 -0
  90. package/dist/server/ServerManager.js +376 -0
  91. package/dist/server/ServerManager.js.map +1 -0
  92. package/dist/sqlite-manager.js +145 -0
  93. package/dist/start-new-server.d.ts +3 -0
  94. package/dist/start-new-server.d.ts.map +1 -0
  95. package/dist/start-new-server.js +10 -0
  96. package/dist/start-new-server.js.map +1 -0
  97. package/dist/test-app.d.ts +2 -0
  98. package/dist/test-app.d.ts.map +1 -0
  99. package/dist/test-app.js +119 -0
  100. package/dist/test-app.js.map +1 -0
  101. package/dist/test-new-architecture.d.ts +3 -0
  102. package/dist/test-new-architecture.d.ts.map +1 -0
  103. package/dist/test-new-architecture.js +72 -0
  104. package/dist/test-new-architecture.js.map +1 -0
  105. package/dist/transport/base-transport.d.ts +21 -0
  106. package/dist/transport/base-transport.d.ts.map +1 -0
  107. package/dist/transport/base-transport.js +16 -0
  108. package/dist/transport/base-transport.js.map +1 -0
  109. package/dist/transport/index.d.ts +10 -0
  110. package/dist/transport/index.d.ts.map +1 -0
  111. package/dist/transport/index.js +12 -0
  112. package/dist/transport/index.js.map +1 -0
  113. package/dist/transport/sse-transport.d.ts +13 -0
  114. package/dist/transport/sse-transport.d.ts.map +1 -0
  115. package/dist/transport/sse-transport.js +106 -0
  116. package/dist/transport/sse-transport.js.map +1 -0
  117. package/dist/transport/stdio-transport.d.ts +8 -0
  118. package/dist/transport/stdio-transport.d.ts.map +1 -0
  119. package/dist/transport/stdio-transport.js +53 -0
  120. package/dist/transport/stdio-transport.js.map +1 -0
  121. package/dist/transport/streamable-http-transport.d.ts +15 -0
  122. package/dist/transport/streamable-http-transport.d.ts.map +1 -0
  123. package/dist/transport/streamable-http-transport.js +151 -0
  124. package/dist/transport/streamable-http-transport.js.map +1 -0
  125. package/dist/types/index.d.ts +64 -0
  126. package/dist/types/index.d.ts.map +1 -0
  127. package/dist/types/index.js +3 -0
  128. package/dist/types/index.js.map +1 -0
  129. package/dist/web/client/MCPClient.js +348 -0
  130. package/dist/web/client/MCPTestRunner.js +317 -0
  131. package/dist/web/database/json-manager.js +124 -0
  132. package/dist/web/database/sqlite-manager.js +146 -0
  133. package/dist/web/dynamic-mcp-executor.js +443 -0
  134. package/dist/web/generators/MCPServerGenerator-new.js +284 -0
  135. package/dist/web/generators/MCPServerGenerator.js +566 -0
  136. package/dist/web/integrated-mcp-server-new.js +394 -0
  137. package/dist/web/parsers/CsvParser.js +144 -0
  138. package/dist/web/parsers/DatabaseParser.js +637 -0
  139. package/dist/web/parsers/ExcelParser.js +180 -0
  140. package/dist/web/parsers/index.js +152 -0
  141. package/dist/web/server.d.ts +3 -0
  142. package/dist/web/server.d.ts.map +1 -0
  143. package/dist/web/server.js +790 -0
  144. package/dist/web/server.js.map +1 -0
  145. package/dist/web/types/index.js +2 -0
  146. package/dist/web/web/server.js +860 -0
  147. package/package.json +68 -0
  148. package/quickmcp-direct-stdio.js +328 -0
  149. package/src/web/public/app.js +1795 -0
  150. package/src/web/public/database-tables.html +711 -0
  151. package/src/web/public/how-to-use.html +571 -0
  152. package/src/web/public/how-to-use.js +255 -0
  153. package/src/web/public/images/1-claude-quickmcp-stdio.png +0 -0
  154. package/src/web/public/images/2-claude-tools.png +0 -0
  155. package/src/web/public/images/3-claude-developer-settings.png +0 -0
  156. package/src/web/public/images/4-claude-config.png +0 -0
  157. package/src/web/public/images/5-claude-config-edit.png +0 -0
  158. package/src/web/public/index.html +626 -0
  159. package/src/web/public/manage-servers.html +198 -0
  160. package/src/web/public/modern-styles.css +946 -0
  161. package/src/web/public/shared-styles.css +2091 -0
  162. package/src/web/public/shared.js +93 -0
  163. package/src/web/public/test-servers.html +302 -0
@@ -0,0 +1,711 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Database Tables - MCP Server Generator</title>
7
+ <link rel="stylesheet" href="shared-styles.css">
8
+ <style>
9
+ .table-grid {
10
+ display: grid;
11
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
12
+ gap: 1.5rem;
13
+ margin-top: 1rem;
14
+ }
15
+
16
+ .table-card {
17
+ background: var(--card-background);
18
+ border: 1px solid var(--border-color);
19
+ border-radius: 8px;
20
+ padding: 1.5rem;
21
+ transition: all 0.2s ease;
22
+ }
23
+
24
+ .table-card:hover {
25
+ transform: translateY(-2px);
26
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
27
+ }
28
+
29
+ .table-header {
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: space-between;
33
+ margin-bottom: 1rem;
34
+ }
35
+
36
+ .table-name {
37
+ font-size: 1.25rem;
38
+ font-weight: 600;
39
+ color: var(--text-primary);
40
+ margin: 0;
41
+ display: flex;
42
+ align-items: center;
43
+ gap: 0.5rem;
44
+ }
45
+
46
+ .table-icon {
47
+ font-size: 1.5rem;
48
+ }
49
+
50
+ .table-stats {
51
+ display: flex;
52
+ gap: 1rem;
53
+ margin-bottom: 1rem;
54
+ }
55
+
56
+ .stat-item {
57
+ display: flex;
58
+ flex-direction: column;
59
+ align-items: center;
60
+ gap: 0.25rem;
61
+ }
62
+
63
+ .stat-number {
64
+ font-size: 1.5rem;
65
+ font-weight: 700;
66
+ color: var(--primary-color);
67
+ }
68
+
69
+ .stat-label {
70
+ font-size: 0.75rem;
71
+ color: var(--text-secondary);
72
+ text-transform: uppercase;
73
+ letter-spacing: 0.5px;
74
+ }
75
+
76
+ .data-preview {
77
+ margin-top: 1rem;
78
+ }
79
+
80
+ .data-header {
81
+ font-size: 0.9rem;
82
+ font-weight: 600;
83
+ color: var(--text-primary);
84
+ margin-bottom: 0.5rem;
85
+ padding-bottom: 0.5rem;
86
+ border-bottom: 1px solid var(--border-color);
87
+ }
88
+
89
+ .data-grid {
90
+ overflow-x: auto;
91
+ margin-top: 0.5rem;
92
+ }
93
+
94
+ .data-table {
95
+ width: 100%;
96
+ border-collapse: collapse;
97
+ background: white;
98
+ border-radius: 8px;
99
+ overflow: hidden;
100
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
101
+ }
102
+
103
+ .data-table th {
104
+ background: var(--primary-color);
105
+ color: white;
106
+ padding: 0.75rem;
107
+ text-align: left;
108
+ font-weight: 600;
109
+ font-size: 0.85rem;
110
+ border: none;
111
+ }
112
+
113
+ .data-table td {
114
+ padding: 0.75rem;
115
+ border-bottom: 1px solid var(--border-light);
116
+ font-size: 0.85rem;
117
+ color: var(--text-primary);
118
+ max-width: 200px;
119
+ word-wrap: break-word;
120
+ }
121
+
122
+ .data-table tr:nth-child(even) {
123
+ background: var(--secondary-color);
124
+ }
125
+
126
+ .data-table tr:hover {
127
+ background: #e3f2fd;
128
+ }
129
+
130
+ .data-table tr:last-child td {
131
+ border-bottom: none;
132
+ }
133
+
134
+ .no-data {
135
+ text-align: center;
136
+ color: var(--text-secondary);
137
+ font-style: italic;
138
+ padding: 2rem;
139
+ background: var(--secondary-color);
140
+ border-radius: 6px;
141
+ }
142
+
143
+ .more-data {
144
+ text-align: center;
145
+ color: var(--text-secondary);
146
+ font-size: 0.9rem;
147
+ font-style: italic;
148
+ margin-top: 0.5rem;
149
+ }
150
+
151
+ .table-actions {
152
+ display: flex;
153
+ gap: 0.5rem;
154
+ margin-top: 1rem;
155
+ }
156
+
157
+ .btn-small {
158
+ font-size: 0.85rem;
159
+ padding: 0.5rem 1rem;
160
+ border: none;
161
+ border-radius: 4px;
162
+ cursor: pointer;
163
+ text-decoration: none;
164
+ display: inline-flex;
165
+ align-items: center;
166
+ gap: 0.5rem;
167
+ transition: all 0.2s ease;
168
+ }
169
+
170
+ .btn-view {
171
+ background: var(--primary-color);
172
+ color: white;
173
+ }
174
+
175
+ .btn-view:hover {
176
+ background: var(--primary-dark);
177
+ transform: translateY(-1px);
178
+ }
179
+
180
+ .btn-query {
181
+ background: var(--secondary-color);
182
+ color: var(--text-primary);
183
+ }
184
+
185
+ .btn-query:hover {
186
+ background: var(--secondary-dark);
187
+ transform: translateY(-1px);
188
+ }
189
+
190
+ .empty-state {
191
+ text-align: center;
192
+ padding: 3rem;
193
+ color: var(--text-secondary);
194
+ }
195
+
196
+ .empty-icon {
197
+ font-size: 4rem;
198
+ margin-bottom: 1rem;
199
+ opacity: 0.5;
200
+ }
201
+
202
+ .refresh-btn {
203
+ position: fixed;
204
+ bottom: 2rem;
205
+ right: 2rem;
206
+ width: 56px;
207
+ height: 56px;
208
+ border: none;
209
+ border-radius: 50%;
210
+ background: var(--primary-color);
211
+ color: white;
212
+ font-size: 1.5rem;
213
+ cursor: pointer;
214
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
215
+ transition: all 0.2s ease;
216
+ z-index: 100;
217
+ }
218
+
219
+ .refresh-btn:hover {
220
+ background: var(--primary-dark);
221
+ transform: scale(1.1);
222
+ }
223
+
224
+ .db-info {
225
+ background: var(--info-background);
226
+ border: 1px solid var(--info-border);
227
+ border-radius: 8px;
228
+ padding: 1rem;
229
+ margin-bottom: 2rem;
230
+ }
231
+
232
+ .db-path {
233
+ font-family: monospace;
234
+ font-size: 0.9rem;
235
+ color: var(--text-secondary);
236
+ word-break: break-all;
237
+ }
238
+
239
+ .tab-navigation {
240
+ display: flex;
241
+ border-bottom: 2px solid var(--border-color);
242
+ margin-bottom: 2rem;
243
+ gap: 0.5rem;
244
+ }
245
+
246
+ .tab-button {
247
+ background: none;
248
+ border: none;
249
+ padding: 1rem 1.5rem;
250
+ cursor: pointer;
251
+ border-bottom: 3px solid transparent;
252
+ font-size: 0.95rem;
253
+ font-weight: 500;
254
+ color: var(--text-secondary);
255
+ transition: all 0.2s ease;
256
+ border-radius: 8px 8px 0 0;
257
+ display: flex;
258
+ align-items: center;
259
+ gap: 0.5rem;
260
+ }
261
+
262
+ .tab-button:hover {
263
+ background: var(--secondary-color);
264
+ color: var(--text-primary);
265
+ }
266
+
267
+ .tab-button.active {
268
+ color: var(--primary-color);
269
+ border-bottom-color: var(--primary-color);
270
+ background: var(--secondary-color);
271
+ font-weight: 600;
272
+ }
273
+
274
+ .tab-content {
275
+ min-height: 400px;
276
+ }
277
+
278
+ .tab-panel {
279
+ display: none !important;
280
+ }
281
+
282
+ .tab-panel.active {
283
+ display: block !important;
284
+ }
285
+
286
+ .table-wrapper {
287
+ background: white;
288
+ border-radius: 8px;
289
+ overflow: hidden;
290
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
291
+ }
292
+
293
+ .table-header {
294
+ background: var(--primary-color);
295
+ color: white;
296
+ padding: 1rem;
297
+ font-weight: 600;
298
+ display: flex;
299
+ align-items: center;
300
+ gap: 0.5rem;
301
+ }
302
+
303
+ @media (max-width: 768px) {
304
+ .tab-navigation {
305
+ flex-direction: column;
306
+ gap: 0;
307
+ }
308
+
309
+ .tab-button {
310
+ border-radius: 0;
311
+ border-bottom: 1px solid var(--border-color);
312
+ border-right: 3px solid transparent;
313
+ padding: 0.75rem 1rem;
314
+ }
315
+
316
+ .tab-button.active {
317
+ border-bottom-color: var(--border-color);
318
+ border-right-color: var(--primary-color);
319
+ }
320
+
321
+ .refresh-btn {
322
+ bottom: 1rem;
323
+ right: 1rem;
324
+ }
325
+ }
326
+ </style>
327
+ </head>
328
+ <body>
329
+ <div class="main-layout">
330
+ <!-- Sidebar -->
331
+ <div class="sidebar" id="sidebar">
332
+ <div class="sidebar-header">
333
+ <div class="sidebar-logo">QM</div>
334
+ <div class="sidebar-title">QuickMCP</div>
335
+ </div>
336
+ <nav class="sidebar-nav">
337
+ <a href="/" class="sidebar-nav-item">
338
+ <div class="icon">🚀</div>
339
+ <span>Generate Server</span>
340
+ </a>
341
+ <a href="/manage-servers" class="sidebar-nav-item">
342
+ <div class="icon">📋</div>
343
+ <span>Manage Servers</span>
344
+ </a>
345
+ <a href="/test-servers" class="sidebar-nav-item">
346
+ <div class="icon">🧪</div>
347
+ <span>Test Servers</span>
348
+ </a>
349
+ <a href="/database-tables" class="sidebar-nav-item active">
350
+ <div class="icon">🗃️</div>
351
+ <span>Database Tables</span>
352
+ </a>
353
+ <a href="/how-to-use" class="sidebar-nav-item">
354
+ <div class="icon">📖</div>
355
+ <span>How to Use</span>
356
+ </a>
357
+ </nav>
358
+ </div>
359
+
360
+ <!-- Overlay for mobile -->
361
+ <div class="sidebar-overlay" id="sidebarOverlay" onclick="closeSidebar()"></div>
362
+
363
+ <!-- Main Content -->
364
+ <div class="main-content">
365
+ <div class="topbar">
366
+ <button class="hamburger" id="hamburger" onclick="toggleSidebar()">
367
+ <span></span>
368
+ <span></span>
369
+ <span></span>
370
+ </button>
371
+ <div class="topbar-title">
372
+ MCP Server Generator - Database Tables
373
+ </div>
374
+ </div>
375
+
376
+ <div class="container">
377
+ <div class="card">
378
+ <div class="card-header">
379
+ <h1 class="section-title">SQLite Database Tables</h1>
380
+ <p class="section-subtitle">Explore the internal database structure</p>
381
+ </div>
382
+ <div class="card-content">
383
+ <div class="db-info">
384
+ <h3 style="margin-top: 0;">Database Information</h3>
385
+ <div class="db-path" id="dbPath">Loading database path...</div>
386
+ <div style="margin-top: 0.5rem;">
387
+ <strong>Total Tables:</strong> <span id="tableCount">-</span>
388
+ </div>
389
+ </div>
390
+
391
+ <div id="tables-container">
392
+ <div class="loading" id="tablesLoading">Loading database tables...</div>
393
+
394
+ <div id="tables-tabs" style="display: none;">
395
+ <!-- Tab Navigation -->
396
+ <div class="tab-navigation">
397
+ <button class="tab-button active" data-table="servers" onclick="switchTab('servers')">
398
+ 🖥️ Servers (<span id="servers-count">0</span>)
399
+ </button>
400
+ <button class="tab-button" data-table="tools" onclick="switchTab('tools')">
401
+ 🔧 Tools (<span id="tools-count">0</span>)
402
+ </button>
403
+ <button class="tab-button" data-table="resources" onclick="switchTab('resources')">
404
+ 📦 Resources (<span id="resources-count">0</span>)
405
+ </button>
406
+ </div>
407
+
408
+ <!-- Tab Content -->
409
+ <div class="tab-content">
410
+ <div id="tab-servers" class="tab-panel active">
411
+ <!-- Servers table will be loaded here -->
412
+ </div>
413
+ <div id="tab-tools" class="tab-panel">
414
+ <!-- Tools table will be loaded here -->
415
+ </div>
416
+ <div id="tab-resources" class="tab-panel">
417
+ <!-- Resources table will be loaded here -->
418
+ </div>
419
+ </div>
420
+ </div>
421
+ </div>
422
+ </div>
423
+ </div>
424
+ </div>
425
+ </div>
426
+ </div>
427
+
428
+ <!-- Table Details Modal -->
429
+ <div id="tableDetailsModal" class="modal" style="display: none;">
430
+ <div class="modal-content">
431
+ <div class="modal-header">
432
+ <h2 id="tableModalTitle">Table Details</h2>
433
+ <button class="modal-close" onclick="closeTableDetailsModal()">&times;</button>
434
+ </div>
435
+ <div class="modal-body" id="tableModalBody">
436
+ <!-- Table details will be loaded here -->
437
+ </div>
438
+ </div>
439
+ <div class="modal-overlay" onclick="closeTableDetailsModal()"></div>
440
+ </div>
441
+
442
+ <!-- Refresh Button -->
443
+ <button class="refresh-btn" onclick="loadTables()" title="Refresh Tables">
444
+ 🔄
445
+ </button>
446
+
447
+ <script src="shared.js"></script>
448
+ <script>
449
+ // Load tables when page loads
450
+ document.addEventListener('DOMContentLoaded', function() {
451
+ loadTables();
452
+ });
453
+
454
+ // Load database tables
455
+ async function loadTables() {
456
+ const loading = document.getElementById('tablesLoading');
457
+ const tabsContainer = document.getElementById('tables-tabs');
458
+
459
+ loading.style.display = 'block';
460
+ tabsContainer.style.display = 'none';
461
+
462
+ try {
463
+ const response = await fetch('/api/database/tables');
464
+ const result = await response.json();
465
+
466
+ if (result.success) {
467
+ displayTables(result.data.tables);
468
+ updateDatabaseInfo(result.data);
469
+ } else {
470
+ throw new Error(result.error || 'Failed to load tables');
471
+ }
472
+ } catch (error) {
473
+ console.error('Error loading tables:', error);
474
+ tabsContainer.innerHTML = `
475
+ <div class="empty-state">
476
+ <div class="empty-icon">❌</div>
477
+ <h3>Failed to Load Tables</h3>
478
+ <p>Error: ${error.message}</p>
479
+ <button class="btn btn-primary" onclick="loadTables()">Retry</button>
480
+ </div>
481
+ `;
482
+ tabsContainer.style.display = 'block';
483
+ } finally {
484
+ loading.style.display = 'none';
485
+ }
486
+ }
487
+
488
+ // Update database info
489
+ function updateDatabaseInfo(data) {
490
+ document.getElementById('dbPath').textContent = data.dbPath || 'Unknown';
491
+ document.getElementById('tableCount').textContent = data.tables.length;
492
+ }
493
+
494
+ // Display tables in tab format
495
+ function displayTables(tables) {
496
+ const tabsContainer = document.getElementById('tables-tabs');
497
+
498
+ if (tables.length === 0) {
499
+ tabsContainer.innerHTML = `
500
+ <div class="empty-state">
501
+ <div class="empty-icon">🗃️</div>
502
+ <h3>No Tables Found</h3>
503
+ <p>The database appears to be empty or not initialized.</p>
504
+ </div>
505
+ `;
506
+ return;
507
+ }
508
+
509
+ // Update counts in tab buttons
510
+ tables.forEach(table => {
511
+ const countSpan = document.getElementById(`${table.name}-count`);
512
+ if (countSpan) {
513
+ countSpan.textContent = table.rowCount || 0;
514
+ }
515
+ });
516
+
517
+ // Display each table in its tab panel
518
+ tables.forEach(table => {
519
+ const tabPanel = document.getElementById(`tab-${table.name}`);
520
+ if (tabPanel) {
521
+ tabPanel.innerHTML = generateTableHTML(table);
522
+ }
523
+ });
524
+
525
+ tabsContainer.style.display = 'block';
526
+ }
527
+
528
+ // Generate HTML for a single table
529
+ function generateTableHTML(table) {
530
+ if (!table.sampleData || table.sampleData.length === 0) {
531
+ return `
532
+ <div class="table-wrapper">
533
+ <div class="table-header">
534
+ <span class="table-icon">${getTableIcon(table.name)}</span>
535
+ ${table.name} - No data available
536
+ </div>
537
+ <div class="no-data" style="padding: 3rem;">
538
+ <div>This table is empty</div>
539
+ </div>
540
+ </div>
541
+ `;
542
+ }
543
+
544
+ return `
545
+ <div class="table-wrapper">
546
+ <div class="table-header">
547
+ <span class="table-icon">${getTableIcon(table.name)}</span>
548
+ ${table.name} (${table.rowCount} rows, ${table.columns.length} columns)
549
+ </div>
550
+ <div class="data-grid" style="max-height: 500px; overflow-y: auto;">
551
+ <table class="data-table" style="margin: 0;">
552
+ <thead style="position: sticky; top: 0; z-index: 10;">
553
+ <tr>
554
+ ${table.columns.map(col => `<th>${col.name}</th>`).join('')}
555
+ </tr>
556
+ </thead>
557
+ <tbody>
558
+ ${table.sampleData.map(row => `
559
+ <tr>
560
+ ${table.columns.map(col => `
561
+ <td>${row[col.name] !== null && row[col.name] !== undefined ?
562
+ (typeof row[col.name] === 'string' && row[col.name].length > 100 ?
563
+ row[col.name].substring(0, 100) + '...' :
564
+ row[col.name]) : '<em>NULL</em>'}</td>
565
+ `).join('')}
566
+ </tr>
567
+ `).join('')}
568
+ </tbody>
569
+ </table>
570
+ </div>
571
+ ${table.sampleData.length >= 5 ? `
572
+ <div style="padding: 1rem; background: var(--secondary-color); text-align: center; color: var(--text-secondary);">
573
+ Showing first ${table.sampleData.length} rows of ${table.rowCount} total
574
+ </div>
575
+ ` : ''}
576
+ </div>
577
+ `;
578
+ }
579
+
580
+ // Switch between tabs
581
+ function switchTab(tableName) {
582
+ // Update tab buttons
583
+ document.querySelectorAll('.tab-button').forEach(btn => {
584
+ btn.classList.remove('active');
585
+ });
586
+ document.querySelector(`[data-table="${tableName}"]`).classList.add('active');
587
+
588
+ // Update tab panels
589
+ document.querySelectorAll('.tab-panel').forEach(panel => {
590
+ panel.classList.remove('active');
591
+ });
592
+ document.getElementById(`tab-${tableName}`).classList.add('active');
593
+ }
594
+
595
+ // Get table icon based on table name
596
+ function getTableIcon(tableName) {
597
+ switch(tableName.toLowerCase()) {
598
+ case 'servers': return '🖥️';
599
+ case 'tools': return '🔧';
600
+ case 'resources': return '📦';
601
+ default: return '📋';
602
+ }
603
+ }
604
+
605
+ // View table details
606
+ async function viewTableDetails(tableName) {
607
+ const modal = document.getElementById('tableDetailsModal');
608
+ const title = document.getElementById('tableModalTitle');
609
+ const body = document.getElementById('tableModalBody');
610
+
611
+ title.textContent = `Table: ${tableName}`;
612
+ body.innerHTML = '<div class="loading">Loading table details...</div>';
613
+ modal.style.display = 'block';
614
+
615
+ try {
616
+ const response = await fetch(`/api/database/tables/${tableName}`);
617
+ const result = await response.json();
618
+
619
+ if (result.success) {
620
+ displayTableDetails(result.data);
621
+ } else {
622
+ throw new Error(result.error || 'Failed to load table details');
623
+ }
624
+ } catch (error) {
625
+ console.error('Error loading table details:', error);
626
+ body.innerHTML = `<div class="error">Failed to load table details: ${error.message}</div>`;
627
+ }
628
+ }
629
+
630
+ // Display table details
631
+ function displayTableDetails(data) {
632
+ const body = document.getElementById('tableModalBody');
633
+
634
+ let detailsHtml = `
635
+ <div class="table-details">
636
+ <div class="info-section">
637
+ <h3>Table Information</h3>
638
+ <div class="info-grid">
639
+ <div><strong>Name:</strong> ${data.name}</div>
640
+ <div><strong>Columns:</strong> ${data.columns.length}</div>
641
+ <div><strong>Row Count:</strong> ${data.rowCount}</div>
642
+ </div>
643
+ </div>
644
+
645
+ <div class="info-section">
646
+ <h3>Column Schema</h3>
647
+ <div class="schema-table">
648
+ <table style="width: 100%; border-collapse: collapse;">
649
+ <thead>
650
+ <tr style="background: var(--secondary-color);">
651
+ <th style="padding: 0.75rem; border: 1px solid var(--border-color); text-align: left;">Column</th>
652
+ <th style="padding: 0.75rem; border: 1px solid var(--border-color); text-align: left;">Type</th>
653
+ <th style="padding: 0.75rem; border: 1px solid var(--border-color); text-align: left;">Not Null</th>
654
+ <th style="padding: 0.75rem; border: 1px solid var(--border-color); text-align: left;">Primary Key</th>
655
+ </tr>
656
+ </thead>
657
+ <tbody>
658
+ ${data.columns.map(column => `
659
+ <tr>
660
+ <td style="padding: 0.75rem; border: 1px solid var(--border-color); font-family: monospace;">${column.name}</td>
661
+ <td style="padding: 0.75rem; border: 1px solid var(--border-color);">${column.type}</td>
662
+ <td style="padding: 0.75rem; border: 1px solid var(--border-color);">${column.notnull ? '✅' : '❌'}</td>
663
+ <td style="padding: 0.75rem; border: 1px solid var(--border-color);">${column.pk ? '🔑' : '❌'}</td>
664
+ </tr>
665
+ `).join('')}
666
+ </tbody>
667
+ </table>
668
+ </div>
669
+ </div>
670
+ `;
671
+
672
+ if (data.sampleData && data.sampleData.length > 0) {
673
+ detailsHtml += `
674
+ <div class="info-section">
675
+ <h3>Sample Data (First 10 rows)</h3>
676
+ <div style="overflow-x: auto;">
677
+ <table style="width: 100%; border-collapse: collapse; min-width: 500px;">
678
+ <thead>
679
+ <tr style="background: var(--secondary-color);">
680
+ ${data.columns.map(col => `<th style="padding: 0.5rem; border: 1px solid var(--border-color); text-align: left; font-size: 0.9rem;">${col.name}</th>`).join('')}
681
+ </tr>
682
+ </thead>
683
+ <tbody>
684
+ ${data.sampleData.map(row => `
685
+ <tr>
686
+ ${data.columns.map(col => `
687
+ <td style="padding: 0.5rem; border: 1px solid var(--border-color); font-size: 0.85rem; max-width: 200px; word-wrap: break-word;">
688
+ ${row[col.name] !== null && row[col.name] !== undefined ? row[col.name] : '<em>NULL</em>'}
689
+ </td>
690
+ `).join('')}
691
+ </tr>
692
+ `).join('')}
693
+ </tbody>
694
+ </table>
695
+ </div>
696
+ </div>
697
+ `;
698
+ }
699
+
700
+ detailsHtml += '</div>';
701
+ body.innerHTML = detailsHtml;
702
+ }
703
+
704
+ // Close table details modal
705
+ function closeTableDetailsModal() {
706
+ document.getElementById('tableDetailsModal').style.display = 'none';
707
+ }
708
+
709
+ </script>
710
+ </body>
711
+ </html>