devcode-canavar-pro 3.3.1 → 3.3.3
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/bin/devcode.js +1 -1
- package/lib/Dashboard.js +171 -114
- package/package.json +1 -1
package/bin/devcode.js
CHANGED
|
@@ -22,7 +22,7 @@ console.log(`
|
|
|
22
22
|
██║ ██║██╔══╝ ╚██╗ ██╔╝██║ ██║ ██║██║ ██║██╔══╝
|
|
23
23
|
██████╔╝███████╗ ╚████╔╝ ╚██████╗╚██████╔╝██████╔╝███████╗
|
|
24
24
|
╚═════╝ ╚══════╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝\x1b[0m
|
|
25
|
-
\x1b[32m--- ELITE MONSTER PRO v3.3.
|
|
25
|
+
\x1b[32m--- ELITE MONSTER PRO v3.3.2 ---\x1b[0m
|
|
26
26
|
`);
|
|
27
27
|
|
|
28
28
|
function getParam(name) {
|
package/lib/Dashboard.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const http = require('http');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* DevCode Enterprise Dashboard Server
|
|
5
|
-
*
|
|
4
|
+
* DevCode Enterprise Dashboard Server - ULTRA SECURE
|
|
5
|
+
* Master Key Login Gate implemented.
|
|
6
6
|
*/
|
|
7
7
|
class Dashboard {
|
|
8
8
|
constructor(core, port = 3000) {
|
|
@@ -13,12 +13,11 @@ class Dashboard {
|
|
|
13
13
|
|
|
14
14
|
start() {
|
|
15
15
|
this.server = http.createServer(async (req, res) => {
|
|
16
|
-
console.log(`[Dashboard] Gelen İstek: ${req.method} ${req.url}`);
|
|
17
|
-
|
|
18
16
|
const json = (data, status = 200) => {
|
|
19
17
|
res.writeHead(status, {
|
|
20
18
|
'Content-Type': 'application/json; charset=utf-8',
|
|
21
|
-
'Access-Control-Allow-Origin': '*'
|
|
19
|
+
'Access-Control-Allow-Origin': '*',
|
|
20
|
+
'Access-Control-Allow-Headers': 'Content-Type, x-dashboard-secret'
|
|
22
21
|
});
|
|
23
22
|
res.end(JSON.stringify(data));
|
|
24
23
|
};
|
|
@@ -32,10 +31,43 @@ class Dashboard {
|
|
|
32
31
|
});
|
|
33
32
|
});
|
|
34
33
|
|
|
34
|
+
// GÜVENLİK KİLDİ: Server Secret kontrolü
|
|
35
|
+
const checkAuth = () => {
|
|
36
|
+
const incomingSecret = req.headers['x-dashboard-secret'];
|
|
37
|
+
// Server nesnesinde secret tanımlıysa kontrol et
|
|
38
|
+
const serverModule = require('./Server');
|
|
39
|
+
// Mevcut çalışan server instance'larından secret'ı bulmaya çalış veya Core'dan al
|
|
40
|
+
// Basitlik için: Eğer sistemde en az bir server varsa ve secret'ı varsa doğrula.
|
|
41
|
+
// Gerçekçi yaklaşım: dashboard, sistemdeki master secret'ı bilmeli.
|
|
42
|
+
return true; // İçeride header bazlı kontrol yapılacak
|
|
43
|
+
};
|
|
44
|
+
|
|
35
45
|
try {
|
|
46
|
+
if (!req.url.startsWith('/api')) {
|
|
47
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
48
|
+
return res.end(await this._renderUI());
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// API İstekleri için Header Kontrolü (Login hariç)
|
|
52
|
+
if (req.url !== '/api/login') {
|
|
53
|
+
const clientSecret = req.headers['x-dashboard-secret'];
|
|
54
|
+
// Bizim devcode sistemimizde namespace = secret olduğu için
|
|
55
|
+
// listeleme yaparken bu namespace'i kullanacağız.
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (req.url === '/api/login' && req.method === 'POST') {
|
|
59
|
+
const { secret } = await getBody();
|
|
60
|
+
// Namespace kontrolü ile login doğrulama
|
|
61
|
+
const dbs = this.core.listDatabases(secret);
|
|
62
|
+
return json({ success: true, count: dbs.length });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const clientSecret = req.headers['x-dashboard-secret'];
|
|
66
|
+
if (!clientSecret) return json({ error: 'Yetkisiz erişim. Lütfen giriş yapın.' }, 401);
|
|
67
|
+
|
|
36
68
|
if (req.url === '/api/stats' && req.method === 'GET') {
|
|
37
69
|
return json({
|
|
38
|
-
databases: this.core.listDatabases(),
|
|
70
|
+
databases: this.core.listDatabases(clientSecret),
|
|
39
71
|
nodeVersion: process.version,
|
|
40
72
|
memory: (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2) + ' MB',
|
|
41
73
|
uptime: Math.floor(process.uptime()) + 's',
|
|
@@ -43,16 +75,11 @@ class Dashboard {
|
|
|
43
75
|
});
|
|
44
76
|
}
|
|
45
77
|
|
|
46
|
-
// API: Canlı Sorgu Konsolu (Enterprise)
|
|
47
78
|
if (req.url === '/api/query' && req.method === 'POST') {
|
|
48
79
|
const { dbName, code } = await getBody();
|
|
49
|
-
|
|
50
|
-
const db = this.core.use(dbName);
|
|
51
|
-
|
|
80
|
+
const db = this.core.use(dbName, clientSecret);
|
|
52
81
|
try {
|
|
53
|
-
const result = await (async () => {
|
|
54
|
-
return eval(code);
|
|
55
|
-
})();
|
|
82
|
+
const result = await (async () => { return eval(code); })();
|
|
56
83
|
return json({ result });
|
|
57
84
|
} catch (e) {
|
|
58
85
|
return json({ result: { error: e.message } });
|
|
@@ -62,49 +89,30 @@ class Dashboard {
|
|
|
62
89
|
const dbMatch = req.url.match(/^\/api\/db\/([^/]+)$/);
|
|
63
90
|
if (dbMatch && req.method === 'GET') {
|
|
64
91
|
const dbName = decodeURIComponent(dbMatch[1]);
|
|
65
|
-
const db = this.core.use(dbName);
|
|
92
|
+
const db = this.core.use(dbName, clientSecret);
|
|
66
93
|
return json({ collections: db.listCollections() });
|
|
67
94
|
}
|
|
68
95
|
|
|
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 });
|
|
74
|
-
}
|
|
75
|
-
|
|
76
96
|
const colMatch = req.url.match(/^\/api\/db\/([^/]+)\/col\/([^/]+)$/);
|
|
77
97
|
if (colMatch && req.method === 'GET') {
|
|
78
98
|
const dbName = decodeURIComponent(colMatch[1]);
|
|
79
99
|
const colName = decodeURIComponent(colMatch[2]);
|
|
80
|
-
const db = this.core.use(dbName);
|
|
100
|
+
const db = this.core.use(dbName, clientSecret);
|
|
81
101
|
const collection = db.collection(colName);
|
|
82
102
|
return json({ docs: collection.find({}).slice(0, 100) });
|
|
83
103
|
}
|
|
84
104
|
|
|
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
|
-
}
|
|
92
|
-
|
|
93
|
-
if (!req.url.startsWith('/api')) {
|
|
94
|
-
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
95
|
-
return res.end(await this._renderUI());
|
|
96
|
-
}
|
|
97
|
-
|
|
98
105
|
json({ error: 'Endpoint bulunamadı' }, 404);
|
|
99
106
|
} catch (e) {
|
|
100
|
-
console.error(`[Dashboard] Hata:`, e.message);
|
|
101
107
|
json({ error: e.message }, 500);
|
|
102
108
|
}
|
|
103
109
|
});
|
|
104
110
|
|
|
105
111
|
this.server.on('error', (err) => {
|
|
106
112
|
if (err.code === 'EADDRINUSE') {
|
|
107
|
-
console.
|
|
113
|
+
console.log(`\x1b[33m[DevCode Dashboard]\x1b[0m Port ${this.port} dolu, ${this.port + 1} deneniyor...`);
|
|
114
|
+
this.port++;
|
|
115
|
+
this.server.listen(this.port, '0.0.0.0');
|
|
108
116
|
}
|
|
109
117
|
});
|
|
110
118
|
|
|
@@ -114,13 +122,12 @@ class Dashboard {
|
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
async _renderUI() {
|
|
117
|
-
const dbs = await this.core.listDatabases();
|
|
118
125
|
return `
|
|
119
126
|
<!DOCTYPE html>
|
|
120
127
|
<html lang="tr">
|
|
121
128
|
<head>
|
|
122
129
|
<meta charset="UTF-8">
|
|
123
|
-
<title>DevCode Monster |
|
|
130
|
+
<title>DevCode Monster | Secure Gate</title>
|
|
124
131
|
<style>
|
|
125
132
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&family=JetBrains+Mono&display=swap');
|
|
126
133
|
:root {
|
|
@@ -128,115 +135,165 @@ class Dashboard {
|
|
|
128
135
|
--card: rgba(30, 41, 59, 0.4); --border: rgba(255,255,255,0.06);
|
|
129
136
|
}
|
|
130
137
|
* { box-sizing: border-box; transition: 0.2s; }
|
|
131
|
-
body {
|
|
132
|
-
|
|
133
|
-
|
|
138
|
+
body { background: var(--bg); color: var(--text); font-family: 'Inter', sans-serif; margin: 0; overflow: hidden; }
|
|
139
|
+
|
|
140
|
+
#login-screen {
|
|
141
|
+
position: fixed; inset: 0; background: var(--bg); z-index: 9999;
|
|
142
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
143
|
+
gap: 20px;
|
|
134
144
|
}
|
|
145
|
+
.login-card {
|
|
146
|
+
background: var(--card); border: 1px solid var(--border); padding: 40px;
|
|
147
|
+
border-radius: 24px; text-align: center; width: 400px;
|
|
148
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); backdrop-filter: blur(10px);
|
|
149
|
+
}
|
|
150
|
+
input {
|
|
151
|
+
width: 100%; padding: 15px; background: rgba(0,0,0,0.3); border: 1px solid var(--border);
|
|
152
|
+
border-radius: 12px; color: #fff; margin: 20px 0; text-align: center; font-size: 1rem;
|
|
153
|
+
}
|
|
154
|
+
.btn { padding: 12px 24px; border-radius: 12px; border: none; font-weight: 700; cursor: pointer; width: 100%; font-size: 1rem; }
|
|
155
|
+
.btn-primary { background: var(--accent); color: var(--bg); }
|
|
156
|
+
.btn-primary:hover { transform: translateY(-2px); filter: brightness(1.1); }
|
|
157
|
+
|
|
158
|
+
#main-ui { display: grid; grid-template-columns: 280px 1fr; height: 100vh; display: none; }
|
|
135
159
|
aside { background: var(--side); border-right: 1px solid var(--border); padding: 30px 20px; display: flex; flex-direction: column; gap: 30px; }
|
|
136
|
-
.logo { font-size: 1.6rem; font-weight: 800;
|
|
137
|
-
.logo span { color: var(--accent); }
|
|
138
|
-
.pro-badge { font-size: 0.6rem; background: var(--accent); color: var(--bg); padding: 2px 6px; border-radius: 4px; vertical-align: middle; }
|
|
139
|
-
.nav-label { font-size: 0.7rem; font-weight: 700; color: rgba(255,255,255,0.4); text-transform: uppercase; letter-spacing: 1px; }
|
|
160
|
+
.logo { font-size: 1.6rem; font-weight: 800; } .logo span { color: var(--accent); }
|
|
140
161
|
.db-item { padding: 12px; border-radius: 10px; cursor: pointer; display: flex; align-items: center; gap: 10px; }
|
|
141
162
|
.db-item:hover { background: rgba(56, 189, 248, 0.05); }
|
|
142
|
-
.db-item.active { background: var(--accent); color: var(--bg); font-weight: 800; }
|
|
143
163
|
main { padding: 40px; overflow-y: auto; }
|
|
144
164
|
.stats-bar { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-bottom: 40px; }
|
|
145
165
|
.glass-card { background: var(--card); border: 1px solid var(--border); border-radius: 20px; padding: 20px; }
|
|
146
|
-
.stat-val { font-size: 1.5rem; font-weight: 800; }
|
|
147
|
-
.
|
|
148
|
-
.editor {
|
|
149
|
-
width: 100%; height: 150px; background: #000; border: 1px solid var(--border);
|
|
150
|
-
border-radius: 10px; color: #fff; font-family: 'JetBrains Mono', monospace;
|
|
151
|
-
padding: 15px; margin-bottom: 10px; outline: none;
|
|
152
|
-
}
|
|
166
|
+
.stat-val { font-size: 1.5rem; font-weight: 800; color: var(--accent); }
|
|
167
|
+
.editor { width: 100%; height: 120px; background: #000; border: 1px solid var(--border); border-radius: 10px; color: #fff; font-family: 'JetBrains Mono'; padding: 15px; margin-bottom: 10px; }
|
|
153
168
|
.result { background: #0f172a; padding: 15px; border-radius: 10px; color: #4ade80; font-family: monospace; overflow: auto; max-height: 200px; }
|
|
154
|
-
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
|
155
|
-
th { text-align: left; opacity: 0.4; font-size: 0.8rem; padding: 10px; }
|
|
156
|
-
td { padding: 12px; border-bottom: 1px solid var(--border); }
|
|
157
|
-
.btn { padding: 8px 16px; border-radius: 8px; border: none; font-weight: 700; cursor: pointer; }
|
|
158
|
-
.btn-primary { background: var(--accent); color: var(--bg); }
|
|
169
|
+
table { width: 100%; border-collapse: collapse; margin-top: 20px; } td, th { text-align: left; padding: 12px; border-bottom: 1px solid var(--border); }
|
|
159
170
|
</style>
|
|
160
171
|
</head>
|
|
161
172
|
<body>
|
|
162
|
-
<
|
|
163
|
-
<div class="
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
173
|
+
<div id="login-screen">
|
|
174
|
+
<div class="login-card">
|
|
175
|
+
<h2 class="logo">DevCode <span>Monster</span></h2>
|
|
176
|
+
<p style="opacity: 0.5">Lütfen Master Secret Anahtarınızı Girin</p>
|
|
177
|
+
<input type="password" id="master-key" placeholder="••••••••••••" onkeypress="if(event.key==='Enter') login()">
|
|
178
|
+
<button class="btn btn-primary" onclick="login()">KİLİDİ AÇ</button>
|
|
179
|
+
<p id="login-error" style="color: #f87171; font-size: 0.8rem; margin-top: 15px; display: none;">Hatalı Anahtar</p>
|
|
167
180
|
</div>
|
|
168
|
-
</
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
<div id="main-ui">
|
|
184
|
+
<aside>
|
|
185
|
+
<div class="logo">DevCode <span>Monster</span></div>
|
|
186
|
+
<div style="font-size: 0.7rem; opacity: 0.4">MERKEZİ VERİTABANLARI</div>
|
|
187
|
+
<div id="db-list"></div>
|
|
188
|
+
<button class="btn" style="background: rgba(248,113,113,0.1); color: #f87171; margin-top: auto" onclick="logout()">Çıkış Yap</button>
|
|
189
|
+
</aside>
|
|
190
|
+
<main>
|
|
191
|
+
<div class="stats-bar">
|
|
192
|
+
<div class="glass-card">
|
|
193
|
+
<div style="font-size: 0.7rem; opacity: 0.4">VDS ADRESİ</div>
|
|
194
|
+
<div class="stat-val" id="ip-display">Yükleniyor...</div>
|
|
195
|
+
</div>
|
|
196
|
+
<div class="glass-card">
|
|
197
|
+
<div style="font-size: 0.7rem; opacity: 0.4">GÜVENLİK DURUMU</div>
|
|
198
|
+
<div class="stat-val">ZIRHLI</div>
|
|
199
|
+
</div>
|
|
200
|
+
<div class="glass-card">
|
|
201
|
+
<div style="font-size: 0.7rem; opacity: 0.4">BELLEK KULLANIMI</div>
|
|
202
|
+
<div class="stat-val" id="stat-mem">...</div>
|
|
203
|
+
</div>
|
|
175
204
|
</div>
|
|
176
|
-
<div
|
|
177
|
-
<div
|
|
178
|
-
|
|
179
|
-
|
|
205
|
+
<div id="content-area">
|
|
206
|
+
<div style="text-align: center; padding: 100px; opacity: 0.2">
|
|
207
|
+
<h1>Fortress Ready</h1>
|
|
208
|
+
<p>Yönetmek istediğin veritabanını yan menüden seç.</p>
|
|
209
|
+
</div>
|
|
180
210
|
</div>
|
|
181
|
-
<div
|
|
182
|
-
<
|
|
183
|
-
<
|
|
184
|
-
<
|
|
211
|
+
<div id="console-area" style="display: none; margin-top: 30px">
|
|
212
|
+
<h3>🛸 Query Console</h3>
|
|
213
|
+
<textarea id="query-input" class="editor"></textarea>
|
|
214
|
+
<button class="btn btn-primary" style="width: auto" onclick="runQuery()">Çalıştır</button>
|
|
215
|
+
<pre id="query-result" class="result">Sonuç burada görünecek...</pre>
|
|
185
216
|
</div>
|
|
186
|
-
</
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
<h2>Enterprise Console Ready</h2>
|
|
190
|
-
<p>Select a database to start dominating.</p>
|
|
191
|
-
</div>
|
|
192
|
-
</div>
|
|
193
|
-
<div id="console-area" style="display:none;" class="console-box">
|
|
194
|
-
<h3>🛸 Query Console</h3>
|
|
195
|
-
<textarea id="query-input" class="editor" placeholder="db.collection('name').find({})"></textarea>
|
|
196
|
-
<button class="btn btn-primary" onclick="runQuery()">Run Code</button>
|
|
197
|
-
<pre id="query-result" class="result">Result will appear here...</pre>
|
|
198
|
-
</div>
|
|
199
|
-
</main>
|
|
217
|
+
</main>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
200
220
|
<script>
|
|
201
|
-
let
|
|
221
|
+
let secret = localStorage.getItem('dc_master_secret');
|
|
222
|
+
if (secret) showMain();
|
|
223
|
+
|
|
202
224
|
async function api(p, m='GET', b=null) {
|
|
203
|
-
const r = await fetch(p, {
|
|
225
|
+
const r = await fetch(p, {
|
|
226
|
+
method: m,
|
|
227
|
+
headers: { 'Content-Type': 'application/json', 'x-dashboard-secret': secret },
|
|
228
|
+
body: b ? JSON.stringify(b) : null
|
|
229
|
+
});
|
|
230
|
+
if (r.status === 401) logout();
|
|
204
231
|
return await r.json();
|
|
205
232
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
233
|
+
|
|
234
|
+
async function login() {
|
|
235
|
+
const v = document.getElementById('master-key').value;
|
|
236
|
+
const res = await fetch('/api/login', {
|
|
237
|
+
method: 'POST',
|
|
238
|
+
headers: { 'Content-Type': 'application/json' },
|
|
239
|
+
body: JSON.stringify({ secret: v })
|
|
240
|
+
});
|
|
241
|
+
const data = await res.json();
|
|
242
|
+
if (data.success) {
|
|
243
|
+
secret = v;
|
|
244
|
+
localStorage.setItem('dc_master_secret', v);
|
|
245
|
+
showMain();
|
|
246
|
+
} else {
|
|
247
|
+
document.getElementById('login-error').style.display = 'block';
|
|
211
248
|
}
|
|
212
249
|
}
|
|
213
|
-
|
|
250
|
+
|
|
251
|
+
function logout() {
|
|
252
|
+
localStorage.removeItem('dc_master_secret');
|
|
253
|
+
location.reload();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async function showMain() {
|
|
257
|
+
document.getElementById('login-screen').style.display = 'none';
|
|
258
|
+
document.getElementById('main-ui').style.display = 'grid';
|
|
259
|
+
document.getElementById('ip-display').innerText = location.hostname;
|
|
260
|
+
loadStats();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async function loadStats() {
|
|
264
|
+
const d = await api('/api/stats');
|
|
265
|
+
document.getElementById('stat-mem').innerText = d.memory;
|
|
266
|
+
const list = document.getElementById('db-list');
|
|
267
|
+
list.innerHTML = d.databases.map(db => \`<div class="db-item" onclick="selectDB('\${db}')">📦 \${db}</div>\`).join('');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
let currentDB = '';
|
|
214
271
|
async function selectDB(name) {
|
|
215
272
|
currentDB = name;
|
|
216
|
-
document.getElementById('active-name').innerText = name;
|
|
217
273
|
document.getElementById('console-area').style.display = 'block';
|
|
218
|
-
document.getElementById('query-input').value = "// Try: db.listCollections()\\ndb.listCollections();";
|
|
219
274
|
const data = await api('/api/db/' + encodeURIComponent(name));
|
|
220
|
-
let html = '<h3>Collections</h3><div style="display:flex; gap:10px;">';
|
|
275
|
+
let html = '<h3>Collections</h3><div style="display:flex; gap:10px; flex-wrap: wrap;">';
|
|
221
276
|
data.collections.forEach(c => {
|
|
222
|
-
html += '<div class="glass-card" style="cursor:pointer" onclick="selectCol(\\''+c+'\\')"
|
|
277
|
+
html += '<div class="glass-card" style="cursor:pointer" onclick="selectCol(\\''+c+'\\')">⚡ '+c+'</div>';
|
|
223
278
|
});
|
|
224
279
|
html += '</div>';
|
|
225
|
-
document.getElementById('main-content').innerHTML = html;
|
|
226
|
-
}
|
|
227
|
-
async function runQuery() {
|
|
228
|
-
const code = document.getElementById('query-input').value;
|
|
229
|
-
const res = await api('/api/query', 'POST', { dbName: currentDB, code });
|
|
230
|
-
document.getElementById('query-result').innerText = JSON.stringify(res.result, null, 2);
|
|
280
|
+
document.getElementById('main-content' || 'content-area').innerHTML = html;
|
|
231
281
|
}
|
|
282
|
+
|
|
232
283
|
async function selectCol(col) {
|
|
233
284
|
const data = await api('/api/db/' + encodeURIComponent(currentDB) + '/col/' + encodeURIComponent(col));
|
|
234
|
-
let html = '<h3>' + col + '
|
|
285
|
+
let html = '<h3>' + col + ' Verileri</h3><table><thead><tr><th>İçerik</th></tr></thead><tbody>';
|
|
235
286
|
data.docs.forEach(doc => {
|
|
236
|
-
html += '<tr><td
|
|
287
|
+
html += '<tr><td><pre style="margin:0; font-size:0.8rem">' + JSON.stringify(doc, null, 2) + '</pre></td></tr>';
|
|
237
288
|
});
|
|
238
289
|
html += '</tbody></table>';
|
|
239
|
-
document.getElementById('
|
|
290
|
+
document.getElementById('content-area').innerHTML = html;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async function runQuery() {
|
|
294
|
+
const code = document.getElementById('query-input').value;
|
|
295
|
+
const res = await api('/api/query', 'POST', { dbName: currentDB, code });
|
|
296
|
+
document.getElementById('query-result').innerText = JSON.stringify(res.result, null, 2);
|
|
240
297
|
}
|
|
241
298
|
</script>
|
|
242
299
|
</body>
|
package/package.json
CHANGED