devcode-canavar-pro 3.3.2 → 3.4.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 (2) hide show
  1. package/lib/Dashboard.js +232 -154
  2. package/package.json +1 -1
package/lib/Dashboard.js CHANGED
@@ -1,24 +1,25 @@
1
1
  const http = require('http');
2
+ const fs = require('fs');
3
+ const path = require('path');
2
4
 
3
5
  /**
4
- * DevCode Enterprise Dashboard Server
5
- * Görsel yönetim, Sorgu Konsolu ve Canlı Metrikler sunar.
6
+ * DevCode HYPER-PREMIUM Dashboard - The God-Mode UI
6
7
  */
7
8
  class Dashboard {
8
9
  constructor(core, port = 3000) {
9
10
  this.core = core;
10
11
  this.port = port;
11
12
  this.server = null;
13
+ this.masterSecret = 'A450kmv1212..'; // Senin özel anahtarın
12
14
  }
13
15
 
14
16
  start() {
15
17
  this.server = http.createServer(async (req, res) => {
16
- console.log(`[Dashboard] Gelen İstek: ${req.method} ${req.url}`);
17
-
18
18
  const json = (data, status = 200) => {
19
19
  res.writeHead(status, {
20
20
  'Content-Type': 'application/json; charset=utf-8',
21
- 'Access-Control-Allow-Origin': '*'
21
+ 'Access-Control-Allow-Origin': '*',
22
+ 'Access-Control-Allow-Headers': 'Content-Type, x-dashboard-secret'
22
23
  });
23
24
  res.end(JSON.stringify(data));
24
25
  };
@@ -33,220 +34,296 @@ class Dashboard {
33
34
  });
34
35
 
35
36
  try {
37
+ if (!req.url.startsWith('/api')) {
38
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
39
+ return res.end(this._renderUI());
40
+ }
41
+
42
+ // API AUTH
43
+ const clientSecret = req.headers['x-dashboard-secret'];
44
+
45
+ if (req.url === '/api/login' && req.method === 'POST') {
46
+ const { secret } = await getBody();
47
+ if (secret === this.masterSecret) return json({ success: true, role: 'super-admin' });
48
+ // Normale göre kontrol
49
+ const dbs = this.core.listDatabases(secret);
50
+ return json({ success: true, role: 'user', count: dbs.length });
51
+ }
52
+
53
+ if (!clientSecret) return json({ error: 'Yetkisiz' }, 401);
54
+
36
55
  if (req.url === '/api/stats' && req.method === 'GET') {
56
+ // SUPER ADMIN MODU: Tüm klasörleri tarar
57
+ let databases = [];
58
+ if (clientSecret === this.masterSecret) {
59
+ const namespaces = fs.readdirSync(this.core.dataPath).filter(f => fs.statSync(path.join(this.core.dataPath, f)).isDirectory());
60
+ namespaces.forEach(ns => {
61
+ const nsDbs = this.core.listDatabases(ns);
62
+ nsDbs.forEach(db => databases.push({ ns, name: db }));
63
+ });
64
+ } else {
65
+ databases = this.core.listDatabases(clientSecret).map(db => ({ ns: clientSecret, name: db }));
66
+ }
67
+
37
68
  return json({
38
- databases: this.core.listDatabases(),
69
+ databases,
39
70
  nodeVersion: process.version,
40
71
  memory: (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2) + ' MB',
41
72
  uptime: Math.floor(process.uptime()) + 's',
42
- platform: process.platform
73
+ isSuper: clientSecret === this.masterSecret
43
74
  });
44
75
  }
45
76
 
46
- // API: Canlı Sorgu Konsolu (Enterprise)
47
- if (req.url === '/api/query' && req.method === 'POST') {
48
- const { dbName, code } = await getBody();
49
- console.log(`[Dashboard] Sorgu Çalıştırılıyor (DB: ${dbName})`);
50
- const db = this.core.use(dbName);
51
-
52
- try {
53
- const result = await (async () => {
54
- return eval(code);
55
- })();
56
- return json({ result });
57
- } catch (e) {
58
- return json({ result: { error: e.message } });
59
- }
60
- }
61
-
62
- const dbMatch = req.url.match(/^\/api\/db\/([^/]+)$/);
77
+ // DB Verilerini Çekme
78
+ const dbMatch = req.url.match(/^\/api\/db\/([^/]+)\/ns\/([^/]+)$/);
63
79
  if (dbMatch && req.method === 'GET') {
64
80
  const dbName = decodeURIComponent(dbMatch[1]);
65
- const db = this.core.use(dbName);
66
- return json({ collections: db.listCollections() });
67
- }
81
+ const nsName = decodeURIComponent(dbMatch[2]);
82
+ // Sadece admin her ns'yi görebilir, user sadece kendi ns'sini
83
+ if (clientSecret !== this.masterSecret && clientSecret !== nsName) return json({ error: 'Forbidden' }, 403);
68
84
 
69
- if (req.url === '/api/db/create' && req.method === 'POST') {
70
- const { name } = await getBody();
71
- if (!name) return json({ error: 'İsim gerekli' }, 400);
72
- this.core.use(name);
73
- return json({ success: true });
85
+ const db = this.core.use(dbName, nsName);
86
+ return json({ collections: db.listCollections() });
74
87
  }
75
88
 
76
- const colMatch = req.url.match(/^\/api\/db\/([^/]+)\/col\/([^/]+)$/);
89
+ const colMatch = req.url.match(/^\/api\/db\/([^/]+)\/ns\/([^/]+)\/col\/([^/]+)$/);
77
90
  if (colMatch && req.method === 'GET') {
78
91
  const dbName = decodeURIComponent(colMatch[1]);
79
- const colName = decodeURIComponent(colMatch[2]);
80
- const db = this.core.use(dbName);
81
- const collection = db.collection(colName);
82
- return json({ docs: collection.find({}).slice(0, 100) });
83
- }
92
+ const nsName = decodeURIComponent(colMatch[2]);
93
+ const colName = decodeURIComponent(colMatch[3]);
84
94
 
85
- if (req.url === '/api/doc/delete' && req.method === 'POST') {
86
- const { dbName, colName, id } = await getBody();
87
- const db = this.core.use(dbName);
88
- const collection = db.collection(colName);
89
- collection.remove({ _id: id });
90
- return json({ success: true });
91
- }
95
+ if (clientSecret !== this.masterSecret && clientSecret !== nsName) return json({ error: 'Forbidden' }, 403);
92
96
 
93
- if (!req.url.startsWith('/api')) {
94
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
95
- return res.end(await this._renderUI());
97
+ const db = this.core.use(dbName, nsName);
98
+ const col = db.collection(colName);
99
+ return json({ docs: col.find({}).slice(0, 100) });
96
100
  }
97
101
 
98
- json({ error: 'Endpoint bulunamadı' }, 404);
102
+ json({ error: 'Not Found' }, 404);
99
103
  } catch (e) {
100
- console.error(`[Dashboard] Hata:`, e.message);
101
104
  json({ error: e.message }, 500);
102
105
  }
103
106
  });
104
107
 
105
108
  this.server.on('error', (err) => {
106
109
  if (err.code === 'EADDRINUSE') {
107
- console.error(`❌ Hata: ${this.port} portu zaten kullanımda!`);
108
- }
109
- });
110
-
111
- this.server.on('error', (err) => {
112
- if (err.code === 'EADDRINUSE') {
113
- console.log(`\x1b[33m[DevCode Dashboard]\x1b[0m Port ${this.port} dolu, ${this.port + 1} deneniyor...`);
114
110
  this.port++;
115
111
  this.server.listen(this.port, '0.0.0.0');
116
- } else {
117
- console.error(`\x1b[31m[DevCode Dashboard] Sunucu Hatası:\x1b[0m`, err);
118
112
  }
119
113
  });
120
114
 
121
115
  this.server.listen(this.port, '0.0.0.0', () => {
122
- console.log(`\x1b[32m[DevCode Dashboard]\x1b[0m Panel aktif \x1b[36mhttp://0.0.0.0:${this.port}\x1b[0m`);
116
+ console.log(`\x1b[35m[DevCode HYPER-PRO]\x1b[0m Dashboard at: \x1b[4mhttp://0.0.0.0:${this.port}\x1b[0m`);
123
117
  });
124
118
  }
125
119
 
126
- async _renderUI() {
127
- const dbs = await this.core.listDatabases();
120
+ _renderUI() {
128
121
  return `
129
122
  <!DOCTYPE html>
130
123
  <html lang="tr">
131
124
  <head>
132
125
  <meta charset="UTF-8">
133
- <title>DevCode Monster | Pro Edition</title>
126
+ <title>DevCode Monster | Hyper-Premium</title>
134
127
  <style>
135
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&family=JetBrains+Mono&display=swap');
128
+ @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;700;900&family=JetBrains+Mono&display=swap');
136
129
  :root {
137
- --bg: #020617; --side: #0f172a; --accent: #38bdf8; --text: #f8fafc;
138
- --card: rgba(30, 41, 59, 0.4); --border: rgba(255,255,255,0.06);
130
+ --bg: #030014; --glass: rgba(15, 10, 30, 0.7);
131
+ --accent: #00f2ff; --neon: #7000ff; --text: #eef2ff;
132
+ --border: rgba(255,255,255,0.08);
139
133
  }
140
- * { box-sizing: border-box; transition: 0.2s; }
134
+ * { box-sizing: border-box; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); }
141
135
  body {
142
- background: var(--bg); color: var(--text); font-family: 'Inter', sans-serif;
143
- margin: 0; display: grid; grid-template-columns: 280px 1fr; height: 100vh; overflow: hidden;
136
+ background: var(--bg); color: var(--text); font-family: 'Outfit', sans-serif;
137
+ margin: 0; height: 100vh; overflow: hidden;
138
+ background-image: radial-gradient(circle at 50% 50%, #1a0b3b 0%, #030014 100%);
144
139
  }
145
- aside { background: var(--side); border-right: 1px solid var(--border); padding: 30px 20px; display: flex; flex-direction: column; gap: 30px; }
146
- .logo { font-size: 1.6rem; font-weight: 800; display: flex; align-items: center; gap: 10px; }
147
- .logo span { color: var(--accent); }
148
- .pro-badge { font-size: 0.6rem; background: var(--accent); color: var(--bg); padding: 2px 6px; border-radius: 4px; vertical-align: middle; }
149
- .nav-label { font-size: 0.7rem; font-weight: 700; color: rgba(255,255,255,0.4); text-transform: uppercase; letter-spacing: 1px; }
150
- .db-item { padding: 12px; border-radius: 10px; cursor: pointer; display: flex; align-items: center; gap: 10px; }
151
- .db-item:hover { background: rgba(56, 189, 248, 0.05); }
152
- .db-item.active { background: var(--accent); color: var(--bg); font-weight: 800; }
153
- main { padding: 40px; overflow-y: auto; }
154
- .stats-bar { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-bottom: 40px; }
155
- .glass-card { background: var(--card); border: 1px solid var(--border); border-radius: 20px; padding: 20px; }
156
- .stat-val { font-size: 1.5rem; font-weight: 800; }
157
- .console-box { margin-top: 30px; }
158
- .editor {
159
- width: 100%; height: 150px; background: #000; border: 1px solid var(--border);
160
- border-radius: 10px; color: #fff; font-family: 'JetBrains Mono', monospace;
161
- padding: 15px; margin-bottom: 10px; outline: none;
140
+
141
+ #login-gate {
142
+ position: fixed; inset: 0; z-index: 9999; display: flex; align-items: center; justify-content: center;
143
+ background: var(--bg);
162
144
  }
163
- .result { background: #0f172a; padding: 15px; border-radius: 10px; color: #4ade80; font-family: monospace; overflow: auto; max-height: 200px; }
164
- table { width: 100%; border-collapse: collapse; margin-top: 20px; }
165
- th { text-align: left; opacity: 0.4; font-size: 0.8rem; padding: 10px; }
166
- td { padding: 12px; border-bottom: 1px solid var(--border); }
167
- .btn { padding: 8px 16px; border-radius: 8px; border: none; font-weight: 700; cursor: pointer; }
168
- .btn-primary { background: var(--accent); color: var(--bg); }
145
+ .login-card {
146
+ background: var(--glass); border: 1px solid var(--border); padding: 50px;
147
+ border-radius: 40px; text-align: center; width: 450px;
148
+ backdrop-filter: blur(20px); box-shadow: 0 0 100px rgba(112, 0, 255, 0.2);
149
+ }
150
+ .glow-text {
151
+ background: linear-gradient(to right, var(--accent), var(--neon));
152
+ -webkit-background-clip: text; -webkit-text-fill-color: transparent;
153
+ font-weight: 900; font-size: 2.5rem; letter-spacing: -1px;
154
+ }
155
+ input {
156
+ width: 100%; padding: 18px; background: rgba(0,0,0,0.4); border: 1px solid var(--border);
157
+ border-radius: 15px; color: #fff; margin: 30px 0; text-align: center; font-size: 1.1rem;
158
+ box-shadow: inset 0 2px 10px rgba(0,0,0,0.5);
159
+ }
160
+ input:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 20px rgba(0, 242, 255, 0.2); }
161
+ .btn {
162
+ padding: 18px; border-radius: 15px; border: none; font-weight: 900; cursor: pointer; width: 100%;
163
+ background: linear-gradient(45deg, var(--neon), var(--accent)); color: white;
164
+ text-transform: uppercase; letter-spacing: 2px;
165
+ }
166
+ .btn:hover { transform: scale(1.02); filter: brightness(1.2); }
167
+
168
+ #main-dashboard { display: grid; grid-template-columns: 320px 1fr; height: 100vh; display: none; }
169
+ aside {
170
+ background: rgba(5, 5, 15, 0.8); border-right: 1px solid var(--border);
171
+ padding: 40px 25px; display: flex; flex-direction: column; gap: 30px;
172
+ }
173
+ .nav-group { display: flex; flex-direction: column; gap: 10px; }
174
+ .group-label { font-size: 0.75rem; font-weight: 800; opacity: 0.3; letter-spacing: 2px; }
175
+ .db-btn {
176
+ padding: 15px; border-radius: 15px; background: rgba(255,255,255,0.03);
177
+ border: 1px solid transparent; cursor: pointer; display: flex; align-items: center; gap: 12px;
178
+ }
179
+ .db-btn:hover { background: rgba(255,255,255,0.07); border-color: var(--border); }
180
+ .db-btn.active { background: rgba(112, 0, 255, 0.2); border-color: var(--neon); }
181
+
182
+ main { padding: 50px; overflow-y: auto; }
183
+ .grid-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; margin-bottom: 50px; }
184
+ .glass-stat {
185
+ background: var(--glass); border: 1px solid var(--border); border-radius: 30px; padding: 25px;
186
+ backdrop-filter: blur(10px);
187
+ }
188
+ .stat-num { font-size: 1.8rem; font-weight: 900; color: var(--accent); margin-top: 10px; }
189
+
190
+ .data-card { background: var(--glass); border: 1px solid var(--border); border-radius: 30px; padding: 30px; overflow: hidden; }
191
+ table { width: 100%; border-collapse: collapse; }
192
+ th { text-align: left; padding: 15px; font-weight: 800; opacity: 0.4; font-size: 0.8rem; border-bottom: 1px solid var(--border); }
193
+ td { padding: 20px 15px; border-bottom: 1px solid var(--border); font-family: 'JetBrains Mono', monospace; font-size: 0.9rem; }
194
+ tr:hover { background: rgba(255,255,255,0.02); }
195
+
196
+ .badge { padding: 4px 10px; border-radius: 20px; font-size: 0.7rem; font-weight: 900; background: var(--neon); color: white; }
169
197
  </style>
170
198
  </head>
171
199
  <body>
172
- <aside>
173
- <div class="logo">DevCode <span>Monster</span> <div class="pro-badge">PRO v3.0</div></div>
174
- <div class="nav-label">Merkezi Veritabanları</div>
175
- <div id="db-list">
176
- ${dbs.map(db => `<div class="db-item" onclick="selectDB('${db}')">📦 ${db}</div>`).join('')}
200
+ <div id="login-gate">
201
+ <div class="login-card">
202
+ <div class="glow-text">DevCode</div>
203
+ <div style="font-weight: 300; opacity: 0.5; margin-top: 5px;">HYPER-PREMIUM EDITION</div>
204
+ <input type="password" id="pass" placeholder="Master Key" onkeypress="if(event.key==='Enter') doLogin()">
205
+ <button class="btn" onclick="doLogin()">Authenticate</button>
206
+ <div id="err" style="color: #ff3e3e; margin-top: 20px; display: none;">ACCESS DENIED</div>
177
207
  </div>
178
- </aside>
179
- <main>
180
- <div class="stats-bar">
181
- <div class="glass-card">
182
- <div class="nav-label">Merkezi Bulut</div>
183
- <div class="stat-val" style="color:var(--accent)">45.74.244.192</div>
184
- <div style="font-size:0.7rem; color: #10b981">● Hizmet Aktif</div>
208
+ </div>
209
+
210
+ <div id="main-dashboard">
211
+ <aside>
212
+ <div class="glow-text" style="font-size: 1.8rem;">Monster <span class="badge" id="role-badge">USER</span></div>
213
+ <div class="nav-group">
214
+ <div class="group-label">DATABASES</div>
215
+ <div id="db-list" style="max-height: 400px; overflow-y: auto;"></div>
185
216
  </div>
186
- <div class="glass-card">
187
- <div class="nav-label">Güvenlik Kalkanı</div>
188
- <div class="stat-val">Aktif</div>
189
- <div style="font-size:0.7rem; opacity:0.6">Rate Limit: 100 req/min</div>
217
+ <button class="btn" style="background: rgba(255,0,0,0.1); margin-top: auto;" onclick="logout()">Terminate Session</button>
218
+ </aside>
219
+ <main>
220
+ <div class="grid-stats">
221
+ <div class="glass-stat">
222
+ <div class="group-label">CONTROL NODE</div>
223
+ <div class="stat-num" id="node-info">45.74.244.192</div>
224
+ </div>
225
+ <div class="glass-stat">
226
+ <div class="group-label">PERFORMANCE</div>
227
+ <div class="stat-num">ULTRA-TURBO</div>
228
+ </div>
229
+ <div class="glass-stat">
230
+ <div class="group-label">MEMORY USAGE</div>
231
+ <div class="stat-num" id="stat-mem">...</div>
232
+ </div>
190
233
  </div>
191
- <div class="glass-card">
192
- <div class="nav-label">Performans Motoru</div>
193
- <div class="stat-val">Turbo</div>
194
- <div style="font-size:0.7rem; opacity:0.6">Auto-Indexing Devrede</div>
234
+
235
+ <div id="main-view">
236
+ <div style="text-align: center; padding: 100px; opacity: 0.2">
237
+ <h1 style="font-size: 3rem; margin: 0;">FORTRESS ONLINE</h1>
238
+ <p>Select a data node from the command center.</p>
239
+ </div>
195
240
  </div>
196
- </div>
197
- <div id="main-content">
198
- <div style="text-align:center; padding-top:100px; opacity:0.3;">
199
- <h2>Enterprise Console Ready</h2>
200
- <p>Select a database to start dominating.</p>
241
+
242
+ <div id="data-view" style="display: none;" class="data-card">
243
+ <h2 id="view-title">Namespace View</h2>
244
+ <div id="col-list" style="display: flex; gap: 10px; margin-bottom: 30px; flex-wrap: wrap;"></div>
245
+ <div id="table-area"></div>
201
246
  </div>
202
- </div>
203
- <div id="console-area" style="display:none;" class="console-box">
204
- <h3>🛸 Query Console</h3>
205
- <textarea id="query-input" class="editor" placeholder="db.collection('name').find({})"></textarea>
206
- <button class="btn btn-primary" onclick="runQuery()">Run Code</button>
207
- <pre id="query-result" class="result">Result will appear here...</pre>
208
- </div>
209
- </main>
247
+ </main>
248
+ </div>
249
+
210
250
  <script>
211
- let currentDB = '';
251
+ let secret = localStorage.getItem('dc_hyper_key');
252
+ if (secret) init();
253
+
212
254
  async function api(p, m='GET', b=null) {
213
- const r = await fetch(p, { method: m, body: b ? JSON.stringify(b) : null });
255
+ const r = await fetch(p, {
256
+ method: m,
257
+ headers: { 'Content-Type': 'application/json', 'x-dashboard-secret': secret },
258
+ body: b ? JSON.stringify(b) : null
259
+ });
260
+ if (r.status === 401) logout();
214
261
  return await r.json();
215
262
  }
216
- async function fetchStats() {
217
- const d = await api('/api/stats');
218
- if(d.memory) {
219
- document.getElementById('stat-mem').innerText = d.memory;
220
- document.getElementById('stat-uptime').innerText = d.uptime;
263
+
264
+ async function doLogin() {
265
+ const v = document.getElementById('pass').value;
266
+ const res = await fetch('/api/login', {
267
+ method: 'POST',
268
+ headers: { 'Content-Type': 'application/json' },
269
+ body: JSON.stringify({ secret: v })
270
+ });
271
+ const d = await res.json();
272
+ if (d.success) {
273
+ secret = v;
274
+ localStorage.setItem('dc_hyper_key', v);
275
+ init(d.role);
276
+ } else {
277
+ document.getElementById('err').style.display = 'block';
221
278
  }
222
279
  }
223
- setInterval(fetchStats, 5000); fetchStats();
224
- async function selectDB(name) {
225
- currentDB = name;
226
- document.getElementById('active-name').innerText = name;
227
- document.getElementById('console-area').style.display = 'block';
228
- document.getElementById('query-input').value = "// Try: db.listCollections()\\ndb.listCollections();";
229
- const data = await api('/api/db/' + encodeURIComponent(name));
230
- let html = '<h3>Collections</h3><div style="display:flex; gap:10px;">';
231
- data.collections.forEach(c => {
232
- html += '<div class="glass-card" style="cursor:pointer" onclick="selectCol(\\''+c+'\\')">'+c+'</div>';
233
- });
234
- html += '</div>';
235
- document.getElementById('main-content').innerHTML = html;
280
+
281
+ function logout() {
282
+ localStorage.removeItem('dc_hyper_key');
283
+ location.reload();
284
+ }
285
+
286
+ async function init(role) {
287
+ document.getElementById('login-gate').style.display = 'none';
288
+ document.getElementById('main-dashboard').style.display = 'grid';
289
+ document.getElementById('node-info').innerText = location.hostname;
290
+ const stats = await api('/api/stats');
291
+ document.getElementById('stat-mem').innerText = stats.memory;
292
+ if (stats.isSuper) document.getElementById('role-badge').innerText = 'SUPER ADMIN';
293
+
294
+ const list = document.getElementById('db-list');
295
+ list.innerHTML = stats.databases.map(db => \`
296
+ <div class="db-btn" onclick="selectDB('\${db.name}', '\${db.ns}')">
297
+ <div style="font-size: 1.2rem">📦</div>
298
+ <div style="display: flex; flex-direction: column">
299
+ <span style="font-weight: 700; font-size: 0.9rem">\${db.name}</span>
300
+ <span style="font-size: 0.6rem; opacity: 0.4">\${db.ns.substring(0, 12)}...</span>
301
+ </div>
302
+ </div>
303
+ \`).join('');
236
304
  }
237
- async function runQuery() {
238
- const code = document.getElementById('query-input').value;
239
- const res = await api('/api/query', 'POST', { dbName: currentDB, code });
240
- document.getElementById('query-result').innerText = JSON.stringify(res.result, null, 2);
305
+
306
+ async function selectDB(name, ns) {
307
+ document.getElementById('main-view').style.display = 'none';
308
+ document.getElementById('data-view').style.display = 'block';
309
+ document.getElementById('view-title').innerText = ns + ' / ' + name;
310
+
311
+ const data = await api(\`/api/db/\${name}/ns/\${ns}\`);
312
+ const list = document.getElementById('col-list');
313
+ list.innerHTML = data.collections.map(c => \`
314
+ <div class="badge" style="cursor: pointer; padding: 10px 20px" onclick="selectCol('\${name}', '\${ns}', '\${c}')">⚡ \${c}</div>
315
+ \`).join('');
316
+ document.getElementById('table-area').innerHTML = '<p style="opacity: 0.3">Select a collection...</p>';
241
317
  }
242
- async function selectCol(col) {
243
- const data = await api('/api/db/' + encodeURIComponent(currentDB) + '/col/' + encodeURIComponent(col));
244
- let html = '<h3>' + col + ' Data</h3><table><thead><tr><th>ID</th><th>Content</th></tr></thead><tbody>';
318
+
319
+ async function selectCol(db, ns, col) {
320
+ const data = await api(\`/api/db/\${db}/ns/\${ns}/col/\${col}\`);
321
+ let html = '<table><thead><tr><th>DOCUMENT PAYLOAD</th></tr></thead><tbody>';
245
322
  data.docs.forEach(doc => {
246
- html += '<tr><td>'+doc._id.substring(0,8)+'</td><td>'+JSON.stringify(doc).substring(0,50)+'...</td></tr>';
323
+ html += \`<tr><td><pre style="margin:0">\${JSON.stringify(doc, null, 2)}</pre></td></tr>\`;
247
324
  });
248
325
  html += '</tbody></table>';
249
- document.getElementById('main-content').innerHTML = html;
326
+ document.getElementById('table-area').innerHTML = html;
250
327
  }
251
328
  </script>
252
329
  </body>
@@ -254,4 +331,5 @@ class Dashboard {
254
331
  `;
255
332
  }
256
333
  }
334
+
257
335
  module.exports = Dashboard;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devcode-canavar-pro",
3
- "version": "3.3.2",
3
+ "version": "3.4.0",
4
4
  "description": "Monster Edition: Ultra-fast, zero-config, embedded document database with Visual Dashboard and Interactive CLI.",
5
5
  "main": "index.js",
6
6
  "bin": {