Source: index.js

const path = require('path')
const EventEmitter = require('events')

const AxideConnection = require(path.join(__dirname, 'connection', 'AxideConnection.js'))

/**
* AxideClient class. Is used to connect to and access axideDB instances.
*/
class AxideClient extends EventEmitter {
	/**
	* Create an Axide client
	* @param {String} host
	* @param {number} [port=5135]
	*/
	constructor (host, port) {
		super() // Initialize EventEmitter

		this.connection = new AxideConnection(host, port)

		this.connection.once('connected', () => {
			this.emit('connect')
		})

		this.idIncrement = 0
	}

	/**
	* Send content and get response
	* @private
	*/
	_sendRetrieve (content) {
		return new Promise((resolve, reject) => {
			this.connection.once(this.idIncrement, (body) => {
				resolve(body)
			})

			this.connection.send(Object.assign(content, {
				'id': this.idIncrement
			}))

			this.idIncrement++
		})
	}

	/**
	* Create a new formula
	* @param {String} name - Name of the created formula
	* @returns {Promise} Resolves with boolean 'did already exist' property or rejects with error.
	*/
	async createFormula (name) {
		let response = await this._sendRetrieve({
			'method': 'createFormula',
			name
		})

		if (response.error) {
			throw new Error(response.error)
		}
		else {
			return (response.success === 'exists' ? true : false)
		}
	}

	/**
	* Create a new hash
	* @param {String} formula - Formula in which the hash will be created
	* @param {String} name - Name of the created hash
	* @param {Object} [value] - Hash values
	* @returns {Promise} Resolves with no properties or rejects with error.
	*/
	async createHash(formula, name, value) {
		let response = await this._sendRetrieve({
			'method': 'createHash',
			formula,
			name,
			value
		})

		if (response.error) {
			throw new Error(response.error)
		}
		else {
			return
		}
	}

	/**
	* Delete a formula
	* @param {String} name - Name of the formula to delete
	* @returns {Promise} Resolves with no properties or rejects with error.
	*/
	async deleteFormula (name) {
		let response = await this._sendRetrieve({
			'method': 'deleteFormula',
			name
		})

		if (response.error) {
			throw new Error(response.error)
		}
		else {
			return
		}
	}

	/**
	* Delete a hash
	* @param {String} formula - Formula in which the hash will be created
	* @param {String} name - Name of the hash to delete
	* @returns {Promise} Resolves with no properties or rejects with error.
	*/
	async deleteHash(formula, name) {
		let response = await this._sendRetrieve({
			'method': 'deleteHash',
			formula,
			name
		})

		if (response.error) {
			throw new Error(response.error)
		}
		else {
			return
		}
	}

	/**
	* Test if an entity exists
	* @param {String} [formula] - If type is 'hash', specifies in which formula to look for the hash.
	* @param {String} name - Name of the entity
	* @param {String} type - Type of the entity ('formula', 'hash')
	* @returns {Promise} Resolves with boolean representing existance of entity or rejects with error.
	*/
	async exists (formula, name, type) {
		let response = await this._sendRetrieve({
			'method': 'exists',
			formula,
			name,
			type
		})

		if (response.error) {
			throw new Error(response.error)
		}
		else {
			return response.exists
		}
	}

	/**
	* Get the names of entities within a formula
	* @param {String} name - Name of formula
	* @returns {Promise} Resolves with list of entity names or rejects with error.
	*/
	async getFormula (name) {
		let response = await this._sendRetrieve({
			'method': 'getFormula',
			name
		})

		if (response.error) {
			throw new Error(response.error)
		}
		else {
			return response.entities
		}
	}

	/**
	* Get the names of all formulas in database
	* @returns {Promise} Resolves with list of formula names or rejects with error.
	*/
	async getFormulas () {
		let response = await this._sendRetrieve({
			'method': 'getFormulas'
		})

		if (response.error) {
			throw new Error(response.error)
		}
		else {
			return response.formulas
		}
	}

	/**
	* Get the full object of a hash (resource intensive)
	* @param {String} formula
	* @param {String} name - Name of the hash to retrieve
	* @returns {Promise} Resolves with full hash object or rejects with error.
	*/
	async getHash (formula, name) {
		let response = await this._sendRetrieve({
			'method': 'getHash',
			formula,
			name
		})

		if (response.error) {
			throw new Error(response.error)
		}
		else {
			return response.data
		}
	}

	/**
	* Get the value of a hash property
	* @param {String} formula
	* @param {String} hash
	* @param {String} name - Name of the hash property whose value should be retrieved
	* @returns {Promise} Resolves with hash property value or rejects with error.
	*/
	async getHashProperty (formula, hash, name) {
		let response = await this._sendRetrieve({
			'method': 'getHashProperty',
			formula,
			hash,
			name
		})

		if (response.error) {
			throw new Error(response.error)
		}
		else {
			return response.value
		}
	}

	/**
	* Set the value of a hash property
	* @param {String} formula
	* @param {String} hash
	* @param {String} name - Name of the hash property whose value will be set
	* @param {String} value - New value of the hash property. (If object, will usually be stringified by DB.)
	* @returns {Promise} Resolves with hash property value or rejects with error.
	*/
	async setHashProperty (formula, hash, name, value) {
		let response = await this._sendRetrieve({
			'method': 'getHashProperty',
			formula,
			hash,
			name,
			value
		})

		if (response.error) {
			throw new Error(response.error)
		}
		else {
			return
		}
	}
}

module.exports = Axide