http://git-wip-us.apache.org/repos/asf/ignite/blob/c56d16fb/modules/platforms/nodejs/lib/CacheConfiguration.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/lib/CacheConfiguration.js 
b/modules/platforms/nodejs/lib/CacheConfiguration.js
new file mode 100644
index 0000000..a4e4574
--- /dev/null
+++ b/modules/platforms/nodejs/lib/CacheConfiguration.js
@@ -0,0 +1,1733 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+const ComplexObjectType = require('./ObjectType').ComplexObjectType;
+const ObjectArrayType = require('./ObjectType').ObjectArrayType;
+const BinaryUtils = require('./internal/BinaryUtils');
+const BinaryReader = require('./internal/BinaryReader');
+const BinaryWriter = require('./internal/BinaryWriter');
+const ArgumentChecker = require('./internal/ArgumentChecker');
+const Errors = require('./Errors');
+
+/**
+ * Class representing Cache Key part of Ignite {@link CacheConfiguration}.
+ *
+ * All configuration settings are optional and have defaults which are defined 
on a server side.
+ *
+ * See Apache Ignite documentation for details of every configuration setting. 
+ */
+class CacheKeyConfiguration {
+
+    /**
+     * Public constructor.
+     *
+     * @param {string} [typeName=null]
+     * @param {string} [affinityKeyFieldName=null]
+     *
+     * @return {CacheKeyConfiguration} - new CacheKeyConfiguration instance.
+     */
+    constructor(typeName = null, affinityKeyFieldName = null) {
+        this._typeName = typeName;
+        this._affinityKeyFieldName = affinityKeyFieldName;
+    }
+
+    /**
+     *
+     *
+     * @param {string} typeName
+     *
+     * @return {CacheKeyConfiguration} - the same instance of the 
CacheKeyConfiguration.
+     */
+    setTypeName(typeName) {
+        this._typeName = typeName;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getTypeName() {
+        return this._typeName;
+    }
+
+    /**
+     *
+     *
+     * @param {string} affinityKeyFieldName
+     *
+     * @return {CacheKeyConfiguration} - the same instance of the 
CacheKeyConfiguration.
+     */
+    setAffinityKeyFieldName(affinityKeyFieldName) {
+        this._affinityKeyFieldName = affinityKeyFieldName;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getAffinityKeyFieldName() {
+        return this._affinityKeyFieldName;
+    }
+
+    /** Private methods */
+
+    /**
+     * @ignore
+     */
+    async _write(buffer) {
+        await BinaryWriter.writeString(buffer, this._typeName);
+        await BinaryWriter.writeString(buffer, this._affinityKeyFieldName);
+    }
+
+    /**
+     * @ignore
+     */
+    async _read(buffer) {
+        this._typeName = await BinaryReader.readObject(buffer);
+        this._affinityKeyFieldName = await BinaryReader.readObject(buffer);
+    }
+}
+
+/**
+ * Class representing one Query Entity element of Ignite {@link 
CacheConfiguration}.
+ *
+ * All configuration settings are optional and have defaults which are defined 
on a server side.
+ *
+ * See Apache Ignite documentation for details of every configuration setting. 
+ */
+class QueryEntity {
+
+    /**
+     * Public constructor.
+     *
+     * @return {QueryEntity} - new QueryEntity instance.
+     */
+    constructor() {
+        this._keyTypeName = null;
+        this._valueTypeName = null;
+        this._tableName = null;
+        this._keyFieldName = null;
+        this._valueFieldName = null;
+        this._fields = null;
+        this._aliases = null;
+        this._indexes = null;
+    }
+
+    /**
+     *
+     *
+     * @param {string} keyTypeName
+     *
+     * @return {QueryEntity} - the same instance of the QueryEntity.
+     */
+    setKeyTypeName(keyTypeName) {
+        this._keyTypeName = keyTypeName;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getKeyTypeName() {
+        return this._keyTypeName;
+    }
+
+    /**
+     *
+     *
+     * @param {string} valueTypeName
+     *
+     * @return {QueryEntity} - the same instance of the QueryEntity.
+     */
+    setValueTypeName(valueTypeName) {
+        this._valueTypeName = valueTypeName;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getValueTypeName() {
+        return this._valueTypeName;
+    }
+
+    /**
+     *
+     *
+     * @param {string} tableName
+     *
+     * @return {QueryEntity} - the same instance of the QueryEntity.
+     */
+    setTableName(tableName) {
+        this._tableName = tableName;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getTableName() {
+        return this._tableName;
+    }
+
+    /**
+     *
+     *
+     * @param {string} keyFieldName
+     *
+     * @return {QueryEntity} - the same instance of the QueryEntity.
+     */
+    setKeyFieldName(keyFieldName) {
+        this._keyFieldName = keyFieldName;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getKeyFieldName() {
+        return this._keyFieldName;
+    }
+
+    /**
+     *
+     *
+     * @param {string} valueFieldName
+     *
+     * @return {QueryEntity} - the same instance of the QueryEntity.
+     */
+    setValueFieldName(valueFieldName) {
+        this._valueFieldName = valueFieldName;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getValueFieldName() {
+        return this._valueFieldName;
+    }
+
+    /**
+     * 
+     *
+     * @param {Array<QueryField>} fields
+     *
+     * @return {QueryEntity} - the same instance of the QueryEntity.
+     */
+    setFields(fields) {
+        this._fields = fields;
+        return this;
+    }
+
+    /**
+     * 
+     *
+     * @return {Array<QueryField>}
+     */
+    getFields() {
+        return this._fields;
+    }
+
+    /**
+     * 
+     *
+     * @param {Map<string, string>} aliases
+     *
+     * @return {QueryEntity} - the same instance of the QueryEntity.
+     */
+    setAliases(aliases) {
+        this._aliases = aliases;
+        return this;
+    }
+
+    /**
+     * 
+     *
+     * @return {Map<string, string>}
+     */
+    getAliases() {
+        return this._aliases;
+    }
+
+    /**
+     * 
+     *
+     * @param {Array<QueryIndex>} indexes
+     *
+     * @return {QueryEntity} - the same instance of the QueryEntity.
+     */
+    setIndexes(indexes) {
+        this._indexes = indexes;
+        return this;
+    }
+
+    /**
+     * 
+     *
+     * @return {Array<QueryIndex>}
+     */
+    getIndexes() {
+        return this._indexes;
+    }
+
+    /** Private methods */
+
+    /**
+     * @ignore
+     */
+    async _write(buffer) {
+        await BinaryWriter.writeString(buffer, this._keyTypeName);
+        await BinaryWriter.writeString(buffer, this._valueTypeName);
+        await BinaryWriter.writeString(buffer, this._tableName);
+        await BinaryWriter.writeString(buffer, this._keyFieldName);
+        await BinaryWriter.writeString(buffer, this._valueFieldName);
+        await this._writeSubEntities(buffer, this._fields);
+        await this._writeAliases(buffer);
+        await this._writeSubEntities(buffer, this._indexes);
+    }
+
+    /**
+     * @ignore
+     */
+    async _writeAliases(buffer) {
+        const length = this._aliases ? this._aliases.size : 0;
+        buffer.writeInteger(length);
+        if (length > 0) {
+            for (let [key, value] of this._aliases.entries()) {
+                await BinaryWriter.writeString(buffer, key);
+                await BinaryWriter.writeString(buffer, value);
+            }
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    async _writeSubEntities(buffer, entities) {
+        const length = entities ? entities.length : 0;
+        buffer.writeInteger(length);
+        if (length > 0) {
+            for (let entity of entities) {
+                await entity._write(buffer);
+            }
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    async _read(buffer) {
+        this._keyTypeName = await BinaryReader.readObject(buffer);
+        this._valueTypeName = await BinaryReader.readObject(buffer);
+        this._tableName = await BinaryReader.readObject(buffer);
+        this._keyFieldName = await BinaryReader.readObject(buffer);
+        this._valueFieldName = await BinaryReader.readObject(buffer);
+        this._fields = await this._readSubEntities(buffer, QueryField);
+        await this._readAliases(buffer);
+        this._indexes = await this._readSubEntities(buffer, QueryIndex);
+    }
+
+    /**
+     * @ignore
+     */
+    async _readSubEntities(buffer, objectConstructor) {
+        const length = buffer.readInteger(buffer);
+        const result = new Array(length);
+        if (length > 0) {
+            let res;
+            for (let i = 0; i < length; i++) {
+                res = new objectConstructor();
+                await res._read(buffer);
+                result[i] = res;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @ignore
+     */
+    async _readAliases(buffer) {
+        const length = buffer.readInteger(buffer);
+        this._aliases = new Map();
+        if (length > 0) {
+            let res;
+            for (let i = 0; i < length; i++) {
+                this._aliases.set(await BinaryReader.readObject(buffer), await 
BinaryReader.readObject(buffer));
+            }
+        }
+    }
+}
+
+/**
+ * Class representing one Query Field element of {@link QueryEntity} of Ignite 
{@link CacheConfiguration}.
+ *
+ * All configuration settings are optional and have defaults which are defined 
on a server side.
+ *
+ * See Apache Ignite documentation for details of every configuration setting. 
+ */
+class QueryField {
+
+    /**
+     * Public constructor.
+     *
+     * @param {string} [name=null]
+     * @param {string} [typeName=null]
+     *
+     * @return {QueryField} - new QueryField instance.
+     */
+    constructor(name = null, typeName = null) {
+        this._name = name;
+        this._typeName = typeName;
+        this._isKeyField = false;
+        this._isNotNull = false;
+        this._defaultValue = undefined;
+        this._precision = -1;
+        this._scale = -1;
+        this._valueType = null;
+        this._buffer = null;
+        this._index = null;
+    }
+
+    /**
+     *
+     *
+     * @param {string} name
+     *
+     * @return {QueryField} - the same instance of the QueryField.
+     */
+    setName(name) {
+        this._name = name;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getName() {
+        return this._name;
+    }
+
+    /**
+     *
+     *
+     * @param {string} typeName
+     *
+     * @return {QueryField} - the same instance of the QueryField.
+     */
+    setTypeName(typeName) {
+        this._typeName = typeName;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getTypeName() {
+        return this._typeName;
+    }
+
+    /**
+     *
+     *
+     * @param {boolean} isKeyField
+     *
+     * @return {QueryField} - the same instance of the QueryField.
+     */
+    setIsKeyField(isKeyField) {
+        this._isKeyField = isKeyField;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {boolean}
+     */
+    getIsKeyField() {
+        return this._isKeyField;
+    }
+
+    /**
+     *
+     *
+     * @param {boolean} isNotNull
+     *
+     * @return {QueryField} - the same instance of the QueryField.
+     */
+    setIsNotNull(isNotNull) {
+        this._isNotNull = isNotNull;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {boolean}
+     */
+    getIsNotNull() {
+        return this._isNotNull;
+    }
+
+    /**
+     *
+     *
+     * @param {*} defaultValue
+     * @param {ObjectType.PRIMITIVE_TYPE | CompositeType} [valueType=null] - 
type of the default value:
+     *   - either a type code of primitive (simple) type
+     *   - or an instance of class representing non-primitive (composite) type
+     *   - or null (or not specified) that means the type is not specified
+     *
+     * @return {QueryField} - the same instance of the QueryField.
+     */
+    setDefaultValue(defaultValue, valueType = null) {
+        this._defaultValue = defaultValue;
+        this._valueType = valueType;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @param {ObjectType.PRIMITIVE_TYPE | CompositeType} [valueType=null] - 
type of the default value:
+     *   - either a type code of primitive (simple) type
+     *   - or an instance of class representing non-primitive (composite) type
+     *   - or null (or not specified) that means the type is not specified
+     *
+     * @async
+     *
+     * @return {*}
+     */
+    async getDefaultValue(valueType = null) {
+        if (this._defaultValue === undefined) {
+            if (this._buffer) {
+                const position = this._buffer.position;
+                this._buffer.position = this._index;
+                const result = await BinaryReader.readObject(this._buffer, 
valueType);
+                this._buffer.position = position;
+                return result;
+            }
+            else {
+                return null;
+            }
+        }
+        else {
+            return this._defaultValue;
+        }
+    }
+
+    /**
+     *
+     *
+     * @param {number} precision
+     *
+     * @return {QueryField} - the same instance of the QueryField.
+     */
+    setPrecision(precision) {
+        ArgumentChecker.isInteger(precision, 'precision');
+        this._precision = precision;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getPrecision() {
+        return this._precision;
+    }
+
+    /**
+     *
+     *
+     * @param {number} scale
+     *
+     * @return {QueryField} - the same instance of the QueryField.
+     */
+    setScale(scale) {
+        ArgumentChecker.isInteger(scale, 'scale');
+        this._scale = scale;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getScale() {
+        return this._scale;
+    }
+
+    /** Private methods */
+
+    /**
+     * @ignore
+     */
+    async _write(buffer) {
+        await BinaryWriter.writeString(buffer, this._name);
+        await BinaryWriter.writeString(buffer, this._typeName);
+        buffer.writeBoolean(this._isKeyField);
+        buffer.writeBoolean(this._isNotNull);
+        await BinaryWriter.writeObject(buffer, this._defaultValue ? 
this._defaultValue : null, this._valueType);
+        buffer.writeInteger(this._precision);
+        buffer.writeInteger(this._scale);
+    }
+
+    /**
+     * @ignore
+     */
+    async _read(buffer) {
+        this._name = await BinaryReader.readObject(buffer);
+        this._typeName = await BinaryReader.readObject(buffer);
+        this._isKeyField = buffer.readBoolean();
+        this._isNotNull = buffer.readBoolean();
+        this._defaultValue = undefined;
+        this._buffer = buffer;
+        this._index = buffer.position;
+        await BinaryReader.readObject(buffer);
+        this._precision = buffer.readInteger();
+        this._scale = buffer.readInteger();
+    }
+}
+
+/**
+ * 
+ * @typedef QueryIndex.INDEX_TYPE
+ * @enum
+ * @readonly
+ * @property SORTED 0
+ * @property FULLTEXT 1
+ * @property GEOSPATIAL 2
+ */
+ const INDEX_TYPE = Object.freeze({
+    SORTED : 0,
+    FULLTEXT : 1,
+    GEOSPATIAL : 2
+});
+
+/**
+ * Class representing one Query Index element of {@link QueryEntity} of Ignite 
{@link CacheConfiguration}.
+ *
+ * All configuration settings are optional and have defaults which are defined 
on a server side.
+ *
+ * See Apache Ignite documentation for details of every configuration setting. 
+ */
+class QueryIndex {
+    
+    /**
+     * Public constructor.
+     *
+     * @param {string} [name=null]
+     * @param {string} [typeName=QueryIndex.INDEX_TYPE.SORTED]
+     *
+     * @return {QueryIndex} - new QueryIndex instance.
+     */
+    constructor(name = null, type = QueryIndex.INDEX_TYPE.SORTED) {
+        this._name = name;
+        this.setType(type);
+        this._inlineSize = -1;
+        this._fields = null;
+    }
+
+    static get INDEX_TYPE() {
+        return INDEX_TYPE;
+    }
+
+    /**
+     *
+     *
+     * @param {string} name
+     *
+     * @return {QueryIndex} - the same instance of the QueryIndex.
+     */
+    setName(name) {
+        this._name = name;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getName() {
+        return this._name;
+    }
+
+    /**
+     *
+     *
+     * @param {QueryIndex.INDEX_TYPE} type
+     *
+     * @return {QueryIndex} - the same instance of the QueryIndex.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setType(type) {
+        ArgumentChecker.hasValueFrom(type, 'type', false, 
QueryIndex.INDEX_TYPE);
+        this._type = type;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {QueryIndex.INDEX_TYPE}
+     */
+    getType() {
+        return this._type;
+    }
+
+    /**
+     *
+     *
+     * @param {number} inlineSize
+     *
+     * @return {QueryIndex} - the same instance of the QueryIndex.
+     */
+    setInlineSize(inlineSize) {
+        this._inlineSize = inlineSize;
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+     getInlineSize() {
+        return this._inlineSize;
+    }
+
+    /**
+     * 
+     *
+     * @param {Map<string, boolean>} fields
+     *
+     * @return {QueryIndex} - the same instance of the QueryIndex.
+     */
+    setFields(fields) {
+        this._fields = fields;
+        return this;
+    }
+
+    /**
+     * 
+     *
+     * @return {Map<string, boolean>}
+     */
+    getFields() {
+        return this._fields;
+    }
+
+    /** Private methods */
+
+    /**
+     * @ignore
+     */
+    async _write(buffer) {
+        await BinaryWriter.writeString(buffer, this._name);
+        buffer.writeByte(this._type);
+        buffer.writeInteger(this._inlineSize);
+        // write fields
+        const length = this._fields ? this._fields.size : 0;
+        buffer.writeInteger(length);
+        if (length > 0) {
+            for (let [key, value] of this._fields.entries()) {
+                await BinaryWriter.writeString(buffer, key);
+                buffer.writeBoolean(value);
+            }
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    async _read(buffer) {
+        this._name = await BinaryReader.readObject(buffer);
+        this._type = buffer.readByte();
+        this._inlineSize = buffer.readInteger();
+        // read fields
+        const length = buffer.readInteger(buffer);
+        this._fields = new Map();
+        if (length > 0) {
+            let res;
+            for (let i = 0; i < length; i++) {
+                this._fields.set(await BinaryReader.readObject(buffer), 
buffer.readBoolean());
+            }
+        }
+    }
+}
+
+const PROP_NAME = 0;
+const PROP_CACHE_MODE = 1;
+const PROP_ATOMICITY_MODE = 2;
+const PROP_BACKUPS = 3;
+const PROP_WRITE_SYNCHRONIZATION_MODE = 4;
+const PROP_COPY_ON_READ = 5;
+const PROP_READ_FROM_BACKUP = 6;
+const PROP_DATA_REGION_NAME = 100;
+const PROP_IS_ONHEAP_CACHE_ENABLED = 101;
+const PROP_QUERY_ENTITY = 200;
+const PROP_QUERY_PARALLELISM = 201;
+const PROP_QUERY_DETAIL_METRICS_SIZE = 202;
+const PROP_SQL_SCHEMA = 203;
+const PROP_SQL_INDEX_INLINE_MAX_SIZE = 204;
+const PROP_SQL_ESCAPE_ALL = 205;
+const PROP_MAX_QUERY_ITERATORS = 206;
+const PROP_REBALANCE_MODE = 300;
+const PROP_REBALANCE_DELAY = 301;
+const PROP_REBALANCE_TIMEOUT = 302;
+const PROP_REBALANCE_BATCH_SIZE = 303;
+const PROP_REBALANCE_BATCHES_PREFETCH_COUNT = 304;
+const PROP_REBALANCE_ORDER = 305;
+const PROP_REBALANCE_THROTTLE = 306;
+const PROP_GROUP_NAME = 400;
+const PROP_CACHE_KEY_CONFIGURATION = 401;
+const PROP_DEFAULT_LOCK_TIMEOUT = 402;
+const PROP_MAX_CONCURRENT_ASYNC_OPS = 403;
+const PROP_PARTITION_LOSS_POLICY = 404;
+const PROP_EAGER_TTL = 405;
+const PROP_STATISTICS_ENABLED = 406;
+
+const PROP_TYPES = Object.freeze({
+    [PROP_NAME] : BinaryUtils.TYPE_CODE.STRING,
+    [PROP_CACHE_MODE] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_ATOMICITY_MODE] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_BACKUPS] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_WRITE_SYNCHRONIZATION_MODE] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_COPY_ON_READ] : BinaryUtils.TYPE_CODE.BOOLEAN,
+    [PROP_READ_FROM_BACKUP] : BinaryUtils.TYPE_CODE.BOOLEAN,
+    [PROP_DATA_REGION_NAME] : BinaryUtils.TYPE_CODE.STRING,
+    [PROP_IS_ONHEAP_CACHE_ENABLED] : BinaryUtils.TYPE_CODE.BOOLEAN,
+    [PROP_QUERY_ENTITY] : new ObjectArrayType(new ComplexObjectType(new 
QueryEntity())),
+    [PROP_QUERY_PARALLELISM] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_QUERY_DETAIL_METRICS_SIZE] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_SQL_SCHEMA] : BinaryUtils.TYPE_CODE.STRING,
+    [PROP_SQL_INDEX_INLINE_MAX_SIZE] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_SQL_ESCAPE_ALL] : BinaryUtils.TYPE_CODE.BOOLEAN,
+    [PROP_MAX_QUERY_ITERATORS] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_REBALANCE_MODE] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_REBALANCE_DELAY] : BinaryUtils.TYPE_CODE.LONG,
+    [PROP_REBALANCE_TIMEOUT] : BinaryUtils.TYPE_CODE.LONG,
+    [PROP_REBALANCE_BATCH_SIZE] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_REBALANCE_BATCHES_PREFETCH_COUNT] : BinaryUtils.TYPE_CODE.LONG,
+    [PROP_REBALANCE_ORDER] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_REBALANCE_THROTTLE] : BinaryUtils.TYPE_CODE.LONG,
+    [PROP_GROUP_NAME] : BinaryUtils.TYPE_CODE.STRING,
+    [PROP_CACHE_KEY_CONFIGURATION] : new ObjectArrayType(new 
ComplexObjectType(new CacheKeyConfiguration())),
+    [PROP_DEFAULT_LOCK_TIMEOUT] : BinaryUtils.TYPE_CODE.LONG,
+    [PROP_MAX_CONCURRENT_ASYNC_OPS] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_PARTITION_LOSS_POLICY] : BinaryUtils.TYPE_CODE.INTEGER,
+    [PROP_EAGER_TTL] : BinaryUtils.TYPE_CODE.BOOLEAN,
+    [PROP_STATISTICS_ENABLED] : BinaryUtils.TYPE_CODE.BOOLEAN
+});
+
+/**
+ * 
+ * @typedef CacheConfiguration.CACHE_ATOMICITY_MODE
+ * @enum
+ * @readonly
+ * @property TRANSACTIONAL 0
+ * @property ATOMIC 1
+ */
+const CACHE_ATOMICITY_MODE = Object.freeze({
+    TRANSACTIONAL : 0,
+    ATOMIC : 1
+});
+
+/**
+ * 
+ * @typedef CacheConfiguration.CACHE_MODE
+ * @enum
+ * @readonly
+ * @property LOCAL 0
+ * @property REPLICATED 1
+ * @property PARTITIONED 2
+ */
+const CACHE_MODE = Object.freeze({
+    LOCAL : 0,
+    REPLICATED : 1,
+    PARTITIONED : 2
+});
+
+/**
+ * 
+ * @typedef CacheConfiguration.PARTITION_LOSS_POLICY
+ * @enum
+ * @readonly
+ * @property READ_ONLY_SAFE 0
+ * @property READ_ONLY_ALL 1
+ * @property READ_WRITE_SAFE 2
+ * @property READ_WRITE_ALL 3
+ * @property IGNORE 4
+ */
+const PARTITION_LOSS_POLICY = Object.freeze({
+    READ_ONLY_SAFE : 0,
+    READ_ONLY_ALL : 1,
+    READ_WRITE_SAFE : 2,
+    READ_WRITE_ALL : 3,
+    IGNORE : 4
+});
+
+/**
+ * 
+ * @typedef CacheConfiguration.REABALANCE_MODE
+ * @enum
+ * @readonly
+ * @property SYNC 0
+ * @property ASYNC 1
+ * @property NONE 2
+ */
+const REABALANCE_MODE = Object.freeze({
+    SYNC : 0,
+    ASYNC : 1,
+    NONE : 2
+});
+
+/**
+ * 
+ * @typedef CacheConfiguration.WRITE_SYNCHRONIZATION_MODE
+ * @enum
+ * @readonly
+ * @property FULL_SYNC 0
+ * @property FULL_ASYNC 1
+ * @property PRIMARY_SYNC 2
+ */
+const WRITE_SYNCHRONIZATION_MODE = Object.freeze({
+    FULL_SYNC : 0,
+    FULL_ASYNC : 1,
+    PRIMARY_SYNC : 2
+});
+
+/**
+ * Class representing Ignite cache configuration on a server.
+ *
+ * All configuration settings are optional and have defaults which are defined 
on a server side.
+ *
+ * See Apache Ignite documentation for details of every configuration setting. 
+ */
+class CacheConfiguration {
+
+    /**
+     * Public constructor.
+     *
+     * @return {CacheConfiguration} - new CacheConfiguration instance.
+     */
+    constructor() {
+        this._properties = new Map();
+    }
+
+    static get CACHE_ATOMICITY_MODE() {
+        return CACHE_ATOMICITY_MODE;
+    }
+
+    static get CACHE_MODE() {
+        return CACHE_MODE;
+    }
+
+    static get PARTITION_LOSS_POLICY() {
+        return PARTITION_LOSS_POLICY;
+    }
+
+    static get REABALANCE_MODE() {
+        return REABALANCE_MODE;
+    }
+
+    static get WRITE_SYNCHRONIZATION_MODE() {
+        return WRITE_SYNCHRONIZATION_MODE;
+    }
+
+    /**
+     *
+     *
+     * @param {CacheConfiguration.CACHE_ATOMICITY_MODE} atomicityMode
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setAtomicityMode(atomicityMode) {
+        ArgumentChecker.hasValueFrom(atomicityMode, 'atomicityMode', false, 
CACHE_ATOMICITY_MODE);
+        this._properties.set(PROP_ATOMICITY_MODE, atomicityMode);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {CacheConfiguration.CACHE_ATOMICITY_MODE}
+     */
+    getAtomicityMode() {
+        return this._properties.get(PROP_ATOMICITY_MODE);
+    }
+
+    /**
+     *
+     *
+     * @param {number} backups
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setBackups(backups) {
+        this._properties.set(PROP_BACKUPS, backups);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getBackups() {
+        return this._properties.get(PROP_BACKUPS);
+    }
+
+    /**
+     *
+     *
+     * @param {CacheConfiguration.CACHE_MODE} cacheMode
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setCacheMode(cacheMode) {
+        ArgumentChecker.hasValueFrom(cacheMode, 'cacheMode', false, 
CACHE_MODE);
+        this._properties.set(PROP_CACHE_MODE, cacheMode);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {CacheConfiguration.CACHE_MODE}
+     */
+    getCacheMode() {
+        return this._properties.get(PROP_CACHE_MODE);
+    }
+
+    /**
+     *
+     *
+     * @param {boolean} copyOnRead
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setCopyOnRead(copyOnRead) {
+        this._properties.set(PROP_COPY_ON_READ, copyOnRead);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {boolean}
+     */
+    getCopyOnRead() {
+        return this._properties.get(PROP_COPY_ON_READ);
+    }
+
+    /**
+     *
+     *
+     * @param {string} dataRegionName
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setDataRegionName(dataRegionName) {
+        this._properties.set(PROP_DATA_REGION_NAME, dataRegionName);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getDataRegionName() {
+        return this._properties.get(PROP_DATA_REGION_NAME);
+    }
+
+    /**
+     *
+     *
+     * @param {boolean} eagerTtl
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setEagerTtl(eagerTtl) {
+        this._properties.set(PROP_EAGER_TTL, eagerTtl);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {boolean}
+     */
+    getEagerTtl() {
+        return this._properties.get(PROP_EAGER_TTL);
+    }
+
+    /**
+     *
+     *
+     * @param {boolean} statisticsEnabled
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setStatisticsEnabled(statisticsEnabled) {
+        this._properties.set(PROP_STATISTICS_ENABLED, statisticsEnabled);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {boolean}
+     */
+    getStatisticsEnabled() {
+        return this._properties.get(PROP_STATISTICS_ENABLED);
+    }
+
+    /**
+     *
+     *
+     * @param {string} groupName
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setGroupName(groupName) {
+        this._properties.set(PROP_GROUP_NAME, groupName);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getGroupName() {
+        return this._properties.get(PROP_GROUP_NAME);
+    }
+
+    /**
+     *
+     *
+     * @param {number} lockTimeout
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setDefaultLockTimeout(lockTimeout) {
+        this._properties.set(PROP_DEFAULT_LOCK_TIMEOUT, lockTimeout);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getDefaultLockTimeout() {
+        return this._properties.get(PROP_DEFAULT_LOCK_TIMEOUT);
+    }
+
+    /**
+     *
+     *
+     * @param {number} maxConcurrentAsyncOperations
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setMaxConcurrentAsyncOperations(maxConcurrentAsyncOperations) {
+        this._properties.set(PROP_MAX_CONCURRENT_ASYNC_OPS, 
maxConcurrentAsyncOperations);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getMaxConcurrentAsyncOperations() {
+        return this._properties.get(PROP_MAX_CONCURRENT_ASYNC_OPS);
+    }
+
+    /**
+     *
+     *
+     * @param {number} maxQueryIterators
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setMaxQueryIterators(maxQueryIterators) {
+        this._properties.set(PROP_MAX_QUERY_ITERATORS, maxQueryIterators);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getMaxQueryIterators() {
+        return this._properties.get(PROP_MAX_QUERY_ITERATORS);
+    }
+
+    /**
+     *
+     *
+     * @param {boolean} isOnheapCacheEnabled
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setIsOnheapCacheEnabled(isOnheapCacheEnabled) {
+        this._properties.set(PROP_IS_ONHEAP_CACHE_ENABLED, 
isOnheapCacheEnabled);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {boolean}
+     */
+    getIsOnheapCacheEnabled() {
+        return this._properties.get(PROP_IS_ONHEAP_CACHE_ENABLED);
+    }
+
+    /**
+     *
+     *
+     * @param {CacheConfiguration.PARTITION_LOSS_POLICY} partitionLossPolicy
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setPartitionLossPolicy(partitionLossPolicy) {
+        ArgumentChecker.hasValueFrom(partitionLossPolicy, 
'partitionLossPolicy', false, PARTITION_LOSS_POLICY);
+        this._properties.set(PROP_PARTITION_LOSS_POLICY, partitionLossPolicy);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {CacheConfiguration.PARTITION_LOSS_POLICY}
+     */
+    getPartitionLossPolicy() {
+        return this._properties.get(PROP_PARTITION_LOSS_POLICY);
+    }
+
+    /**
+     *
+     *
+     * @param {number} queryDetailMetricsSize
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setQueryDetailMetricsSize(queryDetailMetricsSize) {
+        this._properties.set(PROP_QUERY_DETAIL_METRICS_SIZE, 
queryDetailMetricsSize);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getQueryDetailMetricsSize() {
+        return this._properties.get(PROP_QUERY_DETAIL_METRICS_SIZE);
+    }
+
+    /**
+     *
+     *
+     * @param {number} queryParallelism
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setQueryParallelism(queryParallelism) {
+        this._properties.set(PROP_QUERY_PARALLELISM, queryParallelism);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getQueryParallelism() {
+        return this._properties.get(PROP_QUERY_PARALLELISM);
+    }
+
+    /**
+     *
+     *
+     * @param {boolean} readFromBackup
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setReadFromBackup(readFromBackup) {
+        this._properties.set(PROP_READ_FROM_BACKUP, readFromBackup);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {boolean}
+     */
+    getReadFromBackup() {
+        return this._properties.get(PROP_READ_FROM_BACKUP);
+    }
+
+    /**
+     *
+     *
+     * @param {number} rebalanceBatchSize
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setRebalanceBatchSize(rebalanceBatchSize) {
+        this._properties.set(PROP_REBALANCE_BATCH_SIZE, rebalanceBatchSize);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getRebalanceBatchSize() {
+        return this._properties.get(PROP_REBALANCE_BATCH_SIZE);
+    }
+
+    /**
+     *
+     *
+     * @param {number} rebalanceBatchesPrefetchCount
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setRebalanceBatchesPrefetchCount(rebalanceBatchesPrefetchCount) {
+        this._properties.set(PROP_REBALANCE_BATCHES_PREFETCH_COUNT, 
rebalanceBatchesPrefetchCount);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getRebalanceBatchesPrefetchCount() {
+        return this._properties.get(PROP_REBALANCE_BATCHES_PREFETCH_COUNT);
+    }
+
+    /**
+     *
+     *
+     * @param {number} rebalanceDelay
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setRebalanceDelay(rebalanceDelay) {
+        this._properties.set(PROP_REBALANCE_DELAY, rebalanceDelay);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getRebalanceDelay() {
+        return this._properties.get(PROP_REBALANCE_DELAY);
+    }
+
+    /**
+     *
+     *
+     * @param {CacheConfiguration.REABALANCE_MODE} rebalanceMode
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setRebalanceMode(rebalanceMode) {
+        ArgumentChecker.hasValueFrom(rebalanceMode, 'rebalanceMode', false, 
REABALANCE_MODE);
+        this._properties.set(PROP_REBALANCE_MODE, rebalanceMode);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {CacheConfiguration.REABALANCE_MODE}
+     */
+    getRebalanceMode() {
+        return this._properties.get(PROP_REBALANCE_MODE);
+    }
+
+    /**
+     *
+     *
+     * @param {number} rebalanceOrder
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setRebalanceOrder(rebalanceOrder) {
+        this._properties.set(PROP_REBALANCE_ORDER, rebalanceOrder);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getRebalanceOrder() {
+        return this._properties.get(PROP_REBALANCE_ORDER);
+    }
+
+    /**
+     *
+     *
+     * @param {number} rebalanceThrottle
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setRebalanceThrottle(rebalanceThrottle) {
+        this._properties.set(PROP_REBALANCE_THROTTLE, rebalanceThrottle);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getRebalanceThrottle() {
+        return this._properties.get(PROP_REBALANCE_THROTTLE);
+    }
+
+    /**
+     *
+     *
+     * @param {number} rebalanceTimeout
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setRebalanceTimeout(rebalanceTimeout) {
+        this._properties.set(PROP_REBALANCE_TIMEOUT, rebalanceTimeout);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getRebalanceTimeout() {
+        return this._properties.get(PROP_REBALANCE_TIMEOUT);
+    }
+
+    /**
+     *
+     *
+     * @param {boolean} sqlEscapeAll
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setSqlEscapeAll(sqlEscapeAll) {
+        this._properties.set(PROP_SQL_ESCAPE_ALL, sqlEscapeAll);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {boolean}
+     */
+    getSqlEscapeAll() {
+        return this._properties.get(PROP_SQL_ESCAPE_ALL);
+    }
+
+    /**
+     *
+     *
+     * @param {number} sqlIndexInlineMaxSize
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setSqlIndexInlineMaxSize(sqlIndexInlineMaxSize) {
+        this._properties.set(PROP_SQL_INDEX_INLINE_MAX_SIZE, 
sqlIndexInlineMaxSize);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {number}
+     */
+    getSqlIndexInlineMaxSize() {
+        return this._properties.get(PROP_SQL_INDEX_INLINE_MAX_SIZE);
+    }
+
+    /**
+     *
+     *
+     * @param {string} sqlSchema
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     */
+    setSqlSchema(sqlSchema) {
+        this._properties.set(PROP_SQL_SCHEMA, sqlSchema);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {string}
+     */
+    getSqlSchema() {
+        return this._properties.get(PROP_SQL_SCHEMA);
+    }
+
+    /**
+     *
+     *
+     * @param {CacheConfiguration.WRITE_SYNCHRONIZATION_MODE} 
writeSynchronizationMode
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setWriteSynchronizationMode(writeSynchronizationMode) {
+        ArgumentChecker.hasValueFrom(writeSynchronizationMode, 
'writeSynchronizationMode', false, WRITE_SYNCHRONIZATION_MODE);
+        this._properties.set(PROP_WRITE_SYNCHRONIZATION_MODE, 
writeSynchronizationMode);
+        return this;
+    }
+
+    /**
+     *
+     *
+     * @return {CacheConfiguration.WRITE_SYNCHRONIZATION_MODE}
+     */
+    getWriteSynchronizationMode() {
+        return this._properties.get(PROP_WRITE_SYNCHRONIZATION_MODE);
+    }
+
+    /**
+     * 
+     *
+     * @param {...CacheKeyConfiguration} keyConfigurations
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setKeyConfigurations(...keyConfigurations) {
+        ArgumentChecker.hasType(keyConfigurations, 'keyConfigurations', true, 
CacheKeyConfiguration);
+        this._properties.set(PROP_CACHE_KEY_CONFIGURATION, keyConfigurations);
+        return this;
+    }
+
+    /**
+     * 
+     *
+     * @return {Array<CacheKeyConfiguration>}
+     */
+    getKeyConfigurations() {
+        return this._properties.get(PROP_CACHE_KEY_CONFIGURATION);
+    }
+
+    /**
+     * 
+     *
+     * @param {...QueryEntity} queryEntities
+     *
+     * @return {CacheConfiguration} - the same instance of the 
CacheConfiguration.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setQueryEntities(...queryEntities) {
+        ArgumentChecker.hasType(queryEntities, 'queryEntities', true, 
QueryEntity);
+        this._properties.set(PROP_QUERY_ENTITY, queryEntities);
+        return this;
+    }
+
+    /**
+     * 
+     *
+     * @return {Array<QueryEntity>}
+     */
+    getQueryEntities() {
+        return this._properties.get(PROP_QUERY_ENTITY);
+    }
+
+    /** Private methods */
+
+    /**
+     * @ignore
+     */
+    async _write(buffer, name) {
+        this._properties.set(PROP_NAME, name);
+
+        const startPos = buffer.position;
+        buffer.position = buffer.position +
+            BinaryUtils.getSize(BinaryUtils.TYPE_CODE.INTEGER) +
+            BinaryUtils.getSize(BinaryUtils.TYPE_CODE.SHORT);
+
+        for (let [propertyCode, property] of this._properties) {
+            await this._writeProperty(buffer, propertyCode, property);
+        }
+
+        const length = buffer.position - startPos;
+        buffer.position = startPos;
+
+        buffer.writeInteger(length);
+        buffer.writeShort(this._properties.size);
+    }
+
+    /**
+     * @ignore
+     */
+    async _writeProperty(buffer, propertyCode, property) {
+        buffer.writeShort(propertyCode);
+        const propertyType = PROP_TYPES[propertyCode];
+        switch (BinaryUtils.getTypeCode(propertyType)) {
+            case BinaryUtils.TYPE_CODE.INTEGER:
+            case BinaryUtils.TYPE_CODE.LONG:
+            case BinaryUtils.TYPE_CODE.BOOLEAN:
+                await BinaryWriter.writeObject(buffer, property, propertyType, 
false);
+                return;
+            case BinaryUtils.TYPE_CODE.STRING:
+                await BinaryWriter.writeObject(buffer, property, propertyType);
+                return;
+            case BinaryUtils.TYPE_CODE.OBJECT_ARRAY:
+                const length = property ? property.length : 0;
+                buffer.writeInteger(length);
+                for (let prop of property) {
+                    await prop._write(buffer);
+                }
+                return;
+            default:
+                throw Errors.IgniteClientError.internalError();
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    async _read(buffer) {
+        // length
+        buffer.readInteger();
+        await this._readProperty(buffer, PROP_ATOMICITY_MODE);
+        await this._readProperty(buffer, PROP_BACKUPS);
+        await this._readProperty(buffer, PROP_CACHE_MODE);
+        await this._readProperty(buffer, PROP_COPY_ON_READ);
+        await this._readProperty(buffer, PROP_DATA_REGION_NAME);
+        await this._readProperty(buffer, PROP_EAGER_TTL);
+        await this._readProperty(buffer, PROP_STATISTICS_ENABLED);
+        await this._readProperty(buffer, PROP_GROUP_NAME);
+        await this._readProperty(buffer, PROP_DEFAULT_LOCK_TIMEOUT);
+        await this._readProperty(buffer, PROP_MAX_CONCURRENT_ASYNC_OPS);
+        await this._readProperty(buffer, PROP_MAX_QUERY_ITERATORS);
+        await this._readProperty(buffer, PROP_NAME);
+        await this._readProperty(buffer, PROP_IS_ONHEAP_CACHE_ENABLED);
+        await this._readProperty(buffer, PROP_PARTITION_LOSS_POLICY);
+        await this._readProperty(buffer, PROP_QUERY_DETAIL_METRICS_SIZE);
+        await this._readProperty(buffer, PROP_QUERY_PARALLELISM);
+        await this._readProperty(buffer, PROP_READ_FROM_BACKUP);
+        await this._readProperty(buffer, PROP_REBALANCE_BATCH_SIZE);
+        await this._readProperty(buffer, 
PROP_REBALANCE_BATCHES_PREFETCH_COUNT);
+        await this._readProperty(buffer, PROP_REBALANCE_DELAY);
+        await this._readProperty(buffer, PROP_REBALANCE_MODE);
+        await this._readProperty(buffer, PROP_REBALANCE_ORDER);
+        await this._readProperty(buffer, PROP_REBALANCE_THROTTLE);
+        await this._readProperty(buffer, PROP_REBALANCE_TIMEOUT);
+        await this._readProperty(buffer, PROP_SQL_ESCAPE_ALL);
+        await this._readProperty(buffer, PROP_SQL_INDEX_INLINE_MAX_SIZE);
+        await this._readProperty(buffer, PROP_SQL_SCHEMA);
+        await this._readProperty(buffer, PROP_WRITE_SYNCHRONIZATION_MODE);
+        await this._readProperty(buffer, PROP_CACHE_KEY_CONFIGURATION);
+        await this._readProperty(buffer, PROP_QUERY_ENTITY);
+    }
+
+    /**
+     * @ignore
+     */
+    async _readProperty(buffer, propertyCode) {
+        const propertyType = PROP_TYPES[propertyCode];
+        switch (BinaryUtils.getTypeCode(propertyType)) {
+            case BinaryUtils.TYPE_CODE.INTEGER:
+            case BinaryUtils.TYPE_CODE.LONG:
+            case BinaryUtils.TYPE_CODE.BOOLEAN:
+                this._properties.set(propertyCode, await 
BinaryReader._readTypedObject(buffer, propertyType));
+                return;
+            case BinaryUtils.TYPE_CODE.STRING:
+                this._properties.set(propertyCode, await 
BinaryReader.readObject(buffer, propertyType));
+                return;
+            case BinaryUtils.TYPE_CODE.OBJECT_ARRAY:
+                const length = buffer.readInteger();
+                if (length > 0) {
+                    const properties = new Array(length);
+                    for (let i = 0; i < length; i++) {
+                        const property = new 
propertyType._elementType._objectConstructor();
+                        await property._read(buffer);
+                        properties[i] = property;
+                    }
+                    this._properties.set(propertyCode, properties);
+                }
+                return;
+            default:
+                throw Errors.IgniteClientError.internalError();
+        }
+    }
+}
+
+module.exports = CacheConfiguration;
+module.exports.QueryEntity = QueryEntity;
+module.exports.QueryField = QueryField;
+module.exports.QueryIndex = QueryIndex;
+module.exports.CacheKeyConfiguration = CacheKeyConfiguration;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c56d16fb/modules/platforms/nodejs/lib/Cursor.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/lib/Cursor.js 
b/modules/platforms/nodejs/lib/Cursor.js
new file mode 100644
index 0000000..85176e3
--- /dev/null
+++ b/modules/platforms/nodejs/lib/Cursor.js
@@ -0,0 +1,309 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+const Errors = require('./Errors');
+const BinaryUtils = require('./internal/BinaryUtils');
+const BinaryObject = require('./BinaryObject');
+const BinaryReader = require('./internal/BinaryReader');
+const BinaryWriter = require('./internal/BinaryWriter');
+
+/**
+ * Class representing a cursor to obtain results of SQL and Scan query 
operations.
+ *
+ * The class has no public constructor. An instance of this class is obtained
+ * via query() method of {@link CacheClient} objects.
+ * One instance of this class returns results of one SQL or Scan query 
operation.
+ *
+ * @hideconstructor
+ */
+class Cursor {
+
+    /**
+     * Returns one element (cache entry - key-value pair) from the query 
results.
+     *
+     * Every new call returns the next cache entry from the query results.
+     * If the method returns null, no more entries are available.
+     *
+     * @async
+     *
+     * @return {Promise<CacheEntry>} - a cache entry (key-value pair).
+     */
+    async getValue() {
+        if (!this._values || this._valueIndex >= this._values.length) {
+            await this._getValues();
+            this._valueIndex = 0;
+        }
+        if (this._values && this._values.length > 0) {
+            const value = this._values[this._valueIndex];
+            this._valueIndex++;
+            return value;
+        }
+        return null;
+    }
+
+    /**
+     * Checks if more elements are available in the query results.
+     *
+     * @return {boolean} - true if more cache entries are available, false 
otherwise.
+     */
+    hasMore() {
+        return this._hasNext ||
+            this._values && this._valueIndex < this._values.length;
+    }
+
+    /**
+     * Returns all elements (cache entries - key-value pairs) from the query 
results.
+     *
+     * May be used instead of getValue() method if the number of returned 
entries
+     * is relatively small and will not cause memory utilization issues.
+     *
+     * @async
+     *
+     * @return {Promise<Array<CacheEntry>>} - all cache entries (key-value 
pairs)
+     *   returned by SQL or Scan query.
+     */
+    async getAll() {
+        let result = new Array();
+        let values;
+        do {
+            values = await this._getValues();
+            if (values) {
+                result = result.concat(values);
+            }
+        } while (this._hasNext);
+        return result;
+    }
+
+    /**
+     * Closes the cursor. Obtaining elements from the results is not possible 
after this.
+     *
+     * This method should be called if no more elements are needed.
+     * It is not neccessary to call it if all elements have been already 
obtained.
+     *
+     * @async
+     */
+    async close() {
+        // Close cursor only if the server has more pages: the server closes 
cursor automatically on last page
+        if (this._id && this._hasNext) {
+            await this._socket.send(
+                BinaryUtils.OPERATION.RESOURCE_CLOSE,
+                async (payload) => {
+                    await this._write(payload);
+                });
+        }
+    }
+
+    /** Private methods */
+
+    /**
+     * @ignore
+     */
+    constructor(socket, operation, buffer, keyType = null, valueType = null) {
+        this._socket = socket;
+        this._operation = operation;
+        this._buffer = buffer;
+        this._keyType = keyType;
+        this._valueType = valueType;
+        this._id = null;
+        this._hasNext = false;
+        this._values = null;
+        this._valueIndex = 0;
+    }
+
+    /**
+     * @ignore
+     */
+    async _getNext() {
+        this._hasNext = false;
+        this._values = null;
+        this._buffer = null;
+        await this._socket.send(
+            this._operation,
+            async (payload) => {
+                await this._write(payload);
+            },
+            async (payload) => {
+                this._buffer = payload;
+            });
+    }
+
+    /**
+     * @ignore
+     */
+    async _getValues() {
+        if (!this._buffer && this._hasNext) {
+            await this._getNext();
+        }
+        await this._read(this._buffer)
+        this._buffer = null;
+        return this._values;
+    }
+
+    /**
+     * @ignore
+     */
+    async _write(buffer) {
+        buffer.writeLong(this._id);
+    }
+
+    /**
+     * @ignore
+     */
+    _readId(buffer) {
+        this._id = buffer.readLong();
+    }
+
+    /**
+     * @ignore
+     */
+    async _readRow(buffer) {
+        const CacheEntry = require('./CacheClient').CacheEntry;
+        return new CacheEntry(
+            await BinaryReader.readObject(buffer, this._keyType),
+            await BinaryReader.readObject(buffer, this._valueType));
+    }
+
+    /**
+     * @ignore
+     */
+    async _read(buffer) {
+        const rowCount = buffer.readInteger();
+        this._values = new Array(rowCount);
+        for (let i = 0; i < rowCount; i++) {
+            this._values[i] = await this._readRow(buffer);
+        }
+        this._hasNext = buffer.readBoolean();
+    }
+}
+
+/**
+ * Class representing a cursor to obtain results of SQL Fields query operation.
+ *
+ * The class has no public constructor. An instance of this class is obtained
+ * via query() method of {@link CacheClient} objects.
+ * One instance of this class returns results of one SQL Fields query 
operation.
+ *
+ * @hideconstructor
+ * @extends Cursor
+ */
+class SqlFieldsCursor extends Cursor {
+
+    /**
+     * Returns one element (array with values of the fields) from the query 
results.
+     *
+     * Every new call returns the next element from the query results.
+     * If the method returns null, no more elements are available.
+     *
+     * @async
+     *
+     * @return {Promise<Array<*>>} - array with values of the fields requested 
by the query.
+     *
+     */
+    async getValue() {
+        return await super.getValue();
+    }
+
+    /**
+     * Returns all elements (arrays with values of the fields) from the query 
results.
+     *
+     * May be used instead of getValue() method if the number of returned 
elements
+     * is relatively small and will not cause memory utilization issues.
+     *
+     * @async
+     *
+     * @return {Promise<Array<Array<*>>>} - all results returned by SQL Fields 
query.
+     *   Every element of the array is an array with values of the fields 
requested by the query.
+     *
+     */
+    async getAll() {
+        return await super.getAll();
+    }
+
+    /**
+     * Returns names of the fields which were requested in the SQL Fields 
query.
+     *
+     * Empty array is returned if "include field names" flag was false in the 
query.
+     *
+     * @return {Array<string>} - field names.
+     *   The order of names corresponds to the order of field values returned 
in the results of the query.
+     */
+    getFieldNames() {
+        return this._fieldNames;
+    }
+
+    /**
+     * Specifies types of the fields returned by the SQL Fields query.
+     *
+     * By default, a type of every field is not specified that means during 
operations the Ignite client
+     * will try to make automatic mapping between JavaScript types and Ignite 
object types -
+     * according to the mapping table defined in the description of the {@link 
ObjectType} class.
+     *
+     * @param {...ObjectType.PRIMITIVE_TYPE | CompositeType} fieldTypes - 
types of the returned fields.
+     *   The order of types must correspond the order of field values returned 
in the results of the query.
+     *   A type of every field can be:
+     *   - either a type code of primitive (simple) type
+     *   - or an instance of class representing non-primitive (composite) type
+     *   - or null (means the type is not specified)
+     *
+     * @return {SqlFieldsCursor} - the same instance of the SqlFieldsCursor.
+     */
+    setFieldTypes(...fieldTypes) {
+        this._fieldTypes = fieldTypes;
+        return this;
+    }
+
+    /** Private methods */
+
+    /**
+     * @ignore
+     */
+    constructor(socket, buffer) {
+        super(socket, BinaryUtils.OPERATION.QUERY_SQL_FIELDS_CURSOR_GET_PAGE, 
buffer);
+        this._fieldNames = [];
+    }
+
+    /**
+     * @ignore
+     */
+    async _readFieldNames(buffer, includeFieldNames) {
+        this._id = buffer.readLong();
+        this._fieldCount = buffer.readInteger();
+        if (includeFieldNames) {
+            for (let i = 0; i < this._fieldCount; i++) {
+                this._fieldNames[i] = await BinaryReader.readObject(buffer);
+            }
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    async _readRow(buffer) {
+        let values = new Array(this._fieldCount);
+        let fieldType;
+        for (let i = 0; i < this._fieldCount; i++) {
+            fieldType = this._fieldTypes && i < this._fieldTypes.length ? 
this._fieldTypes[i] : null;
+            values[i] = await BinaryReader.readObject(buffer);
+        }
+        return values;
+    }
+}
+
+module.exports.Cursor = Cursor;
+module.exports.SqlFieldsCursor = SqlFieldsCursor;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c56d16fb/modules/platforms/nodejs/lib/EnumItem.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/lib/EnumItem.js 
b/modules/platforms/nodejs/lib/EnumItem.js
new file mode 100644
index 0000000..e4fb165
--- /dev/null
+++ b/modules/platforms/nodejs/lib/EnumItem.js
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+const ArgumentChecker = require('./internal/ArgumentChecker');
+const Errors = require('./Errors');
+
+/**
+ * Class representing an item of Ignite enum type.
+ *
+ * The item is defined by:
+ *   - type Id (mandatory) - Id of the Ignite enum type.
+ *   - ordinal (optional) - ordinal of the item in the Ignite enum type.
+ *   - name (optional) - name of the item (field name in the Ignite enum type).
+ *   - value (optional) - value of the item.
+ * Usually, at least one from the optional ordinal, name or value must be 
specified
+ * in order to use an instance of this class in Ignite operations.
+ *
+ * To distinguish one item from another, the Ignite client analyzes the 
optional fields in the following order:
+ * ordinal, name, value.
+ */
+class EnumItem {
+
+    /**
+     * Public constructor.
+     *
+     * @param {number} typeId - Id of the Ignite enum type.
+     *
+     * @return {EnumItem} - new EnumItem instance
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    constructor(typeId) {
+        this.setTypeId(typeId);
+        this._ordinal = null;
+        this._name = null;
+        this._value = null;
+    }
+
+    /**
+     * Returns Id of the Ignite enum type.
+     *
+     * @return {number} - Id of the enum type.
+     */
+    getTypeId() {
+        return this._typeId;
+    }
+
+    /**
+     * Updates Id of the Ignite enum type.
+     *
+     * @param {number} typeId - new Id of the Ignite enum type.
+     *
+     * @return {EnumItem} - the same instance of EnumItem
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setTypeId(typeId) {
+        ArgumentChecker.isInteger(typeId, 'typeId');
+        this._typeId = typeId;
+        return this;
+    }
+
+    /**
+     * Returns ordinal of the item in the Ignite enum type
+     * or null if ordinal is not set.
+     *
+     * @return {number} - ordinal of the item in the Ignite enum type.
+     */
+    getOrdinal() {
+        return this._ordinal;
+    }
+
+    /**
+     * Sets or updates ordinal of the item in the Ignite enum type.
+     *
+     * @param {number} ordinal - ordinal of the item in the Ignite enum type.
+     *
+     * @return {EnumItem} - the same instance of EnumItem
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setOrdinal(ordinal) {
+        ArgumentChecker.isInteger(ordinal, 'ordinal');
+        this._ordinal = ordinal;
+        return this;
+    }
+
+    /**
+     * Returns name of the item
+     * or null if name is not set.
+     *
+     * @return {string} - name of the item.
+     */
+    getName() {
+        return this._name;
+    }
+
+    /**
+     * Sets or updates name of the item.
+     *
+     * @param {string} name - name of the item.
+     *
+     * @return {EnumItem} - the same instance of EnumItem
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setName(name) {
+        ArgumentChecker.notEmpty(name, 'name');
+        this._name = name;
+        return this;
+    }
+
+    /**
+     * Returns value of the item
+     * or null if value is not set.
+     *
+     * @return {number} - value of the item.
+     */
+    getValue() {
+        return this._value;
+    }
+
+    /**
+     * Sets or updates value of the item.
+     *
+     * @param {number} value - value of the item.
+     *
+     * @return {EnumItem} - the same instance of EnumItem
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setValue(value) {
+        ArgumentChecker.isInteger(value, 'value');
+        this._value = value;
+        return this;
+    }
+
+    /** Private methods */
+
+    /**
+     * @ignore
+     */
+    async _write(buffer) {
+        buffer.writeInteger(this._typeId);
+        if (this._ordinal !== null) {
+            buffer.writeInteger(this._ordinal);
+            return;
+        }
+        else if (this._name !== null || this._value !== null) {
+            const type = await this._getType(this._typeId);
+            if (type._isEnum && type._enumValues) {
+                for (let i = 0; i < type._enumValues.length; i++) {
+                    if (this._name === type._enumValues[i][0] ||
+                        this._value === type._enumValues[i][1]) {
+                        buffer.writeInteger(i);
+                        return;
+                    }
+                }
+            }
+        }
+        throw Errors.IgniteClientError.illegalArgumentError(
+            'Proper ordinal, name or value must be specified for EnumItem');
+    }
+
+    /**
+     * @ignore
+     */
+    async _read(buffer) {
+        this._typeId = buffer.readInteger();
+        this._ordinal = buffer.readInteger();
+        const type = await this._getType(this._typeId);
+        if (!type._isEnum || !type._enumValues || type._enumValues.length <= 
this._ordinal) {
+            throw new Errors.IgniteClientError('EnumItem can not be 
deserialized: type mismatch');
+        }
+        this._name = type._enumValues[this._ordinal][0];
+        this._value = type._enumValues[this._ordinal][1];
+    }
+
+    /**
+     * @ignore
+     */
+    async _getType(typeId) {
+        const BinaryTypeStorage = require('./internal/BinaryTypeStorage');
+        return await BinaryTypeStorage.getEntity().getType(typeId);
+    }
+}
+
+module.exports = EnumItem;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c56d16fb/modules/platforms/nodejs/lib/Errors.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/lib/Errors.js 
b/modules/platforms/nodejs/lib/Errors.js
new file mode 100644
index 0000000..57a7a8c
--- /dev/null
+++ b/modules/platforms/nodejs/lib/Errors.js
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+const Util = require('util');
+
+/**
+ * Base Ignite client error class.
+ */
+class IgniteClientError extends Error {
+    constructor(message) {
+        super(message);
+    }
+
+    /**
+     * Ignite client does not support one of the specified or received data 
types.
+     * @ignore
+     */
+    static unsupportedTypeError(type) {
+        const BinaryUtils = require('./internal/BinaryUtils');
+        return new IgniteClientError(Util.format('Type %s is not supported', 
BinaryUtils.getTypeName(type)));
+    }
+
+    /**
+     * The real type of data is not equal to the specified one.
+     * @ignore
+     */
+    static typeCastError(fromType, toType) {
+        const BinaryUtils = require('./internal/BinaryUtils');
+        return new IgniteClientError(Util.format('Type "%s" can not be cast to 
%s',
+            BinaryUtils.getTypeName(fromType), 
BinaryUtils.getTypeName(toType)));
+    }
+
+    /**
+     * The real value can not be cast to the specified type.
+     * @ignore
+     */
+    static valueCastError(value, toType) {
+        const BinaryUtils = require('./internal/BinaryUtils');
+        return new IgniteClientError(Util.format('Value "%s" can not be cast 
to %s',
+            value, BinaryUtils.getTypeName(toType)));
+    }
+
+    /**
+     * An illegal or inappropriate argument has been passed to the API method.
+     * @ignore
+     */
+    static illegalArgumentError(message) {
+        return new IgniteClientError(message);
+    }
+
+    /**
+     * Ignite client internal error.
+     * @ignore
+     */
+    static internalError(message = null) {
+        return new IgniteClientError(message || 'Internal library error');
+    }
+
+    /**
+     * Serialization/deserialization errors.
+     * @ignore
+     */
+    static serializationError(serialize, message = null) {
+        let msg = serialize ? 'Complex object can not be serialized' : 
'Complex object can not be deserialized';
+        if (message) {
+            msg = msg + ': ' + message;
+        }
+        return new IgniteClientError(msg);
+    }
+}
+
+/**
+ * Ignite server returns error for the requested operation.
+ * @extends IgniteClientError
+ */
+class OperationError extends IgniteClientError {
+    constructor(message) {
+        super(message);
+    }
+}
+
+/**
+ * Ignite client is not in an appropriate state for the requested operation.
+ * @extends IgniteClientError
+ */
+class IllegalStateError extends IgniteClientError {
+    constructor(message = null) {
+        super(message || 'Ignite client is not in an appropriate state for the 
requested operation');
+    }
+}
+
+/**
+ * The requested operation is not completed due to the connection lost.
+ * @extends IgniteClientError
+ */
+class LostConnectionError extends IgniteClientError {
+    constructor(message = null) {
+        super(message || 'Request is not completed due to the connection 
lost');
+    }
+}
+
+module.exports.IgniteClientError = IgniteClientError;
+module.exports.OperationError = OperationError;
+module.exports.IllegalStateError = IllegalStateError;
+module.exports.LostConnectionError = LostConnectionError;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c56d16fb/modules/platforms/nodejs/lib/IgniteClient.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/lib/IgniteClient.js 
b/modules/platforms/nodejs/lib/IgniteClient.js
new file mode 100644
index 0000000..ba3361f
--- /dev/null
+++ b/modules/platforms/nodejs/lib/IgniteClient.js
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+const CacheClient = require('./CacheClient');
+const IgniteClientConfiguration = require('./IgniteClientConfiguration');
+const CacheConfiguration = require('./CacheConfiguration');
+const BinaryUtils = require('./internal/BinaryUtils');
+const BinaryWriter = require('./internal/BinaryWriter');
+const BinaryReader = require('./internal/BinaryReader');
+const BinaryTypeStorage = require('./internal/BinaryTypeStorage');
+const ArgumentChecker = require('./internal/ArgumentChecker');
+const Logger = require('./internal/Logger');
+
+/**
+ * State of Ignite client.
+ *
+ * @typedef IgniteClient.STATE
+ * @enum
+ * @readonly
+ * @property DISCONNECTED The client is not connected to any Ignite node,
+ *     operations with the Ignite server are not allowed.
+ *     This is initial state after a client instance creation.
+ *     If connect() method is called, the client moves to CONNECTING state.
+ * @property CONNECTING The client tries to connect to an Ignite node,
+ *     operations with the Ignite server are not allowed.
+ *     If disconnect() method is called, the client moves to DISCONNECTED 
state.
+ *     If not possible to connect to any Ignite node, the client moves to 
DISCONNECTED state.
+ *     If connection to an Ignite node is successful, the client moves to 
CONNECTED state.
+ * @property CONNECTED The client is connected to an Ignite node,
+ *     all operations with the Ignite server are allowed.
+ *     If connection with the Ignite node is lost, the client moves to 
CONNECTING state.
+ *     If disconnect() method is called, the client moves to DISCONNECTED 
state.
+ */
+const STATE = Object.freeze({
+    DISCONNECTED : 0,
+    CONNECTING : 1,
+    CONNECTED : 2
+});
+
+/**
+ * Class representing Ignite client.
+ * 
+ */
+class IgniteClient {
+
+    /**
+     * Public constructor.
+     *
+     * @param {IgniteClient.onStateChanged} [onStateChanged] -
+     * callback called everytime when the client has moved to a new state 
{@link IgniteClient.STATE}.
+     *
+     * @return {IgniteClient} - new IgniteClient instance.
+     */
+    constructor(onStateChanged = null) {
+        const ClientFailoverSocket = 
require('./internal/ClientFailoverSocket');
+        this._socket = new ClientFailoverSocket(onStateChanged);
+        BinaryTypeStorage.createEntity(this._socket);
+    }
+
+    static get STATE() {
+        return STATE;
+    }
+
+    /**
+     * onStateChanged callback.
+     * @callback IgniteClient.onStateChanged
+     * @param {IgniteClient.STATE} state - the new state of the client.
+     * @param {string} reason - the reason why the state has been changed.
+     */
+
+    /**
+     * Connects the client.
+     *
+     * Should be called from DISCONNECTED state only.
+     * Moves the client to CONNECTING state.
+     *
+     * @async
+     *
+     * @param {IgniteClientConfiguration} config - the client configuration.
+     *
+     * @throws {IllegalStateError} if the client is not in DISCONNECTED {@link 
IgniteClient.STATE}.
+     * @throws {IgniteClientError} if other error.
+     */
+    async connect(config) {
+        ArgumentChecker.notEmpty(config, 'config');
+        ArgumentChecker.hasType(config, 'config', false, 
IgniteClientConfiguration);
+        await this._socket.connect(config);
+    }
+
+    /**
+     * Disconnects the client.
+     *
+     * Moves the client to DISCONNECTED state from any other state.
+     * Does nothing if the client already disconnected.
+     */
+    disconnect() {
+        if (this._socket) {
+            this._socket.disconnect();
+        }
+    }
+
+    /**
+     * Creates new cache with the provided name and optional configuration.
+     *
+     * @async
+     *
+     * @param {string} name - cache name.
+     * @param {CacheConfiguration} [cacheConfig] - cache configuration.
+     *
+     * @return {Promise<CacheClient>} - new cache client instance for the 
created cache.
+     *
+     * @throws {IllegalStateError} if the client is not in CONNECTED {@link 
IgniteClient.STATE}.
+     * @throws {OperationError} if cache with the provided name already exists.
+     * @throws {IgniteClientError} if other error.
+     */
+    async createCache(name, cacheConfig = null) {
+        ArgumentChecker.notEmpty(name, 'name');
+        ArgumentChecker.hasType(cacheConfig, 'cacheConfig', false, 
CacheConfiguration);
+
+        await this._socket.send(
+            cacheConfig ?
+                BinaryUtils.OPERATION.CACHE_CREATE_WITH_CONFIGURATION :
+                BinaryUtils.OPERATION.CACHE_CREATE_WITH_NAME,
+            async (payload) => {
+                await this._writeCacheNameOrConfig(payload, name, cacheConfig);
+            });
+        return this._getCache(name, cacheConfig);
+    }
+
+    /**
+     * Gets existing cache with the provided name
+     * or creates new one with the provided name and optional configuration.
+     *
+     * @async
+     *
+     * @param {string} name - cache name.
+     * @param {CacheConfiguration} [cacheConfig] - cache configuration 
(ignored if cache
+     *   with the provided name already exists).
+     *
+     * @return {Promise<CacheClient>} - new cache client instance for the 
existing or created cache.
+     *
+     * @throws {IllegalStateError} if the client is not in CONNECTED {@link 
IgniteClient.STATE}.
+     * @throws {IgniteClientError} if other error.
+     */
+    async getOrCreateCache(name, cacheConfig = null) {
+        ArgumentChecker.notEmpty(name, 'name');
+        ArgumentChecker.hasType(cacheConfig, 'cacheConfig', false, 
CacheConfiguration);
+        await this._socket.send(
+            cacheConfig ?
+                BinaryUtils.OPERATION.CACHE_GET_OR_CREATE_WITH_CONFIGURATION :
+                BinaryUtils.OPERATION.CACHE_GET_OR_CREATE_WITH_NAME,
+            async (payload) => {
+                await this._writeCacheNameOrConfig(payload, name, cacheConfig);
+            });
+        return this._getCache(name, cacheConfig);
+    }
+
+    /**
+     * Gets cache client instance of cache with the provided name.
+     * The method does not check if the cache with the provided name exists.
+     *
+     * @param {string} name - cache name.
+     *
+     * @return {CacheClient} - new cache client instance.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    getCache(name) {
+        ArgumentChecker.notEmpty(name, 'name');
+        return this._getCache(name);
+    }
+
+    /**
+     * Destroys cache with the provided name.
+     *
+     * @async
+     *
+     * @param {string} name - cache name.
+     *
+     * @throws {IllegalStateError} if the client is not in CONNECTED {@link 
IgniteClient.STATE}.
+     * @throws {OperationError} if cache with the provided name does not exist.
+     * @throws {IgniteClientError} if other error.
+     */
+    async destroyCache(name) {
+        ArgumentChecker.notEmpty(name, 'name');
+        await this._socket.send(
+            BinaryUtils.OPERATION.CACHE_DESTROY,
+            async (payload) => {
+                payload.writeInteger(CacheClient._calculateId(name));
+            });
+    }
+
+    /**
+     * Returns configuration of cache with the provided name.
+     *
+     * @async
+     *
+     * @param {string} name - cache name.
+     *
+     * @return {Promise<CacheConfiguration>} - cache configuration
+     *
+     * @throws {IllegalStateError} if the client is not in CONNECTED {@link 
IgniteClient.STATE}.
+     * @throws {OperationError} if cache with the provided name does not exist.
+     * @throws {IgniteClientError} if other error.
+     */
+    async getCacheConfiguration(name) {
+        ArgumentChecker.notEmpty(name, 'name');
+        let config;
+        await this._socket.send(
+            BinaryUtils.OPERATION.CACHE_GET_CONFIGURATION,
+            async (payload) => {
+                payload.writeInteger(CacheClient._calculateId(name));
+                payload.writeByte(0);
+            },
+            async (payload) => {
+                config = new CacheConfiguration();
+                await config._read(payload);
+            });
+        return config;
+    }
+
+    /**
+     * Gets existing cache names.
+     *
+     * @async
+     *
+     * @return {Promise<Array<string>>} - array with the existing cache names.
+     *     The array is empty if no caches exist.
+     *
+     * @throws {IllegalStateError} if the client is not in CONNECTED {@link 
IgniteClient.STATE}.
+     * @throws {IgniteClientError} if other error.
+     */
+    async cacheNames() {
+        let names;
+        await this._socket.send(
+            BinaryUtils.OPERATION.CACHE_GET_NAMES,
+            null,
+            async (payload) => {
+                names = await BinaryReader.readStringArray(payload);
+            });
+        return names;
+    }
+
+    /**
+     * Enables/disables the library debug output (including errors logging).
+     * Disabled by default.
+     *
+     * @param {boolean} value - true to enable, false to disable
+     */
+    setDebug(value) {
+        Logger.debug = value;
+    }
+
+    /** Private methods */
+
+    /**
+     * @ignore
+     */
+    _getCache(name, cacheConfig = null) {
+        return new CacheClient(name, cacheConfig, this._socket);
+    }
+
+    /**
+     * @ignore
+     */
+    async _writeCacheNameOrConfig(buffer, name, cacheConfig) {
+        if (cacheConfig) {
+            await cacheConfig._write(buffer, name);
+        }
+        else {
+            await BinaryWriter.writeString(buffer, name);
+        }
+    }
+}
+
+module.exports = IgniteClient;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c56d16fb/modules/platforms/nodejs/lib/IgniteClientConfiguration.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/lib/IgniteClientConfiguration.js 
b/modules/platforms/nodejs/lib/IgniteClientConfiguration.js
new file mode 100644
index 0000000..5dab92a
--- /dev/null
+++ b/modules/platforms/nodejs/lib/IgniteClientConfiguration.js
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+const FS = require('fs');
+const Util = require('util');
+const Errors = require('./Errors');
+const ArgumentChecker = require('./internal/ArgumentChecker');
+
+/**
+ * Class representing Ignite client configuration.
+ *
+ * The configuration includes:
+ *   - (mandatory) Ignite node endpoint(s)
+ *   - (optional) user credentials for authentication
+ *   - (optional) TLS enabling
+ *   - (optional) connection options
+ */
+class IgniteClientConfiguration {
+
+    /**
+     * Creates an instance of Ignite client configuration
+     * with the provided mandatory settings and default optional settings.
+     *
+     * By default, the client does not use authentication and secure 
connection.
+     *
+     * @param {...string} endpoints - Ignite node endpoint(s).
+     *  The client randomly connects/reconnects to one of the specified node.
+     *
+     * @return {IgniteClientConfiguration} - new client configuration instance.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    constructor(...endpoints) {
+        ArgumentChecker.notEmpty(endpoints, 'endpoints');
+        this._endpoints = endpoints;
+        this._userName = null;
+        this._password = null;
+        this._useTLS = false;
+        this._options = null;
+    }
+
+
+    /**
+     * Sets username which will be used for authentication during the client's 
connection.
+     *
+     * If username is not set, the client does not use authentication during 
connection.
+     *
+     * @param {string} userName - username. If null, authentication is 
disabled.
+     *
+     * @return {IgniteClientConfiguration} - the same instance of the 
IgniteClientConfiguration.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setUserName(userName) {
+        this._userName = userName;
+        return this;
+    }
+
+    /**
+     * Sets password which will be used for authentication during the client's 
connection.
+     *
+     * Password is ignored, if username is not set.
+     * If password is not set, it is considered empty.
+     *
+     * @param {string} password - password. If null, password is empty.
+     *
+     * @return {IgniteClientConfiguration} - the same instance of the 
IgniteClientConfiguration.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setPassword(password) {
+        this._password = password;
+        return this;
+    }
+
+    /**
+     * Sets connection options.
+     *
+     * By default the client establishes a non-secure connection with default 
connection options defined by nodejs.
+     *
+     * @param {boolean} useTLS - if true, secure connection will be 
established;
+     *                           if false, non-secure connection will be 
established.
+     * @param {object} [connectionOptions=null] - connection options.
+     *   - For non-secure connection options defined here {@link 
https://nodejs.org/api/net.html#net_net_createconnection_options_connectlistener}
+     *   - For secure connection options defined here {@link 
https://nodejs.org/api/tls.html#tls_tls_connect_options_callback}
+     *
+     * @return {IgniteClientConfiguration} - the same instance of the 
IgniteClientConfiguration.
+     */
+    setConnectionOptions(useTLS, connectionOptions = null) {
+        this._useTLS = useTLS;
+        this._options = connectionOptions;
+        return this;
+    }
+}
+
+module.exports = IgniteClientConfiguration;

Reply via email to