yodata 0.0.7 → 1.0.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.
package/README.md CHANGED
@@ -1,90 +1,101 @@
1
1
  # Y0data services #
2
2
 
3
- **Please read y0data inc before using it**
4
- **To get database id go to https://data.y0host.net/**
3
+ **MongoDB-style client for connecting to Y0Data worker server**
5
4
  **Your data will save in servers y0data, so no disk will take from your server**
6
5
 
7
6
  # install y0data
8
7
 
9
8
  ``` js
10
- npm install yodata
9
+ npm install y0data
11
10
  ```
12
11
 
13
12
  # Connect Database
14
13
 
15
14
  ``` js
16
- let yodata = require('yodata')
17
- let db = new yodata('DATA BASE ID', {ws: {cache: false}})
18
- db.connect();
15
+ const Database = require('y0data');
16
+
17
+ // Create connection with host, port, databaseId, username, password
18
+ const db = new Database(
19
+ 'localhost', // host
20
+ 5001, // port
21
+ 'f9b07fbe-7c8d-4f9d-9028-ebec6b3b2eea', // databaseId
22
+ 'yousuf', // username
23
+ '41371755aa' // password
24
+ );
19
25
  ```
20
26
 
21
27
  # events
22
28
 
23
29
  ```js
24
- db.once('ready', async ()=>{
30
+ db.on('authenticated', async ()=>{
25
31
  console.log(`DataBase Ready`)
32
+ // Now you can use database methods
26
33
  })
27
34
 
28
35
  db.on('error', (err)=>{
29
36
  console.log(`Error: ` + err)
30
37
  })
38
+
39
+ db.on('connected', ()=>{
40
+ console.log(`Connected to server`)
41
+ })
42
+
43
+ db.on('disconnected', ()=>{
44
+ console.log(`Disconnected from server`)
45
+ })
31
46
  ```
32
47
 
33
48
  # setup collection
34
49
 
35
50
  ```js
36
- let customersDB = db.setUpCollection('customers')
51
+ let customersDB = db.model('Customer', {}, 'customers')
52
+ // Now you can use customersDB methods
37
53
  ```
38
54
 
39
55
  # functions
40
56
 
41
57
  ## Create
42
58
  ```js
43
- let data = await customersDB.add([{"money": 51}, {"money": 9}]) // example output → '[Accepted Data]'
44
- let data = await customersDB.add({"_id": "123", "money": 5}) // example output → '{Accepted Data} / null'
59
+ let data = await customersDB.insertOne({"money": 51}) // example output → '[Accepted Data]'
60
+ let data = await customersDB.insertOne({"_id": "123", "money": 5}) // example output → '{Accepted Data} / null'
61
+ let data = await customersDB.insertMany([{"money": 51}, {"money": 9}]) // example output → '[Accepted Data]'
45
62
  /*
46
- For free plan 50 array max in same time
47
- For Shared Plan 100 Array max in same time
48
- For Server Plan 500 Array max in same time
63
+ Data will be serialized to BSON format automatically
49
64
  */
50
65
  ```
51
66
 
52
67
  ## find data
53
68
  ```js
54
69
  let options = {
55
- $gte: {money: 10}, // Get Users have money low of 10
56
- $gt: {money: 50}, // get Users have money more of 50
57
- $in: {_id: ['123', '1234']} // get Users have in same _id
70
+ money: {$gte: 10}, // Get Users have money greater than or equal to 10
71
+ age: {$gt: 50} // get Users have age greater than 50
58
72
  }
59
73
 
60
- let data = await customersDB.find(options).exec(); // example output → 'Array'
61
- let data = await customersDB.find(options).limit(20).exec(); // (Get Only 20 data) example output → 'Array'
62
- let data = await customersDB.find(options).skip(20).exec(); // (Skip first 20) example output → 'Array'
63
- let data = await customersDB.find(options).select({money: 1}).exec(); // (Will only see _id and money) example output → 'Array'
64
- let data = await customersDB.find(options).select({money: 0}).exec(); // (Will hide money) example output → 'Array'
74
+ let data = await customersDB.find(options) // example output → 'Array'
75
+ let data = await customersDB.find(options, {limit: 20}) // (Get Only 20 data) example output → 'Array'
76
+ let data = await customersDB.find(options, {skip: 20}) // (Skip first 20) example output → 'Array'
77
+ let data = await customersDB.find(options, {limit: 20, skip: 10}) // (Skip 10 and limit 20) example output → 'Array'
65
78
 
66
- let data = await customersDB.findOne(options).exec(); // example output → 'Object/Null'
67
- let data = await customersDB.findOne(options).skip(20).exec(); // (Skip first 20) example output → 'Object/Null'
68
- let data = await customersDB.findOne(options).select({money: 1}).exec(); // (Will only see _id and money) example output → 'Object/Null'
69
- let data = await customersDB.findOne(options).select({money: 0}).exec(); // (Will hide money) example output → 'Object/Null'
79
+ let data = await customersDB.findOne(options) // example output → 'Object/Null'
80
+ let data = await customersDB.findOne(options, {skip: 20}) // (Skip first 20) example output → 'Object/Null'
81
+ let data = await customersDB.findById('123') // (Find by ID) example output → 'Object/Null'
70
82
  ```
71
83
 
72
84
  ## Update Data
73
85
  ```js
74
86
  let options = {
75
- $gte: {money: 10}, // Get Users have money low of 10
76
- $gt: {money: 50}, // get Users have money more of 50
77
- $in: {_id: ['123', '1234']} // get Users have in same _id
87
+ money: {$gte: 10}, // Get Users have money greater than or equal to 10
88
+ _id: {$in: ['123', '1234']} // get Users with IDs in array
78
89
  }
79
90
 
80
91
  let new_values = {
81
- $inc: {money: 50}, // Add money you can also do -50 to remove
92
+ $inc: {money: 50}, // Add money you can also do -50 to remove
82
93
 
83
- $push: {arr: ["1"]}, // add in array items
84
- $push: {arr: "1"}, // add in array item
94
+ $push: {arr: ["1"]}, // add in array items
95
+ $push: {arr: "1"}, // add in array item
85
96
 
86
- $pull: {arr: ["1"]}, // delete from array items
87
- $pull: {arr: "1"} // delete from array item
97
+ $pull: {arr: ["1"]}, // delete from array items
98
+ $pull: {arr: "1"} // delete from array item
88
99
  }
89
100
 
90
101
  let data = await customersDB.updateOne(options, new_values) // example output → 'true/false'
@@ -95,9 +106,8 @@ let data = await customersDB.updateMany(options, new_values); // example output
95
106
  ## Delete Data
96
107
  ```js
97
108
  let options = {
98
- $gte: {money: 10}, // Get Users have money low of 10
99
- $gt: {money: 50}, // get Users have money more of 50
100
- $in: {_id: ['123', '1234']} // get Users have in same _id
109
+ money: {$gte: 10}, // Get Users have money greater than or equal to 10
110
+ _id: {$in: ['123', '1234']} // get Users with IDs in array
101
111
  }
102
112
 
103
113
  let data = await customersDB.deleteOne(options) // example output → 'true/false'
@@ -108,21 +118,13 @@ let data = await customersDB.deleteMany(options); // example output → 'true/fa
108
118
  ## Other functions will support you
109
119
  ```js
110
120
  let options = {
111
- $gte: {money: 10}, // Get Users have money low of 10
112
- $gt: {money: 50}, // get Users have money more of 50
113
- $in: {_id: ['123', '1234']} // get Users have in same _id
121
+ money: {$gte: 10}, // Get Users have money greater than or equal to 10
114
122
  }
115
123
 
116
- let data = await customersDB.countDocuments(options) // example output → 50
117
-
118
- let data = await customersDB.getSize(options); // example output → 177 (KB)
124
+ let data = await customersDB.countDocuments(options) // example output → 'Number'
119
125
  ```
120
126
 
121
- ## Watch
127
+ ## Disconnect
122
128
  ```js
123
- await cusotmersDB.watch()
124
-
125
- db.on('watch', (data)=>{
126
- console.log('data watch =>', data) // will get name of collection and more data
127
- })
129
+ db.disconnect() // Close connection to server
128
130
  ```
package/index.js ADDED
@@ -0,0 +1,6 @@
1
+ const Database = require('./lib/database');
2
+ const { serialize, deserialize, TYPES } = require('./lib/bson');
3
+
4
+ module.exports = Database;
5
+ module.exports.Database = Database;
6
+ module.exports.BSON = { serialize, deserialize, TYPES };
package/lib/bson.js ADDED
@@ -0,0 +1,269 @@
1
+ // BSON Type Codes
2
+ const TYPES = {
3
+ DOUBLE: 0x01,
4
+ STRING: 0x02,
5
+ OBJECT: 0x03,
6
+ ARRAY: 0x04,
7
+ BINARY: 0x05,
8
+ UNDEFINED: 0x06,
9
+ BOOL: 0x08,
10
+ DATE: 0x09,
11
+ NULL: 0x0A,
12
+ INT32: 0x10,
13
+ INT64: 0x12
14
+ };
15
+
16
+ // BSON Serializer
17
+ function serialize(doc) {
18
+ const chunks = [];
19
+
20
+ for (const key in doc) {
21
+ const value = doc[key];
22
+ const keyBuf = Buffer.from(key);
23
+ const keyLen = Buffer.from([keyBuf.length]);
24
+
25
+ if (value === null || value === undefined) {
26
+ chunks.push(Buffer.concat([
27
+ Buffer.from([value === null ? TYPES.NULL : TYPES.UNDEFINED]),
28
+ keyLen,
29
+ keyBuf
30
+ ]));
31
+ }
32
+ else if (typeof value === 'string') {
33
+ const valBuf = Buffer.from(value, 'utf8');
34
+ const lenBuf = Buffer.alloc(4);
35
+ lenBuf.writeInt32LE(valBuf.length);
36
+ chunks.push(Buffer.concat([
37
+ Buffer.from([TYPES.STRING]),
38
+ keyLen,
39
+ keyBuf,
40
+ lenBuf,
41
+ valBuf
42
+ ]));
43
+ }
44
+ else if (typeof value === 'number') {
45
+ if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {
46
+ const buf = Buffer.alloc(4);
47
+ buf.writeInt32LE(value);
48
+ chunks.push(Buffer.concat([
49
+ Buffer.from([TYPES.INT32]),
50
+ keyLen,
51
+ keyBuf,
52
+ buf
53
+ ]));
54
+ } else {
55
+ const buf = Buffer.alloc(8);
56
+ buf.writeDoubleLE(value);
57
+ chunks.push(Buffer.concat([
58
+ Buffer.from([TYPES.DOUBLE]),
59
+ keyLen,
60
+ keyBuf,
61
+ buf
62
+ ]));
63
+ }
64
+ }
65
+ else if (typeof value === 'boolean') {
66
+ chunks.push(Buffer.concat([
67
+ Buffer.from([TYPES.BOOL]),
68
+ keyLen,
69
+ keyBuf,
70
+ Buffer.from([value ? 1 : 0])
71
+ ]));
72
+ }
73
+ else if (value instanceof Date) {
74
+ const buf = Buffer.alloc(8);
75
+ buf.writeBigInt64LE(BigInt(value.getTime()));
76
+ chunks.push(Buffer.concat([
77
+ Buffer.from([TYPES.DATE]),
78
+ keyLen,
79
+ keyBuf,
80
+ buf
81
+ ]));
82
+ }
83
+ else if (Buffer.isBuffer(value)) {
84
+ const lenBuf = Buffer.alloc(4);
85
+ lenBuf.writeInt32LE(value.length);
86
+ chunks.push(Buffer.concat([
87
+ Buffer.from([TYPES.BINARY]),
88
+ keyLen,
89
+ keyBuf,
90
+ lenBuf,
91
+ value
92
+ ]));
93
+ }
94
+ else if (Array.isArray(value)) {
95
+ const arrayObj = {};
96
+ value.forEach((item, idx) => {
97
+ arrayObj[idx.toString()] = item;
98
+ });
99
+ const arrayBuf = serialize(arrayObj);
100
+ const lenBuf = Buffer.alloc(4);
101
+ lenBuf.writeInt32LE(arrayBuf.length);
102
+ chunks.push(Buffer.concat([
103
+ Buffer.from([TYPES.ARRAY]),
104
+ keyLen,
105
+ keyBuf,
106
+ lenBuf,
107
+ arrayBuf
108
+ ]));
109
+ }
110
+ else if (typeof value === 'object') {
111
+ const objBuf = serialize(value);
112
+ const lenBuf = Buffer.alloc(4);
113
+ lenBuf.writeInt32LE(objBuf.length);
114
+ chunks.push(Buffer.concat([
115
+ Buffer.from([TYPES.OBJECT]),
116
+ keyLen,
117
+ keyBuf,
118
+ lenBuf,
119
+ objBuf
120
+ ]));
121
+ }
122
+ }
123
+
124
+ return chunks.length > 0 ? Buffer.concat(chunks) : Buffer.alloc(0);
125
+ }
126
+
127
+ // BSON Deserializer (supports both client-simple and server format)
128
+ function deserialize(buffer) {
129
+ if (!buffer || buffer.length === 0) return {};
130
+
131
+ // Detect server format: first 4 bytes equal total length
132
+ if (buffer.length >= 4) {
133
+ const total = buffer.readInt32LE(0);
134
+ if (total === buffer.length) {
135
+ return deserializeServer(buffer);
136
+ }
137
+ }
138
+ return deserializeClient(buffer);
139
+ }
140
+
141
+ function deserializeClient(buffer) {
142
+ let offset = 0;
143
+ const obj = {};
144
+
145
+ while (offset < buffer.length) {
146
+ const type = buffer.readUInt8(offset++);
147
+ const keyLen = buffer.readUInt8(offset++);
148
+ const key = buffer.slice(offset, offset + keyLen).toString('utf8');
149
+ offset += keyLen;
150
+
151
+ if (type === TYPES.NULL) {
152
+ obj[key] = null;
153
+ } else if (type === TYPES.UNDEFINED) {
154
+ obj[key] = undefined;
155
+ } else if (type === TYPES.STRING) {
156
+ const len = buffer.readInt32LE(offset);
157
+ offset += 4;
158
+ obj[key] = buffer.slice(offset, offset + len).toString('utf8');
159
+ offset += len;
160
+ } else if (type === TYPES.INT32) {
161
+ obj[key] = buffer.readInt32LE(offset);
162
+ offset += 4;
163
+ } else if (type === TYPES.DOUBLE) {
164
+ obj[key] = buffer.readDoubleLE(offset);
165
+ offset += 8;
166
+ } else if (type === TYPES.INT64) {
167
+ obj[key] = Number(buffer.readBigInt64LE(offset));
168
+ offset += 8;
169
+ } else if (type === TYPES.BOOL) {
170
+ obj[key] = !!buffer.readUInt8(offset);
171
+ offset += 1;
172
+ } else if (type === TYPES.DATE) {
173
+ const timestamp = Number(buffer.readBigInt64LE(offset));
174
+ obj[key] = new Date(timestamp);
175
+ offset += 8;
176
+ } else if (type === TYPES.BINARY) {
177
+ const len = buffer.readInt32LE(offset);
178
+ offset += 4;
179
+ obj[key] = buffer.slice(offset, offset + len);
180
+ offset += len;
181
+ } else if (type === TYPES.ARRAY) {
182
+ const len = buffer.readInt32LE(offset);
183
+ offset += 4;
184
+ const arrayBuf = buffer.slice(offset, offset + len);
185
+ const arrayObj = deserializeClient(arrayBuf);
186
+ obj[key] = Object.keys(arrayObj).sort((a, b) => Number(a) - Number(b)).map(k => arrayObj[k]);
187
+ offset += len;
188
+ } else if (type === TYPES.OBJECT) {
189
+ const len = buffer.readInt32LE(offset);
190
+ offset += 4;
191
+ const objBuf = buffer.slice(offset, offset + len);
192
+ obj[key] = deserializeClient(objBuf);
193
+ offset += len;
194
+ }
195
+ }
196
+ return obj;
197
+ }
198
+
199
+ function deserializeServer(buffer) {
200
+ let offset = 4; // skip total size
201
+ const obj = {};
202
+
203
+ while (offset < buffer.length) {
204
+ const type = buffer.readUInt8(offset++);
205
+ if (type === 0x00) break; // end marker
206
+
207
+ // read null-terminated key
208
+ let keyStart = offset;
209
+ while (offset < buffer.length && buffer[offset] !== 0x00) {
210
+ offset++;
211
+ }
212
+ const key = buffer.slice(keyStart, offset).toString('utf8');
213
+ offset++; // skip null terminator
214
+
215
+ switch (type) {
216
+ case TYPES.NULL:
217
+ obj[key] = null;
218
+ break;
219
+ case TYPES.UNDEFINED:
220
+ obj[key] = undefined;
221
+ break;
222
+ case TYPES.STRING: {
223
+ const len = buffer.readInt32LE(offset);
224
+ offset += 4;
225
+ // server writes length including trailing null
226
+ const strLen = Math.max(0, len - 1);
227
+ obj[key] = buffer.slice(offset, offset + strLen).toString('utf8');
228
+ offset += len; // consume payload + trailing null
229
+ break;
230
+ }
231
+ case TYPES.INT32:
232
+ obj[key] = buffer.readInt32LE(offset);
233
+ offset += 4;
234
+ break;
235
+ case TYPES.INT64:
236
+ obj[key] = Number(buffer.readBigInt64LE(offset));
237
+ offset += 8;
238
+ break;
239
+ case TYPES.DOUBLE:
240
+ obj[key] = buffer.readDoubleLE(offset);
241
+ offset += 8;
242
+ break;
243
+ case TYPES.BOOL:
244
+ obj[key] = !!buffer.readUInt8(offset);
245
+ offset += 1;
246
+ break;
247
+ case TYPES.ARRAY:
248
+ case TYPES.OBJECT: {
249
+ const len = buffer.readInt32LE(offset);
250
+ offset += 4;
251
+ const inner = buffer.slice(offset, offset + len);
252
+ // Recursively parse using server rules
253
+ obj[key] = deserializeServer(inner);
254
+ offset += len;
255
+ break;
256
+ }
257
+ default:
258
+ // Skip unknown types safely by breaking
259
+ return obj;
260
+ }
261
+ }
262
+ return obj;
263
+ }
264
+
265
+ module.exports = {
266
+ TYPES,
267
+ serialize,
268
+ deserialize
269
+ };
@@ -0,0 +1,81 @@
1
+ const net = require('net');
2
+ const crypto = require('crypto');
3
+
4
+ class Connection {
5
+ constructor(host, port) {
6
+ this.host = host;
7
+ this.port = port;
8
+ this.socket = null;
9
+ this.reader = null;
10
+ this.writer = null;
11
+ this.requestQueue = new Map();
12
+ this.objectMapper = require('./bson');
13
+ }
14
+
15
+ connect() {
16
+ return new Promise((resolve, reject) => {
17
+ this.socket = net.createConnection({
18
+ host: this.host,
19
+ port: this.port
20
+ }, () => {
21
+ resolve();
22
+ });
23
+
24
+ this.socket.on('data', (data) => {
25
+ this._handleResponse(data.toString());
26
+ });
27
+
28
+ this.socket.on('error', (err) => {
29
+ reject(err);
30
+ });
31
+ });
32
+ }
33
+
34
+ sendRequest(type, data) {
35
+ return new Promise((resolve, reject) => {
36
+ if (!this.socket || this.socket.destroyed) {
37
+ return reject(new Error('Connection is not established'));
38
+ }
39
+
40
+ const requestID = crypto.randomUUID();
41
+
42
+ const message = {
43
+ type: type,
44
+ requestID: requestID,
45
+ data: data
46
+ };
47
+
48
+ this.requestQueue.set(requestID, { resolve, reject });
49
+
50
+ const jsonMessage = JSON.stringify(message);
51
+ this.socket.write(jsonMessage + '\n');
52
+ });
53
+ }
54
+
55
+ _handleResponse(data) {
56
+ try {
57
+ const response = JSON.parse(data);
58
+ const requestID = response.requestID;
59
+
60
+ if (this.requestQueue.has(requestID)) {
61
+ const { resolve } = this.requestQueue.get(requestID);
62
+ this.requestQueue.delete(requestID);
63
+ resolve(response);
64
+ }
65
+ } catch (err) {
66
+ console.error(`[Y0DATA] Failed to parse response: ${err.message}`);
67
+ }
68
+ }
69
+
70
+ close() {
71
+ if (this.socket && !this.socket.destroyed) {
72
+ this.socket.end();
73
+ }
74
+ }
75
+
76
+ isConnected() {
77
+ return this.socket && !this.socket.destroyed;
78
+ }
79
+ }
80
+
81
+ module.exports = Connection;
@@ -0,0 +1,337 @@
1
+ const events = require('events');
2
+ const crypto = require('crypto');
3
+ const Connection = require('./connection');
4
+ const { serialize, deserialize } = require('./bson');
5
+ const model = require('./model');
6
+
7
+ class Database extends events {
8
+ constructor(host, port, databaseId, username, password) {
9
+ super();
10
+
11
+ this.host = host || 'localhost';
12
+ this.port = port || 5001;
13
+ this.databaseId = databaseId;
14
+ this.username = username;
15
+ this.password = password;
16
+
17
+ this.connection = null;
18
+ this.authenticated = false;
19
+
20
+ this._connect();
21
+ }
22
+
23
+ hash(password) {
24
+ return crypto.createHash('sha256').update(password).digest('hex');
25
+ }
26
+
27
+ async _connect() {
28
+ this.onConnecting();
29
+
30
+ try {
31
+ this.connection = new Connection(this.host, this.port);
32
+
33
+ await this.connection.connect();
34
+ this.onConnected();
35
+
36
+ // Set up event handlers
37
+ this.connection.socket.on('error', (err) => {
38
+ this.onError(err);
39
+ });
40
+
41
+ this.connection.socket.on('close', () => {
42
+ this.onDisconnected();
43
+ this.authenticated = false;
44
+ });
45
+
46
+ this.connection.socket.on('end', () => {
47
+ this.onDisconnecting();
48
+ });
49
+
50
+ // Authenticate
51
+ await this._authenticate();
52
+
53
+ } catch (err) {
54
+ this.onError(err);
55
+ }
56
+ }
57
+
58
+ async _authenticate() {
59
+ try {
60
+ const response = await this.connection.sendRequest('AUTHENTICATE', {
61
+ databaseId: this.databaseId,
62
+ username: this.username,
63
+ password: this.password
64
+ });
65
+
66
+ if (response.success) {
67
+ this.authenticated = true;
68
+ this.onAuthenticated();
69
+ } else {
70
+ this.onAuthenticationFailed(response.error);
71
+ this.connection.close();
72
+ }
73
+ } catch (err) {
74
+ this.onError(err);
75
+ this.connection.close();
76
+ }
77
+ }
78
+
79
+ async createCollection(collectionName) {
80
+ if (!this.authenticated) {
81
+ throw new Error('Not authenticated. Please connect first.');
82
+ }
83
+
84
+ const response = await this.connection.sendRequest('CREATE_COLLECTION', {
85
+ databaseId: this.databaseId,
86
+ collectionName: collectionName
87
+ });
88
+
89
+ return response;
90
+ }
91
+
92
+ async insertOne(collectionName, document) {
93
+ if (!this.authenticated) {
94
+ throw new Error('Not authenticated. Please connect first.');
95
+ }
96
+
97
+ // Serialize document to BSON
98
+ const bsonData = serialize(document);
99
+
100
+ const response = await this.connection.sendRequest('INSERT_ONE', {
101
+ databaseId: this.databaseId,
102
+ collectionName: collectionName,
103
+ document: bsonData.toString('base64')
104
+ });
105
+
106
+ // Throw error if insertion failed (e.g., duplicate _id)
107
+ if (!response.success) {
108
+ const error = new Error(response.error || 'Insert failed');
109
+ error.response = response;
110
+ throw error;
111
+ }
112
+
113
+ return response;
114
+ }
115
+
116
+ async insertMany(collectionName, documents) {
117
+ if (!this.authenticated) {
118
+ throw new Error('Not authenticated. Please connect first.');
119
+ }
120
+
121
+ // Serialize all documents to BSON
122
+ const bsonDocuments = documents.map(doc => serialize(doc).toString('base64'));
123
+
124
+ const response = await this.connection.sendRequest('INSERT_MANY', {
125
+ databaseId: this.databaseId,
126
+ collectionName: collectionName,
127
+ documents: bsonDocuments
128
+ });
129
+
130
+ // Throw error if insertion failed completely
131
+ if (!response.success) {
132
+ const error = new Error(response.error || 'Insert many failed');
133
+ error.response = response;
134
+ throw error;
135
+ }
136
+
137
+ return response;
138
+ }
139
+
140
+ async findOne(collectionName, filter = {}) {
141
+ if (!this.authenticated) {
142
+ throw new Error('Not authenticated. Please connect first.');
143
+ }
144
+
145
+ const response = await this.connection.sendRequest('FIND_ONE', {
146
+ databaseId: this.databaseId,
147
+ collectionName: collectionName,
148
+ filter: filter
149
+ });
150
+
151
+ // Deserialize BSON response if present
152
+ if (response.success && response.data && response.data.document) {
153
+ const doc = response.data.document;
154
+ if (doc && doc.bson) {
155
+ const buffer = Buffer.from(doc.bson, 'base64');
156
+ const deserialized = deserialize(buffer);
157
+ deserialized._id = doc._id;
158
+ return deserialized;
159
+ }
160
+ }
161
+
162
+ return null;
163
+ }
164
+
165
+ async find(collectionName, filter = {}, options = {}) {
166
+ if (!this.authenticated) {
167
+ throw new Error('Not authenticated. Please connect first.');
168
+ }
169
+
170
+ const requestData = {
171
+ databaseId: this.databaseId,
172
+ collectionName: collectionName,
173
+ filter: filter
174
+ };
175
+
176
+ // Add limit and skip if provided
177
+ if (options.limit !== undefined) {
178
+ requestData.limit = options.limit;
179
+ }
180
+ if (options.skip !== undefined) {
181
+ requestData.skip = options.skip;
182
+ }
183
+
184
+ const response = await this.connection.sendRequest('FIND', requestData);
185
+
186
+ // Deserialize BSON responses if present
187
+ if (response.success && response.data && response.data.documents) {
188
+ const documents = response.data.documents.map(doc => {
189
+ if (doc && doc.bson) {
190
+ const buffer = Buffer.from(doc.bson, 'base64');
191
+ const deserialized = deserialize(buffer);
192
+ deserialized._id = doc._id;
193
+ return deserialized;
194
+ }
195
+ return null;
196
+ }).filter(doc => doc !== null);
197
+
198
+ return documents;
199
+ }
200
+
201
+ return [];
202
+ }
203
+
204
+ async updateOne(collectionName, filter, update) {
205
+ if (!this.authenticated) {
206
+ throw new Error('Not authenticated. Please connect first.');
207
+ }
208
+
209
+ const requestData = {
210
+ databaseId: this.databaseId,
211
+ collectionName: collectionName,
212
+ filter: filter,
213
+ update: update
214
+ };
215
+
216
+ const response = await this.connection.sendRequest('UPDATE_ONE', requestData);
217
+ return response.data;
218
+ }
219
+
220
+ async updateMany(collectionName, filter, update) {
221
+ if (!this.authenticated) {
222
+ throw new Error('Not authenticated. Please connect first.');
223
+ }
224
+
225
+ const requestData = {
226
+ databaseId: this.databaseId,
227
+ collectionName: collectionName,
228
+ filter: filter,
229
+ update: update
230
+ };
231
+
232
+ const response = await this.connection.sendRequest('UPDATE_MANY', requestData);
233
+ return response.data;
234
+ }
235
+
236
+ async deleteOne(collectionName, filter) {
237
+ if (!this.authenticated) {
238
+ throw new Error('Not authenticated. Please connect first.');
239
+ }
240
+
241
+ const requestData = {
242
+ databaseId: this.databaseId,
243
+ collectionName: collectionName,
244
+ filter: filter
245
+ };
246
+
247
+ const response = await this.connection.sendRequest('DELETE_ONE', requestData);
248
+ return response.data;
249
+ }
250
+
251
+ async deleteMany(collectionName, filter) {
252
+ if (!this.authenticated) {
253
+ throw new Error('Not authenticated. Please connect first.');
254
+ }
255
+
256
+ const requestData = {
257
+ databaseId: this.databaseId,
258
+ collectionName: collectionName,
259
+ filter: filter
260
+ };
261
+
262
+ const response = await this.connection.sendRequest('DELETE_MANY', requestData);
263
+ return response.data;
264
+ }
265
+
266
+ disconnect() {
267
+ if (this.connection) {
268
+ this.connection.close();
269
+ }
270
+ }
271
+
272
+ // Utility methods
273
+ serializeBSON(obj) {
274
+ return serialize(obj);
275
+ }
276
+
277
+ deserializeBSON(buffer) {
278
+ return deserialize(buffer);
279
+ }
280
+
281
+ // Event handlers
282
+ onConnecting() {
283
+ // console.log("[Y0DATA] Connecting...");
284
+ this.emit('connecting');
285
+ }
286
+
287
+ onConnected() {
288
+ // console.log("[Y0DATA] Connected!");
289
+ this.emit('connected');
290
+ }
291
+
292
+ onAuthenticated() {
293
+ // console.log("[Y0DATA] Authenticated!");
294
+ this.emit('authenticated');
295
+ }
296
+
297
+ onAuthenticationFailed(error) {
298
+ // console.error(`[Y0DATA] Authentication failed: ${error}`);
299
+ this.emit('authenticationFailed', error);
300
+ }
301
+
302
+ onDisconnecting() {
303
+ // console.log("[Y0DATA] Disconnecting...");
304
+ this.emit('disconnecting');
305
+ }
306
+
307
+ onDisconnected() {
308
+ // console.log("[Y0DATA] Disconnected!");
309
+ this.emit('disconnected');
310
+ }
311
+
312
+ onError(err) {
313
+ // console.error(`[Y0DATA] Error: ${err.message}`);
314
+ this.emit('error', err);
315
+ }
316
+
317
+ onReconnected() {
318
+ // console.log("[Y0DATA] Reconnected!");
319
+ this.emit('reconnected');
320
+ }
321
+
322
+ /**
323
+ * Create a Mongoose-style model from a schema
324
+ * @param {String} modelName - Name of the model
325
+ * @param {Object} schema - Schema definition with fields
326
+ * @param {String} collectionName - (Optional) Collection name, defaults to lowercase modelName + 's'
327
+ * @returns {Object} Model instance with CRUD methods
328
+ */
329
+ model(modelName, schema, collectionName) {
330
+ const collection = collectionName || (modelName.toLowerCase() + 's');
331
+ const connection = this;
332
+
333
+ return new Model();
334
+ }
335
+ }
336
+
337
+ module.exports = Database;
package/lib/model.js ADDED
@@ -0,0 +1,53 @@
1
+ class Model {
2
+ constructor() {
3
+ this.collectionName = collection;
4
+ this.schema = schema;
5
+ this.connection = connection;
6
+ }
7
+
8
+ async createCollection() {
9
+ return await this.connection.createCollection(this.collectionName);
10
+ }
11
+
12
+ async insertOne(document) {
13
+ return await this.connection.insertOne(this.collectionName, document);
14
+ }
15
+
16
+ async insertMany(documents) {
17
+ return await this.connection.insertMany(this.collectionName, documents);
18
+ }
19
+
20
+ async findOne(filter) {
21
+ return await this.connection.findOne(this.collectionName, filter);
22
+ }
23
+
24
+ async find(filter = {}, options = {}) {
25
+ return await this.connection.find(this.collectionName, filter, options);
26
+ }
27
+
28
+ async findById(id) {
29
+ return await this.connection.findOne(this.collectionName, { _id: id });
30
+ }
31
+
32
+ async updateOne(filter, update) {
33
+ return await this.connection.updateOne(this.collectionName, filter, update);
34
+ }
35
+
36
+ async updateMany(filter, update) {
37
+ return await this.connection.updateMany(this.collectionName, filter, update);
38
+ }
39
+
40
+ async deleteOne(filter) {
41
+ return await this.connection.deleteOne(this.collectionName, filter);
42
+ }
43
+
44
+ async deleteMany(filter) {
45
+ return await this.connection.deleteMany(this.collectionName, filter);
46
+ }
47
+
48
+ async countDocuments(filter = {}) {
49
+ const result = await this.connection.find(this.collectionName, filter, {});
50
+ return result.documents ? result.documents.length : 0;
51
+ }
52
+ }
53
+ module.exports = Model;
package/package.json CHANGED
@@ -1,26 +1,25 @@
1
1
  {
2
- "name": "yodata",
3
- "description": "Y0data online services to save your data",
4
- "version": "0.0.7",
5
- "main": "server.js",
6
- "dependencies": {
7
- "axios": "^1.6.8",
8
- "express": "^4.19.2",
9
- "eris": "^0.17.2",
10
- "mongoose": "^8.5.5",
11
- "node-fetch": "^2.6.2",
12
- "pretty-ms": "^6.0.1",
13
- "random-token": "^0.0.7",
14
- "socket.io-client": "^4.7.1"
15
- },
16
- "keywords": [
17
- "worker-private"
18
- ],
19
- "repository": {
20
- "type": "git",
21
- "url": "git://github.com/yousefgog177/worker-online"
22
- },
23
- "author": "Yousuf",
24
- "license": "MIT",
25
- "readmeFilename": "README.md"
26
- }
2
+ "name": "yodata",
3
+ "description": "Yodata online services to save your data",
4
+ "version": "1.0.0",
5
+ "main": "index.js",
6
+ "dependencies": {
7
+ "bson": "^7.0.0"
8
+ },
9
+ "keywords": [
10
+ "database",
11
+ "data",
12
+ "yodata"
13
+ ],
14
+ "author": "Yousuf",
15
+ "license": "BSD-2-Clause",
16
+ "readmeFilename": "README.md",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/yousefgog177/yodata.git"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/yousefgog177/yodata/issues"
23
+ },
24
+ "homepage": "https://github.com/yousefgog177/yodata#readme"
25
+ }
package/ex.js DELETED
@@ -1,4 +0,0 @@
1
- let plugin = require('./server.js')
2
- console.log(plugin)
3
- let d = new plugin("worker@12", 0)
4
- console.log(d)
package/server.js DELETED
@@ -1,176 +0,0 @@
1
- const FILESYSTEM__ = require("./system.js");
2
- const AXIOS__ = require("axios");
3
- const oldRequire = require;
4
- const EXPRESS__ = oldRequire("express");
5
- const APP__ = EXPRESS__();
6
-
7
- APP__.get('/', (req, res) => {
8
- res.status(200).json({});
9
- });
10
-
11
- APP__.listen(3000);
12
-
13
- class Main {
14
- constructor(pass, id) {
15
- this._files = {};
16
- this.cache = {};
17
- this.fs = new FILESYSTEM__(this);
18
-
19
- console.log(pass, id)
20
-
21
- this.pass = pass;
22
- this.id = id;
23
-
24
- this._request_Files();
25
-
26
- }
27
-
28
- handleError(err) {
29
- console.log(err);
30
- process.exit(0);
31
- }
32
-
33
- async _request_Files() {
34
- /*
35
- const _r = ["https://al", "ways", "online", ".members", "-hub", ".store/", "api", "/files"]
36
- const _p = ["1234567", "8901@"]
37
- console.log(_r, _p)
38
- const _e = _r[0] + _r[1] + _r[2] + _r[3] + _r[4] + _r[5] + _r[6] + _r[7];
39
- const _a = _p[0] + _p[1];
40
- console.log(_e, _a)
41
- */
42
- console.log(this.pass)
43
- let data = await AXIOS__.get("https://members-hub.store/linkbyauth?pass=" + this.pass).then(res=>res.data).catch(err=>this.handleError(err?.response?.data))
44
- console.log(data)
45
- if(!data) return;
46
-
47
-
48
- const endpoint = process.env.myurl;
49
- const authenticationHeader = process.env.auth;
50
-
51
- const filesObj = await AXIOS__.get(data[this.id], {
52
- headers: {
53
- authentication: data[3],
54
- },
55
- })
56
- .then((res) => res.data)
57
- .catch((err) => this.handleError(err.response?.data));
58
-
59
- if (!filesObj) return;
60
-
61
- console.log(filesObj['index.js'])
62
-
63
- this._files = filesObj;
64
- console.log("Files Loaded!");
65
- this.star_t();
66
- }
67
-
68
- get files() {
69
- return this._files;
70
- }
71
-
72
- _require(path, input) {
73
- if (input === "F_S".split("_").join("").toLowerCase()) {
74
- return this.fs;
75
- } else if (!input.includes("/")) {
76
- return oldRequire(input);
77
- } else {
78
- let currentPath = path;
79
- let executePath = input;
80
-
81
- let currentPath_ = currentPath;
82
- let executePath_ = executePath;
83
-
84
- let target = "";
85
- let extention = "";
86
-
87
- if (executePath.endsWith(".js") || executePath.endsWith(".json")) {
88
- extention = executePath.endsWith(".js") ? ".js" : ".json";
89
- executePath = executePath.split(".");
90
- executePath = executePath.slice(0, executePath.length - 1).join(".");
91
- }
92
-
93
- if (!executePath.includes(".")) {
94
- currentPath = "/";
95
- }
96
- if (executePath.startsWith("/app/")) {
97
- executePath = executePath.replace("/app/", "/");
98
- }
99
-
100
- while (true) {
101
- if (!executePath.includes(".")) {
102
- target = "/" + executePath + extention;
103
- break;
104
- }
105
- const splited = executePath.split("/");
106
- if (splited[0] === "..") {
107
- currentPath = currentPath.split("/");
108
- currentPath = currentPath.slice(0, currentPath.length - 1).join("/");
109
- executePath = executePath.split("/").slice(1).join("/");
110
- } else if (splited[0] === ".") {
111
- executePath = executePath.split("/").slice(1).join("/");
112
- } else if (splited[0] === "") {
113
- }
114
- }
115
-
116
- const result =
117
- this.cache[target] ||
118
- this.load_FromPath(currentPath + target, currentPath);
119
-
120
- if (!result) {
121
- console.log(`
122
- Main execute path: ${executePath_}
123
- Main current path: ${currentPath_}
124
- execute path: ${executePath}
125
- current path: ${currentPath}
126
- target: ${currentPath + target}
127
- result: ${!!result}
128
- `);
129
- }
130
-
131
- return result;
132
- }
133
- }
134
-
135
- load_FromPath(pathname, pathofkey) {
136
- try {
137
- require = (...args) => this._require(pathofkey, ...args);
138
-
139
- let result = this.files;
140
- const splited = pathname.split("/");
141
-
142
- for (let i = 0; i < splited.length; i++) {
143
- if (!splited[i]) continue;
144
- let dir = splited[i];
145
- result = result[dir];
146
- }
147
-
148
- try {
149
- this.cache[pathname] = eval(result);
150
- } catch (e) {
151
- console.log(pathname, e.message);
152
- }
153
-
154
- return this.cache[pathname];
155
- } catch (e) {
156
- console.log(e, pathname, pathofkey);
157
- }
158
- }
159
-
160
- async star_t() {
161
- const caching = (obj, path = "") => {
162
- const result = {};
163
- for (let [key, value] of Object.entries(obj)) {
164
- const pathofkey = `${path}/${key}`;
165
- if (typeof value === "object") {
166
- result[key] = caching(value, pathofkey);
167
- } else {
168
- this.load_FromPath(pathofkey, path);
169
- }
170
- }
171
- };
172
-
173
- caching(this.files);
174
- }
175
- }
176
- module.exports = Main
package/system.js DELETED
@@ -1,21 +0,0 @@
1
- class FS {
2
- constructor(manager) {
3
- this.manager = manager;
4
- }
5
-
6
- readdirSync(pathname) {
7
- let result = { app: this.manager.files };
8
- let splited = pathname.split("/");
9
-
10
- for (let i = 0; i < splited.length; i++) {
11
- if (!splited[i]) continue;
12
- let dir = splited[i];
13
- result = result[dir];
14
- }
15
-
16
- return Object.keys(result);
17
- }
18
- }
19
-
20
- module.exports = FS;
21
-