maazdb-js 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 +58 -0
- package/examples/basic.js +40 -0
- package/package.json +23 -0
- package/src/client.js +147 -0
- package/src/errors.js +22 -0
- package/src/protocol.js +20 -0
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
|
|
2
|
+
# MaazDB-JS ๐ฉ
|
|
3
|
+
|
|
4
|
+
**The Official Node.js Driver for MaazDB**
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
`maazdb-js` is a high-performance, asynchronous Node.js client for MaazDB. It uses native Promises and Buffers to handle the binary protocol securely over TLS.
|
|
10
|
+
|
|
11
|
+
## ๐ฆ Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install maazdb-js
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## ๐ Usage
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
const MaazDB = require('maazdb-js');
|
|
21
|
+
|
|
22
|
+
async function run() {
|
|
23
|
+
const db = new MaazDB();
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
// Connect securely
|
|
27
|
+
await db.connect("127.0.0.1", 8888, "admin", "password");
|
|
28
|
+
|
|
29
|
+
// Run SQL
|
|
30
|
+
await db.query("CREATE DATABASE web_app;");
|
|
31
|
+
await db.query("USE web_app;");
|
|
32
|
+
|
|
33
|
+
const users = await db.query("SELECT * FROM users;");
|
|
34
|
+
console.log(users);
|
|
35
|
+
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.error(e);
|
|
38
|
+
} finally {
|
|
39
|
+
db.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
run();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## ๐งช Testing
|
|
47
|
+
|
|
48
|
+
1. Start your Rust Server.
|
|
49
|
+
2. Run the example:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
node examples/basic.js
|
|
53
|
+
```
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
Created for the MaazDB Ecosystem.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// FILE PATH: examples/basic.js
|
|
2
|
+
//npm link maazdb-js
|
|
3
|
+
const MaazDB = require('maazdb-js');
|
|
4
|
+
|
|
5
|
+
async function main() {
|
|
6
|
+
console.log("--- MaazDB Node.js Client ---");
|
|
7
|
+
|
|
8
|
+
const db = new MaazDB();
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
// 1. Connect
|
|
12
|
+
console.log("Connecting...");
|
|
13
|
+
await db.connect("127.0.0.1", 8888, "admin", "admin");
|
|
14
|
+
console.log("โ Connected via TLS 1.3");
|
|
15
|
+
|
|
16
|
+
// 2. Run Queries
|
|
17
|
+
const queries = [
|
|
18
|
+
"CREATE DATABASE node_test;",
|
|
19
|
+
"USE node_test;",
|
|
20
|
+
"CREATE TABLE js_users (id SERIAL PRIMARY KEY, name TEXT);",
|
|
21
|
+
"INSERT INTO js_users (name) VALUES ('Maaz');",
|
|
22
|
+
"INSERT INTO js_users (name) VALUES ('Waheed');",
|
|
23
|
+
"SELECT * FROM js_users;"
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
for (const sql of queries) {
|
|
27
|
+
console.log(`\nExecuting: ${sql}`);
|
|
28
|
+
const result = await db.query(sql);
|
|
29
|
+
console.log(`Server: ${result.trim()}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
} catch (err) {
|
|
33
|
+
console.error("โ Error:", err.message);
|
|
34
|
+
} finally {
|
|
35
|
+
db.close();
|
|
36
|
+
console.log("\nConnection closed.");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "maazdb-js",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official Node.js Driver for MaazDB",
|
|
5
|
+
"main": "src/client.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "node examples/basic.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"database",
|
|
11
|
+
"driver",
|
|
12
|
+
"maazdb",
|
|
13
|
+
"sql",
|
|
14
|
+
"tls"
|
|
15
|
+
],
|
|
16
|
+
"author": "Maaz",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/42Wor/maazdb-js.git"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
package/src/client.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
const tls = require('tls');
|
|
2
|
+
const {
|
|
3
|
+
PACKET_HANDSHAKE, PACKET_AUTH_OK, PACKET_AUTH_ERR,
|
|
4
|
+
PACKET_QUERY, PACKET_MSG, PACKET_DATA, DRIVER_SIG
|
|
5
|
+
} = require('./protocol');
|
|
6
|
+
const { AuthError, ProtocolError, MaazDBError } = require('./errors');
|
|
7
|
+
|
|
8
|
+
class MaazDB {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.socket = null;
|
|
11
|
+
this.connected = false;
|
|
12
|
+
this.buffer = Buffer.alloc(0); // Store incoming data chunks
|
|
13
|
+
this.currentResolve = null; // Promise resolver for the current query
|
|
14
|
+
this.currentReject = null; // Promise rejector for the current query
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Connects to the MaazDB server securely via TLS.
|
|
19
|
+
*/
|
|
20
|
+
connect(host, port, user, password) {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const options = {
|
|
23
|
+
host: host,
|
|
24
|
+
port: port,
|
|
25
|
+
rejectUnauthorized: false, // Allow self-signed certs (Dev Mode)
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
this.socket = tls.connect(options, () => {
|
|
29
|
+
// 1. Send Handshake immediately upon connection
|
|
30
|
+
const payload = `${user}\0${password}\0${DRIVER_SIG}`;
|
|
31
|
+
this._sendPacket(PACKET_HANDSHAKE, payload);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
this.socket.on('data', (data) => {
|
|
35
|
+
this._handleData(data);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
this.socket.on('error', (err) => {
|
|
39
|
+
this.connected = false;
|
|
40
|
+
if (this.currentReject) this.currentReject(err);
|
|
41
|
+
else reject(err);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
this.socket.on('close', () => {
|
|
45
|
+
this.connected = false;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// We hijack the first request to handle Auth
|
|
49
|
+
this.currentResolve = () => {
|
|
50
|
+
this.connected = true;
|
|
51
|
+
resolve(this);
|
|
52
|
+
};
|
|
53
|
+
this.currentReject = (err) => {
|
|
54
|
+
this.close();
|
|
55
|
+
reject(err);
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Sends a SQL query and returns the result string.
|
|
62
|
+
*/
|
|
63
|
+
query(sql) {
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
if (!this.connected) {
|
|
66
|
+
return reject(new MaazDBError("Not connected to server"));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Set the callbacks for when data arrives
|
|
70
|
+
this.currentResolve = resolve;
|
|
71
|
+
this.currentReject = reject;
|
|
72
|
+
|
|
73
|
+
this._sendPacket(PACKET_QUERY, sql);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
close() {
|
|
78
|
+
if (this.socket) {
|
|
79
|
+
this.socket.end();
|
|
80
|
+
this.socket.destroy();
|
|
81
|
+
}
|
|
82
|
+
this.connected = false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// --- Internal Helpers ---
|
|
86
|
+
|
|
87
|
+
_sendPacket(type, payloadStr) {
|
|
88
|
+
const payload = Buffer.from(payloadStr, 'utf8');
|
|
89
|
+
const length = payload.length;
|
|
90
|
+
|
|
91
|
+
// Header: [Type (1B)] [Length (4B Big Endian)]
|
|
92
|
+
const header = Buffer.alloc(5);
|
|
93
|
+
header.writeUInt8(type, 0);
|
|
94
|
+
header.writeUInt32BE(length, 1);
|
|
95
|
+
|
|
96
|
+
const packet = Buffer.concat([header, payload]);
|
|
97
|
+
this.socket.write(packet);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_handleData(chunk) {
|
|
101
|
+
// Append new chunk to our buffer
|
|
102
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
103
|
+
|
|
104
|
+
// Try to parse packets from the buffer
|
|
105
|
+
while (true) {
|
|
106
|
+
if (this.buffer.length < 5) return; // Wait for more data
|
|
107
|
+
|
|
108
|
+
// Read Header
|
|
109
|
+
const type = this.buffer.readUInt8(0);
|
|
110
|
+
const length = this.buffer.readUInt32BE(1);
|
|
111
|
+
|
|
112
|
+
// Check if we have the full payload
|
|
113
|
+
if (this.buffer.length < 5 + length) return; // Wait for more data
|
|
114
|
+
|
|
115
|
+
// Extract Payload
|
|
116
|
+
const payloadBuffer = this.buffer.subarray(5, 5 + length);
|
|
117
|
+
const payloadStr = payloadBuffer.toString('utf8');
|
|
118
|
+
|
|
119
|
+
// Remove this packet from the buffer
|
|
120
|
+
this.buffer = this.buffer.subarray(5 + length);
|
|
121
|
+
|
|
122
|
+
// Handle the packet
|
|
123
|
+
this._processPacket(type, payloadStr);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
_processPacket(type, msg) {
|
|
128
|
+
if (type === PACKET_AUTH_OK) {
|
|
129
|
+
if (this.currentResolve) this.currentResolve("Authenticated");
|
|
130
|
+
}
|
|
131
|
+
else if (type === PACKET_AUTH_ERR) {
|
|
132
|
+
if (this.currentReject) this.currentReject(new AuthError(msg));
|
|
133
|
+
}
|
|
134
|
+
else if (type === PACKET_MSG || type === PACKET_DATA) {
|
|
135
|
+
if (this.currentResolve) this.currentResolve(msg);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
if (this.currentReject) this.currentReject(new ProtocolError(`Unknown Packet: ${type}`));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Reset callbacks
|
|
142
|
+
this.currentResolve = null;
|
|
143
|
+
this.currentReject = null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
module.exports = MaazDB;
|
package/src/errors.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class MaazDBError extends Error {
|
|
2
|
+
constructor(message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = "MaazDBError";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
class AuthError extends MaazDBError {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "AuthError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class ProtocolError extends MaazDBError {
|
|
16
|
+
constructor(message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = "ProtocolError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = { MaazDBError, AuthError, ProtocolError };
|
package/src/protocol.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Protocol Constants
|
|
2
|
+
const PACKET_HANDSHAKE = 0x10;
|
|
3
|
+
const PACKET_AUTH_OK = 0x11;
|
|
4
|
+
const PACKET_AUTH_ERR = 0x12;
|
|
5
|
+
const PACKET_QUERY = 0x20;
|
|
6
|
+
const PACKET_MSG = 0x02;
|
|
7
|
+
const PACKET_DATA = 0x03;
|
|
8
|
+
|
|
9
|
+
// Driver Signature
|
|
10
|
+
const DRIVER_SIG = "maazdb-nodejs-driver-v1";
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
PACKET_HANDSHAKE,
|
|
14
|
+
PACKET_AUTH_OK,
|
|
15
|
+
PACKET_AUTH_ERR,
|
|
16
|
+
PACKET_QUERY,
|
|
17
|
+
PACKET_MSG,
|
|
18
|
+
PACKET_DATA,
|
|
19
|
+
DRIVER_SIG
|
|
20
|
+
};
|