Comparing version 0.0.1-beta to 0.0.2-beta
{ | ||
"name": "pyxisdb", | ||
"version": "0.0.1-beta", | ||
"version": "0.0.2-beta", | ||
"description": "A real-time database package for communicating with Pyxiscloud server using WebSockets", | ||
"main": "index.js", | ||
"main": "pyxisdb.cjs", | ||
"module": "pyxisdb.js", | ||
"type": "module", | ||
"exports": { | ||
".": { | ||
"require": "./pyxisdb.cjs", | ||
"import": "./pyxisdb.js", | ||
"default": "./pyxisdb.cjs" | ||
} | ||
}, | ||
"scripts": { | ||
@@ -39,4 +48,6 @@ "start": "node index.js", | ||
"files": [ | ||
"index.js", | ||
"pyxisdb.js", | ||
"pyxisdb.cjs", | ||
"lib/esm/pyxis.js", | ||
"lib/cjs/pyxis.cjs", | ||
"README.md", | ||
@@ -48,4 +59,7 @@ "LICENSE" | ||
"name": "i._.become_a_devil" | ||
}, | ||
{ | ||
"name": "Iscordian" | ||
} | ||
] | ||
} | ||
} |
350
pyxisdb.js
@@ -1,357 +0,33 @@ | ||
// pyxisdb.js | ||
const WebSocket = require('ws'); | ||
import PyxisDB from './lib/esm/pyxisdb'; | ||
class PyxisDB { | ||
constructor() { | ||
this.url = null; | ||
this.ws = null; | ||
this.isConnected = false; | ||
this.schemas = new Map(); | ||
this.models = new Map(); | ||
this.connectionPromise = null; | ||
this.reconnectAttempts = 0; | ||
this.maxReconnectAttempts = 5; | ||
this.reconnectDelay = 1000; | ||
this.messageCallbacks = new Map(); | ||
this.operationQueue = []; | ||
} | ||
connect(url) { | ||
if (this.isConnected) { | ||
return Promise.resolve(this.ping); | ||
} | ||
this.url = url; | ||
return this.establishConnection(); | ||
} | ||
const pyx = { | ||
async establishConnection() { | ||
this.connectionPromise = new Promise((resolve, reject) => { | ||
this.ws = new WebSocket(this.url, { | ||
mask: true, | ||
skipUTF8Validation: true | ||
}); | ||
connect: async (url) => { | ||
this.ws.on('open', async () => { | ||
this.isConnected = true; | ||
this.reconnectAttempts = 0; | ||
this.reconnectDelay = 1000; | ||
try { | ||
const startTime = Date.now(); | ||
this.ws.ping('', true, (error) => { | ||
if (error) { | ||
reject(error); | ||
} else { | ||
this.ping = Date.now() - startTime; | ||
resolve(this.ping); | ||
this.processQueuedOperations(); | ||
} | ||
}); | ||
}); | ||
const ping = await PyxisDB.connect(url); | ||
this.ws.on('error', (error) => { | ||
this.handleDisconnection(reject); | ||
}); | ||
return pyx; | ||
this.ws.on('close', () => { | ||
this.handleDisconnection(reject); | ||
}); | ||
this.setupHeartbeat(); | ||
this.ws.on('message', (data) => { | ||
try { | ||
const response = JSON.parse(data); | ||
if (response.requestId && this.messageCallbacks.has(response.requestId)) { | ||
const { resolve, reject } = this.messageCallbacks.get(response.requestId); | ||
if (response.status === 'success') { | ||
resolve(response.data); | ||
} else { | ||
reject(new Error(response.message)); | ||
} | ||
this.messageCallbacks.delete(response.requestId); | ||
} | ||
} catch (error) { | ||
console.error('Error processing server response:', error); | ||
} | ||
}); | ||
}); | ||
return this.connectionPromise; | ||
} | ||
handleDisconnection(reject) { | ||
this.isConnected = false; | ||
this.ping = null; | ||
if (this.reconnectAttempts < this.maxReconnectAttempts) { | ||
setTimeout(() => { | ||
this.reconnectAttempts++; | ||
this.reconnectDelay *= 2; | ||
this.establishConnection(); | ||
}, this.reconnectDelay); | ||
} else { | ||
reject(new Error('Failed to maintain connection to server')); | ||
} | ||
} | ||
setupHeartbeat() { | ||
const heartbeatInterval = setInterval(() => { | ||
if (this.isConnected) { | ||
this.ws.ping('', true, (error) => { | ||
if (error) { | ||
clearInterval(heartbeatInterval); | ||
} | ||
}); | ||
} else { | ||
clearInterval(heartbeatInterval); | ||
} | ||
}, 30000); | ||
this.ws.on('close', () => { | ||
clearInterval(heartbeatInterval); | ||
}); | ||
} | ||
schema(schemaDefinition, collectionName) { | ||
return this.ensureConnection(() => { | ||
const schema = new Schema(schemaDefinition, this, collectionName); | ||
this.schemas.set(collectionName, schema); | ||
return schema; | ||
}); | ||
} | ||
model(collectionName, schema) { | ||
return this.ensureConnection(() => { | ||
if (!schema) { | ||
schema = this.schemas.get(collectionName); | ||
if (!schema) { | ||
throw new Error(`Schema for collection "${collectionName}" not found. Define it first using pyx.schema().`); | ||
} | ||
} | ||
const model = new Model(collectionName, schema, this); | ||
this.models.set(collectionName, model); | ||
return model; | ||
}); | ||
} | ||
async sendMessage(message) { | ||
return this.ensureConnection(async () => { | ||
if (!this.isConnected) { | ||
throw new Error('Not connected to server'); | ||
} | ||
return new Promise((resolve, reject) => { | ||
const requestId = Math.random().toString(36).substr(2, 9); | ||
message.requestId = requestId; | ||
this.messageCallbacks.set(requestId, { resolve, reject }); | ||
this.ws.send(JSON.stringify(message), { mask: true }, (error) => { | ||
if (error) { | ||
this.messageCallbacks.delete(requestId); | ||
reject(error); | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
ensureConnection(operation) { | ||
if (this.isConnected) { | ||
return operation(); | ||
} else { | ||
return new Promise((resolve, reject) => { | ||
this.operationQueue.push({ operation, resolve, reject }); | ||
}); | ||
} | ||
} | ||
async processQueuedOperations() { | ||
while (this.operationQueue.length > 0) { | ||
const { operation, resolve, reject } = this.operationQueue.shift(); | ||
try { | ||
const result = await operation(); | ||
resolve(result); | ||
} catch (error) { | ||
reject(error); | ||
} | ||
} | ||
} | ||
} | ||
class Schema { | ||
constructor(schemaDefinition, pyxisDB, collectionName) { | ||
this.schemaDefinition = schemaDefinition; | ||
this.pyxisDB = pyxisDB; | ||
this.collectionName = collectionName; | ||
} | ||
async createOrUpdateSchema() { | ||
try { | ||
await this.pyxisDB.sendMessage({ | ||
type: 'CreateSchema', | ||
data: { | ||
collectionName: this.collectionName, | ||
schemaDefinition: this.schemaDefinition | ||
} | ||
}); | ||
} catch (error) { | ||
if (error.message === 'Schema already exists') { | ||
await this.updateSchema(); | ||
} else { | ||
throw error; | ||
} | ||
} | ||
} | ||
async updateSchema() { | ||
await this.pyxisDB.sendMessage({ | ||
type: 'UpdateSchema', | ||
data: { | ||
collectionName: this.collectionName, | ||
schemaDefinition: this.schemaDefinition | ||
} | ||
}); | ||
} | ||
console.error('Failed to connect to PyxisCloud:', error); | ||
validate(document, isUpdate = false) { | ||
for (const [field, definition] of Object.entries(this.schemaDefinition)) { | ||
if (!isUpdate && definition.required && !(field in document)) { | ||
throw new Error(`Field "${field}" is required.`); | ||
} | ||
throw error; | ||
if (field in document) { | ||
const value = document[field]; | ||
if (value === null || value === undefined) { | ||
if (!isUpdate) { | ||
throw new Error(`Field "${field}" cannot be null or undefined.`); | ||
} | ||
continue; | ||
} | ||
if (definition.type === 'number' && typeof value !== 'number') { | ||
throw new Error(`Field "${field}" must be a number.`); | ||
} | ||
if (definition.type === 'string' && typeof value !== 'string') { | ||
throw new Error(`Field "${field}" must be a string.`); | ||
} | ||
if (definition.type === 'boolean' && typeof value !== 'boolean') { | ||
throw new Error(`Field "${field}" must be a boolean.`); | ||
} | ||
if (definition.type === 'date' && !(value instanceof Date)) { | ||
throw new Error(`Field "${field}" must be a Date object.`); | ||
} | ||
if (definition.type === 'object' && typeof value !== 'object') { | ||
throw new Error(`Field "${field}" must be an object.`); | ||
} | ||
if (definition.type === 'array' && !Array.isArray(value)) { | ||
throw new Error(`Field "${field}" must be an array.`); | ||
} | ||
} | ||
} | ||
} | ||
validateUpdate(updateFields) { | ||
const fieldsToValidate = {}; | ||
for (const field in updateFields) { | ||
if (this.schemaDefinition[field]) { | ||
fieldsToValidate[field] = this.schemaDefinition[field]; | ||
} | ||
} | ||
}, | ||
const updateSchema = new Schema(fieldsToValidate, this.pyxisDB, this.collectionName); | ||
updateSchema.validate(updateFields, true); | ||
} | ||
} | ||
schema: (...args) => PyxisDB.schema(...args), | ||
class Model { | ||
constructor(collectionName, schema, pyxisDB) { | ||
this.collectionName = collectionName; | ||
this.schema = schema; | ||
this.pyxisDB = pyxisDB; | ||
} | ||
model: (...args) => PyxisDB.model(...args), | ||
async insert(document) { | ||
this.schema.validate(document); | ||
await this.schema.createOrUpdateSchema(); | ||
return this.pyxisDB.sendMessage({ | ||
type: 'Query', | ||
data: { | ||
collectionName: this.collectionName, | ||
operation: 'insert', | ||
document | ||
} | ||
}); | ||
} | ||
}; | ||
async find(query = {}) { | ||
await this.schema.createOrUpdateSchema(); | ||
return this.pyxisDB.sendMessage({ | ||
type: 'Query', | ||
data: { | ||
collectionName: this.collectionName, | ||
operation: 'find', | ||
query | ||
} | ||
}); | ||
} | ||
async update(query, updateFields) { | ||
this.schema.validateUpdate(updateFields); | ||
await this.schema.createOrUpdateSchema(); | ||
return this.pyxisDB.sendMessage({ | ||
type: 'Query', | ||
data: { | ||
collectionName: this.collectionName, | ||
operation: 'update', | ||
query, | ||
updateFields | ||
} | ||
}); | ||
} | ||
async delete(query) { | ||
await this.schema.createOrUpdateSchema(); | ||
return this.pyxisDB.sendMessage({ | ||
type: 'Query', | ||
data: { | ||
collectionName: this.collectionName, | ||
operation: 'delete', | ||
query | ||
} | ||
}); | ||
} | ||
async count(query = {}) { | ||
await this.schema.createOrUpdateSchema(); | ||
return this.pyxisDB.sendMessage({ | ||
type: 'Query', | ||
data: { | ||
collectionName: this.collectionName, | ||
operation: 'count', | ||
query | ||
} | ||
}); | ||
} | ||
async exists(field, value) { | ||
await this.schema.createOrUpdateSchema(); | ||
return this.pyxisDB.sendMessage({ | ||
type: 'Query', | ||
data: { | ||
collectionName: this.collectionName, | ||
operation: 'exists', | ||
field, | ||
value | ||
} | ||
}); | ||
} | ||
} | ||
module.exports = new PyxisDB(); | ||
export default pyx; |
# PyxisDB | ||
PyxisDB is a real-time database package for communicating with Pyxiscloud server. It provides a simple and efficient way to interact with your database using WebSocket connections. | ||
*PyxisDB* is a real-time database package for communicating with Pyxiscloud server. It provides a simple and efficient way to interact with your database using WebSocket connections. | ||
## Installation | ||
First you need to install, Check [PyxiCloud](https://github.com/Darknessking13/PyxiCloud) | ||
To install PyxisDB, use npm: | ||
```bash | ||
npm install pyxisdb@latest | ||
``` | ||
npm install pyxisdb | ||
``` | ||
@@ -18,2 +19,3 @@ ## Usage | ||
```javascript | ||
// import pyx from 'pyxisdb'; | ||
const pyx = require('pyxisdb'); | ||
@@ -86,2 +88,2 @@ | ||
This project is licensed under the MIT License. | ||
This project is licensed under the MIT License. |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
26783
6
654
88
Yes
1