devcode-canavar-pro 3.3.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.
@@ -0,0 +1,275 @@
1
+ const http = require('http');
2
+
3
+ // Baran'ın Merkezi Veri Sunucusu (VDS) - Veri Merkezi IP
4
+ const CLOUD_HOST = '45.74.244.192';
5
+ const CLOUD_PORT = 4242;
6
+
7
+ /**
8
+ * DevCode Remote Client
9
+ * VDS'teki DevCode Server'a uzaktan bağlanır.
10
+ * API, yerel Collection ile birebir aynıdır.
11
+ */
12
+ class RemoteClient {
13
+ /**
14
+ * @param {string|object} options - Connection URI string or options object
15
+ */
16
+ constructor(options = {}) {
17
+ let uri = typeof options === 'string' && options.startsWith('devcode:') ? options : (options.uri || process.env.DEVCODE_URI);
18
+ let host, port, secret;
19
+
20
+ if (uri) {
21
+ try {
22
+ const url = new URL(uri);
23
+ secret = url.username || null;
24
+ host = url.hostname;
25
+ port = parseInt(url.port) || CLOUD_PORT;
26
+ } catch (e) {
27
+ throw new Error("Geçersiz Connection URI! Format: devcode://secret@vds-ip:4242");
28
+ }
29
+ } else {
30
+ // Varsayılan olarak Baran'ın Bulut Sunucusuna bağlan
31
+ host = options.host || process.env.DEVCODE_HOST || CLOUD_HOST;
32
+ port = options.port || process.env.DEVCODE_PORT || CLOUD_PORT;
33
+ secret = typeof options === 'string' ? options : (options.secret || null);
34
+ }
35
+
36
+ this.host = host;
37
+ this.port = port;
38
+ this.secret = secret;
39
+ this.timeout = options.timeout || 10000;
40
+ this.maxRetries = options.maxRetries || 3; // Varsayılan 3 deneme
41
+ this.retryDelay = options.retryDelay || 1000; // Denemeler arası 1 saniye
42
+ this._dashboard = null;
43
+ }
44
+
45
+ /**
46
+ * Kullanıcının kendi verilerini yönetebilmesi için yerel paneli başlatır.
47
+ * Bu panel VDS'teki verileri gösterir!
48
+ */
49
+ startDashboard(port = 3000) {
50
+ const Dashboard = require('./Dashboard');
51
+ this._dashboard = new Dashboard(this, port);
52
+ this._dashboard.start();
53
+ }
54
+
55
+ /**
56
+ * Bağlantıyı test eder.
57
+ * @returns {Promise<boolean>}
58
+ */
59
+ async ping() {
60
+ const res = await this._request('GET', '/ping');
61
+ return res.ok === true;
62
+ }
63
+
64
+ /**
65
+ * Uzak sunucudaki veritabanı listesini getirir.
66
+ * @returns {Promise<string[]>}
67
+ */
68
+ async listDatabases() {
69
+ const res = await this._request('GET', '/databases');
70
+ return res.data || [];
71
+ }
72
+
73
+ /**
74
+ * Bir veritabanına bağlanır.
75
+ * @param {string} dbName
76
+ * @returns {RemoteDatabase}
77
+ */
78
+ use(dbName) {
79
+ return new RemoteDatabase(this, dbName);
80
+ }
81
+
82
+ /**
83
+ * HTTP isteği gönderir (Hata durumunda otomatik tekrar denemeli).
84
+ * @private
85
+ */
86
+ async _request(method, path, body = null, retryCount = 0) {
87
+ try {
88
+ return await new Promise((resolve, reject) => {
89
+ const bodyStr = body ? JSON.stringify(body) : null;
90
+
91
+ const options = {
92
+ hostname: this.host,
93
+ port: this.port,
94
+ path: path,
95
+ method: method,
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ ...(this.secret ? { 'x-secret': this.secret } : {}),
99
+ ...(bodyStr ? { 'Content-Length': Buffer.byteLength(bodyStr) } : {})
100
+ }
101
+ };
102
+
103
+ const req = http.request(options, (res) => {
104
+ let data = '';
105
+ res.on('data', chunk => { data += chunk; });
106
+ res.on('end', () => {
107
+ try {
108
+ const parsed = JSON.parse(data);
109
+ resolve(parsed);
110
+ } catch (e) {
111
+ reject(new Error('Sunucudan geçersiz yanıt.'));
112
+ }
113
+ });
114
+ });
115
+
116
+ req.setTimeout(this.timeout, () => {
117
+ req.destroy();
118
+ reject(new Error(`Zaman aşımı (${this.timeout}ms)`));
119
+ });
120
+
121
+ req.on('error', (err) => {
122
+ reject(err);
123
+ });
124
+
125
+ if (bodyStr) req.write(bodyStr);
126
+ req.end();
127
+ });
128
+ } catch (error) {
129
+ // Sadece bağlantı hatalarında ve zaman aşımında tekrar dene
130
+ if (retryCount < this.maxRetries) {
131
+ console.warn(`⚠️ [Monster-Retry] ${path} hatası: ${error.message}. Tekrar deneniyor (${retryCount + 1}/${this.maxRetries})...`);
132
+ await new Promise(r => setTimeout(r, this.retryDelay));
133
+ return this._request(method, path, body, retryCount + 1);
134
+ }
135
+ throw new Error(`[DevCode Remote] ${path} başarısız: ${error.message}`);
136
+ }
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Uzak veritabanı örneği — RemoteClient.use() tarafından oluşturulur.
142
+ */
143
+ class RemoteDatabase {
144
+ constructor(client, dbName) {
145
+ this._client = client;
146
+ this._dbName = dbName;
147
+ }
148
+
149
+ /**
150
+ * Bir koleksiyona bağlanır.
151
+ * @param {string} name
152
+ * @returns {RemoteCollection}
153
+ */
154
+ collection(name) {
155
+ return new RemoteCollection(this._client, this._dbName, name);
156
+ }
157
+
158
+ /**
159
+ * Koleksiyon listesini getirir (Dashboard için).
160
+ */
161
+ async listCollections() {
162
+ return this._client._request('GET', `/use/${this._dbName}/-dummy-/collections`)
163
+ .then(res => res.data);
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Uzak koleksiyon — yerel Collection ile aynı API'ye sahiptir.
169
+ */
170
+ class RemoteCollection {
171
+ constructor(client, dbName, collectionName) {
172
+ this._client = client;
173
+ this._base = `/use/${dbName}/${collectionName}`;
174
+ }
175
+
176
+ /** @private */
177
+ _post(action, body) {
178
+ return this._client._request('POST', `${this._base}/${action}`, body)
179
+ .then(res => res.data);
180
+ }
181
+
182
+ /** @private */
183
+ _get(action) {
184
+ return this._client._request('GET', `${this._base}/${action}`)
185
+ .then(res => res.data);
186
+ }
187
+
188
+ /**
189
+ * Tek bir belge ekler.
190
+ * @param {object} doc
191
+ */
192
+ async insert(doc) {
193
+ return this._post('insert', { doc });
194
+ }
195
+
196
+ /**
197
+ * Birden fazla belge ekler.
198
+ * @param {object[]} docs
199
+ */
200
+ async insertMany(docs) {
201
+ return this._post('insertMany', { docs });
202
+ }
203
+
204
+ /**
205
+ * Sorguya uyan tüm belgeleri getirir.
206
+ * @param {object} query
207
+ */
208
+ async find(query = {}) {
209
+ return this._post('find', { query });
210
+ }
211
+
212
+ /**
213
+ * Sorguya uyan ilk belgeyi getirir.
214
+ * @param {object} query
215
+ */
216
+ async findOne(query = {}) {
217
+ return this._post('findOne', { query });
218
+ }
219
+
220
+ /**
221
+ * Sorguya uyan ilk belgeyi günceller.
222
+ * @param {object} query
223
+ * @param {object} update
224
+ */
225
+ async update(query, update) {
226
+ return this._post('update', { query, update });
227
+ }
228
+
229
+ /**
230
+ * Sorguya uyan tüm belgeleri günceller.
231
+ * @param {object} query
232
+ * @param {object} update
233
+ */
234
+ async updateMany(query, update) {
235
+ return this._post('updateMany', { query, update });
236
+ }
237
+
238
+ /**
239
+ * Sorguya uyan ilk belgeyi siler.
240
+ * @param {object} query
241
+ */
242
+ async delete(query) {
243
+ return this._post('delete', { query });
244
+ }
245
+
246
+ /**
247
+ * Sorguya uyan tüm belgeleri siler.
248
+ * @param {object} query
249
+ */
250
+ async deleteMany(query) {
251
+ return this._post('deleteMany', { query });
252
+ }
253
+
254
+ /**
255
+ * Belge sayısını döner.
256
+ * @param {object} query
257
+ */
258
+ async count(query = {}) {
259
+ return this._post('count', { query });
260
+ }
261
+
262
+ /**
263
+ * Koleksiyonu tamamen siler.
264
+ */
265
+ async drop() {
266
+ return this._post('drop', {});
267
+ }
268
+
269
+ /** Dashboard uyumluluğu için alias */
270
+ async remove(query) {
271
+ return this.delete(query);
272
+ }
273
+ }
274
+
275
+ module.exports = RemoteClient;
package/lib/Schema.js ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * DevCode Schema Validator
3
+ * Verilerin bütünlüğünü ve doğruluğunu kontrol eder.
4
+ */
5
+ class Schema {
6
+ constructor(definition) {
7
+ this.definition = definition;
8
+ }
9
+
10
+ /**
11
+ * Dökümanı şemaya göre doğrular.
12
+ */
13
+ validate(doc) {
14
+ const errors = [];
15
+
16
+ for (let field in this.definition) {
17
+ const rules = this.definition[field];
18
+ const value = doc[field];
19
+
20
+ // Zorunlu alan kontrolü
21
+ if (rules.required && (value === undefined || value === null)) {
22
+ errors.push(`${field} alanı zorunludur.`);
23
+ continue;
24
+ }
25
+
26
+ if (value !== undefined) {
27
+ // Tip kontrolü
28
+ if (rules.type && typeof value !== rules.type && rules.type !== 'array') {
29
+ errors.push(`${field} alanı ${rules.type} tipinde olmalıdır.`);
30
+ }
31
+
32
+ // Array kontrolü
33
+ if (rules.type === 'array' && !Array.isArray(value)) {
34
+ errors.push(`${field} alanı bir dizi olmalıdır.`);
35
+ }
36
+
37
+ // Özel doğrulama (validator function)
38
+ if (rules.validate && typeof rules.validate === 'function') {
39
+ if (!rules.validate(value)) {
40
+ errors.push(`${field} alanı geçersiz değer içeriyor.`);
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ if (errors.length > 0) {
47
+ throw new Error(`Şema Doğrulama Hatası: ${errors.join(' ')}`);
48
+ }
49
+
50
+ return true;
51
+ }
52
+ }
53
+
54
+ module.exports = Schema;
package/lib/Server.js ADDED
@@ -0,0 +1,224 @@
1
+ const http = require('http');
2
+ const url = require('url');
3
+
4
+ /**
5
+ * DevCode Remote Server
6
+ * VDS üzerinde çalışır. HTTP API ile uzaktan veritabanı erişimi sağlar.
7
+ * Kullanıcılar RemoteClient ile bu sunucuya bağlanır.
8
+ */
9
+ class Server {
10
+ /**
11
+ * @param {object} devcode - DevCode core örneği
12
+ * @param {object} options
13
+ * @param {number} options.port - Sunucu portu (varsayılan: 4242)
14
+ * @param {string} options.secret - Güvenlik anahtarı (boş bırakılırsa açık erişim)
15
+ */
16
+ constructor(devcode, options = {}) {
17
+ this.devcode = devcode;
18
+ this.port = options.port || 4242;
19
+ this.secret = options.secret || null;
20
+ this.rateLimit = options.rateLimit || 100; // Dakikada 100 istek sınırı
21
+ this.requestTracker = new Map(); // IP/Secret bazlı istek takibi
22
+ this._server = null;
23
+ }
24
+
25
+ /**
26
+ * Sunucuyu başlatır.
27
+ */
28
+ start() {
29
+ this._server = http.createServer((req, res) => {
30
+ this._handle(req, res);
31
+ });
32
+
33
+ this._server.listen(this.port, '0.0.0.0', () => {
34
+ console.log(`\x1b[32m[DevCode Server]\x1b[0m Uzak veritabanı sunucusu aktif → Port: \x1b[33m${this.port}\x1b[0m`);
35
+ if (this.secret) {
36
+ console.log(`\x1b[32m[DevCode Server]\x1b[0m Güvenlik: \x1b[32mAktif\x1b[0m (secret key gerekli)`);
37
+ } else {
38
+ console.log(`\x1b[33m[DevCode Server]\x1b[0m Uyarı: Güvenlik anahtarı tanımlanmadı! Açık erişim aktif.`);
39
+ }
40
+ });
41
+
42
+ return this;
43
+ }
44
+
45
+ /**
46
+ * Sunucuyu durdurur.
47
+ */
48
+ stop() {
49
+ if (this._server) {
50
+ this._server.close();
51
+ console.log('\x1b[33m[DevCode Server]\x1b[0m Sunucu durduruldu.');
52
+ }
53
+ }
54
+
55
+ /**
56
+ * HTTP isteklerini işler.
57
+ * @private
58
+ */
59
+ async _handle(req, res) {
60
+ res.setHeader('Content-Type', 'application/json');
61
+ res.setHeader('Access-Control-Allow-Origin', '*');
62
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
63
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, x-secret');
64
+
65
+ // simple rate limit logic
66
+ const ip = req.socket.remoteAddress;
67
+ const now = Date.now();
68
+ const clientData = this.requestTracker.get(ip) || { count: 0, startTime: now };
69
+
70
+ if (now - clientData.startTime > 60000) {
71
+ clientData.count = 0;
72
+ clientData.startTime = now;
73
+ }
74
+
75
+ clientData.count++;
76
+ this.requestTracker.set(ip, clientData);
77
+
78
+ if (clientData.count > this.rateLimit) {
79
+ res.writeHead(429);
80
+ return res.end(JSON.stringify({ ok: false, error: 'Rate limit aşıldı! Lütfen bekleyin.' }));
81
+ }
82
+
83
+ // OPTIONS (preflight) isteğini yanıtla
84
+ if (req.method === 'OPTIONS') {
85
+ res.writeHead(204);
86
+ return res.end();
87
+ }
88
+
89
+ let namespace = 'public'; // Varsayılan namespace
90
+ // Kimlik doğrulama
91
+ if (this.secret) {
92
+ const clientSecret = req.headers['x-secret'];
93
+ if (clientSecret !== this.secret) {
94
+ res.writeHead(401);
95
+ return res.end(JSON.stringify({ ok: false, error: 'Geçersiz güvenlik anahtarı.' }));
96
+ }
97
+ namespace = clientSecret; // Güvenlik anahtarı aynı zamanda namespace olarak kullanılır
98
+ }
99
+
100
+ // URL parse: /use/:db/:collection/:action
101
+ const parsed = url.parse(req.url, true);
102
+ const parts = parsed.pathname.replace(/^\//, '').split('/');
103
+
104
+ // Özel route: GET /ping — bağlantı testi
105
+ if (parts[0] === 'ping') {
106
+ res.writeHead(200);
107
+ return res.end(JSON.stringify({ ok: true, message: 'pong', version: '2.0' }));
108
+ }
109
+
110
+ // Özel route: GET /databases — veritabanı listesi
111
+ if (parts[0] === 'databases') {
112
+ res.writeHead(200);
113
+ return res.end(JSON.stringify({ ok: true, data: this.devcode.listDatabases(namespace) }));
114
+ }
115
+
116
+ // Beklenen format: /use/:db/:collection/:action
117
+ if (parts[0] !== 'use' || parts.length < 4) {
118
+ res.writeHead(400);
119
+ return res.end(JSON.stringify({ ok: false, error: 'Geçersiz route. Format: /use/:db/:collection/:action' }));
120
+ }
121
+
122
+ const [, dbName, collectionName, action] = parts;
123
+
124
+ try {
125
+ const db = this.devcode.use(dbName, namespace);
126
+ const col = db.collection(collectionName);
127
+
128
+ // İstek gövdesini oku
129
+ let body = {};
130
+ if (req.method === 'POST') {
131
+ body = await this._readBody(req);
132
+ }
133
+
134
+ let result;
135
+
136
+ switch (action) {
137
+ case 'insert':
138
+ result = await col.insert(body.doc);
139
+ break;
140
+ case 'insertMany':
141
+ result = await col.insertMany(body.docs);
142
+ break;
143
+ case 'find':
144
+ result = col.find(body.query || {});
145
+ break;
146
+ case 'findOne':
147
+ result = col.findOne(body.query || {});
148
+ break;
149
+ case 'update':
150
+ result = await col.update(body.query, body.update);
151
+ break;
152
+ case 'updateMany':
153
+ result = await col.updateMany(body.query, body.update);
154
+ break;
155
+ case 'delete':
156
+ result = await col.delete(body.query);
157
+ break;
158
+ case 'deleteMany':
159
+ result = await col.deleteMany(body.query);
160
+ break;
161
+ case 'count':
162
+ result = col.count(body.query || {});
163
+ break;
164
+ case 'drop':
165
+ result = col.drop();
166
+ break;
167
+ case 'collections':
168
+ result = db.listCollections();
169
+ break;
170
+ default:
171
+ res.writeHead(400);
172
+ return res.end(JSON.stringify({ ok: false, error: `Bilinmeyen işlem: ${action}` }));
173
+ }
174
+
175
+ res.writeHead(200);
176
+ res.end(JSON.stringify({ ok: true, data: result }));
177
+ } catch (err) {
178
+ res.writeHead(500);
179
+ res.end(JSON.stringify({ ok: false, error: err.message }));
180
+ }
181
+ }
182
+
183
+ _readBody(req) {
184
+ return new Promise((resolve, reject) => {
185
+ let body = '';
186
+ req.on('data', chunk => { body += chunk.toString(); });
187
+ req.on('end', () => {
188
+ try {
189
+ resolve(body ? JSON.parse(body) : {});
190
+ } catch (e) {
191
+ reject(new Error('Geçersiz JSON gövdesi.'));
192
+ }
193
+ });
194
+ req.on('error', reject);
195
+ });
196
+ }
197
+
198
+ /**
199
+ * Sunucuyu başlatır ve dinler.
200
+ */
201
+ startServer(port) {
202
+ this.port = port || this.port;
203
+ this.start();
204
+ return this;
205
+ }
206
+
207
+ /**
208
+ * Görsel paneli başlatır.
209
+ */
210
+ startDashboard(port) {
211
+ this.devcode.startDashboard(port);
212
+ return this;
213
+ }
214
+
215
+ /**
216
+ * İnteraktif kabuğu başlatır.
217
+ */
218
+ startShell() {
219
+ this.devcode.startShell();
220
+ return this;
221
+ }
222
+ }
223
+
224
+ module.exports = Server;
package/lib/Storage.js ADDED
@@ -0,0 +1,52 @@
1
+ const fs = require('fs');
2
+ const zlib = require('zlib');
3
+ const path = require('path');
4
+
5
+ /**
6
+ * DevCode Storage Engine 2.0 (Enterprise Edition)
7
+ * Veri güvenliğini atomik işlemlerle (Atomic Write) sağlar.
8
+ */
9
+ class Storage {
10
+ /**
11
+ * Veriyi atomik olarak diske yazar.
12
+ * Bu yöntem veri bozulmasını (corruption) %100 önler.
13
+ */
14
+ static save(filePath, data, compress = false) {
15
+ const json = JSON.stringify(data);
16
+ const tempPath = `${filePath}.tmp`;
17
+
18
+ try {
19
+ if (compress) {
20
+ const buffer = zlib.gzipSync(json);
21
+ fs.writeFileSync(tempPath, buffer);
22
+ } else {
23
+ fs.writeFileSync(tempPath, json, 'utf8');
24
+ }
25
+
26
+ // ATOMİK YER DEĞİŞTİRME: Dosya tamamen yazılmadan asıl dosya değişmez.
27
+ fs.renameSync(tempPath, compress ? filePath + '.gz' : filePath);
28
+ } catch (err) {
29
+ if (fs.existsSync(tempPath)) fs.unlinkSync(tempPath);
30
+ throw new Error(`Kritik Depolama Hatası: ${err.message}`);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Veriyi diskten okur.
36
+ */
37
+ static load(filePath) {
38
+ const gzPath = filePath + '.gz';
39
+
40
+ if (fs.existsSync(gzPath)) {
41
+ const buffer = fs.readFileSync(gzPath);
42
+ const json = zlib.gunzipSync(buffer).toString();
43
+ return JSON.parse(json);
44
+ } else if (fs.existsSync(filePath)) {
45
+ const content = fs.readFileSync(filePath, 'utf8');
46
+ return JSON.parse(content || '[]');
47
+ }
48
+ return [];
49
+ }
50
+ }
51
+
52
+ module.exports = Storage;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Advanced Update Parser (Enterprise Edition)
3
+ * MongoDB benzeri güncelleme operatörlerini ($set, $inc, $push, $pull, $unset) işler.
4
+ */
5
+ class UpdateParser {
6
+ /**
7
+ * Bir dökümanı verilen güncelleme sorgusuna göre mutasyona uğratır.
8
+ * @param {Object} doc Güncellenecek döküman
9
+ * @param {Object} updateQuery Güncelleme sorgusu ($set, $inc vb.)
10
+ * @returns {Object} Güncellenmiş döküman
11
+ */
12
+ static parse(doc, updateQuery) {
13
+ for (let key in updateQuery) {
14
+ const val = updateQuery[key];
15
+
16
+ switch (key) {
17
+ case '$set':
18
+ for (let field in val) doc[field] = val[field];
19
+ break;
20
+
21
+ case '$inc':
22
+ for (let field in val) {
23
+ if (typeof doc[field] === 'number') doc[field] += val[field];
24
+ else doc[field] = val[field];
25
+ }
26
+ break;
27
+
28
+ case '$push':
29
+ for (let field in val) {
30
+ if (!Array.isArray(doc[field])) doc[field] = [];
31
+ doc[field].push(val[field]);
32
+ }
33
+ break;
34
+
35
+ case '$pull':
36
+ for (let field in val) {
37
+ if (Array.isArray(doc[field])) {
38
+ doc[field] = doc[field].filter(v => v !== val[field]);
39
+ }
40
+ }
41
+ break;
42
+
43
+ case '$unset':
44
+ for (let field in val) {
45
+ if (val[field]) delete doc[field];
46
+ }
47
+ break;
48
+
49
+ case '$rename':
50
+ for (let field in val) {
51
+ const newName = val[field];
52
+ if (doc[field] !== undefined) {
53
+ doc[newName] = doc[field];
54
+ delete doc[field];
55
+ }
56
+ }
57
+ break;
58
+
59
+ default:
60
+ // Eğer operatör değilse, direkt set olarak kabul et (Mongo mantığı)
61
+ if (!key.startsWith('$')) {
62
+ doc[key] = val;
63
+ }
64
+ break;
65
+ }
66
+ }
67
+ return doc;
68
+ }
69
+ }
70
+
71
+ module.exports = UpdateParser;