From 3f6fa94a4b6c1a7289328e681a574342075a9b1b Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Fri, 2 Jun 2023 11:11:00 -0600 Subject: [PATCH 01/23] Added support for creating secondary indexes on a CDT context CLIENT-1803 Added support for creating secondary index on a CDT context Added index creation tests Ran linter --- lib/client.js | 2 ++ src/main/commands/index_create.cc | 26 +++++++++++++++++++------ test/index.js | 32 +++++++++++++++++++++++++++++++ test/test_helper.js | 5 +++-- 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/lib/client.js b/lib/client.js index 8917cc47..65494430 100644 --- a/lib/client.js +++ b/lib/client.js @@ -991,6 +991,7 @@ Client.prototype.connect = function (callback) { * created based on the type of values stored in the bin. This option needs to * be specified if the bin to be indexed contains list or map values and the * individual entries of the list or keys/values of the map should be indexed. + * @param {string} options.context - The {@link CdtContext} on which the index is to be created. * @param {module:aerospike.indexDataType} options.datatype - The data type of * the index to be created, e.g. Numeric, String or Geo. * @param {InfoPolicy} [policy] - The Info Policy to use for this operation. @@ -1058,6 +1059,7 @@ Client.prototype.createIndex = function (options, policy, callback) { options.index, options.type || as.indexType.DEFAULT, options.datatype, + { context: options.context }, policy ] diff --git a/src/main/commands/index_create.cc b/src/main/commands/index_create.cc index cfa5dfd4..9f0d0987 100644 --- a/src/main/commands/index_create.cc +++ b/src/main/commands/index_create.cc @@ -20,6 +20,7 @@ #include "conversions.h" #include "policy.h" #include "log.h" +#include "operations.h" extern "C" { #include @@ -42,6 +43,8 @@ class IndexCreateCommand : public AerospikeCommand { cf_free(policy); if (index != NULL) free(index); + if (with_context) + as_cdt_ctx_destroy(&context); } as_index_task task; @@ -52,6 +55,8 @@ class IndexCreateCommand : public AerospikeCommand { char *index = NULL; as_index_type itype; as_index_datatype dtype; + as_cdt_ctx context; + bool with_context; }; static void *prepare(const Nan::FunctionCallbackInfo &info) @@ -60,7 +65,7 @@ static void *prepare(const Nan::FunctionCallbackInfo &info) AerospikeClient *client = Nan::ObjectWrap::Unwrap(info.This()); IndexCreateCommand *cmd = - new IndexCreateCommand(client, info[7].As()); + new IndexCreateCommand(client, info[8].As()); LogInfo *log = client->log; if (as_strlcpy(cmd->ns, *Nan::Utf8String(info[0].As()), @@ -90,8 +95,16 @@ static void *prepare(const Nan::FunctionCallbackInfo &info) cmd->dtype = (as_index_datatype)Nan::To(info[5]).FromJust(); if (info[6]->IsObject()) { + if (get_optional_cdt_context(&cmd->context, &cmd->with_context, info[6].As(), "context", log) != + AS_NODE_PARAM_OK) { + return CmdSetError(cmd, AEROSPIKE_ERR_PARAM, + "Context parameter is invalid"); + } + } + + if (info[7]->IsObject()) { cmd->policy = (as_policy_info *)cf_malloc(sizeof(as_policy_info)); - if (infopolicy_from_jsobject(cmd->policy, info[6].As(), log) != + if (infopolicy_from_jsobject(cmd->policy, info[7].As(), log) != AS_NODE_PARAM_OK) { return CmdSetError(cmd, AEROSPIKE_ERR_PARAM, "Policy parameter is invalid"); @@ -115,9 +128,9 @@ static void execute(uv_work_t *req) "index=%s, type=%d, datatype=%d", cmd->ns, cmd->set, cmd->bin, cmd->index, cmd->itype, cmd->dtype); - aerospike_index_create_complex(cmd->as, &cmd->err, &cmd->task, cmd->policy, + aerospike_index_create_ctx(cmd->as, &cmd->err, &cmd->task, cmd->policy, cmd->ns, cmd->set, cmd->bin, cmd->index, - cmd->itype, cmd->dtype); + cmd->itype, cmd->dtype, cmd->with_context ? &cmd->context : NULL); } static void respond(uv_work_t *req, int status) @@ -144,8 +157,9 @@ NAN_METHOD(AerospikeClient::IndexCreate) TYPE_CHECK_REQ(info[3], IsString, "Index name must be a string"); TYPE_CHECK_OPT(info[4], IsNumber, "Index type must be an integer"); TYPE_CHECK_REQ(info[5], IsNumber, "Index datatype must be an integer"); - TYPE_CHECK_OPT(info[6], IsObject, "Policy must be an object"); - TYPE_CHECK_REQ(info[7], IsFunction, "Callback must be a function"); + TYPE_CHECK_OPT(info[6], IsObject, "Context must be an object"); + TYPE_CHECK_OPT(info[7], IsObject, "Policy must be an object"); + TYPE_CHECK_REQ(info[8], IsFunction, "Callback must be a function"); async_invoke(info, prepare, execute, respond); } diff --git a/test/index.js b/test/index.js index f98019e0..e3daebc8 100644 --- a/test/index.js +++ b/test/index.js @@ -23,6 +23,7 @@ const Aerospike = require('../lib/aerospike') const Job = require('../lib/job') const IndexJob = require('../lib/index_job') const helper = require('./test_helper') +const Context = Aerospike.cdt.Context context('secondary indexes', function () { const client = helper.client @@ -80,6 +81,37 @@ context('secondary indexes', function () { .then(() => verifyIndexExists(helper.namespace, testIndex.name)) }) + it('should create an index with CDT Context', function () { + const options = { + ns: helper.namespace, + set: helper.set, + bin: testIndex.bin, + index: testIndex.name, + type: Aerospike.indexType.LIST, + datatype: Aerospike.indexDataType.NUMERIC, + context: new Context().addListIndex(0) + } + + return client.createIndex(options) + .then(() => verifyIndexExists(helper.namespace, testIndex.name)) + }) + + it('should not create an index with CDT Context \'addListIndexCreate\'', function () { + const options = { + ns: helper.namespace, + set: helper.set, + bin: testIndex.bin, + index: testIndex.name, + type: Aerospike.indexType.LIST, + datatype: Aerospike.indexDataType.NUMERIC, + context: new Context().addListIndexCreate(0, 0, false) + } + + return client.createIndex(options) + .then(() => expect(1).to.equal(2)) + .catch(() => { expect('pass').to.equal('pass') }) + }) + it('should create an integer index with info policy', function () { const options = { ns: helper.namespace, diff --git a/test/test_helper.js b/test/test_helper.js index c865d480..9682b92d 100644 --- a/test/test_helper.js +++ b/test/test_helper.js @@ -72,14 +72,15 @@ function IndexHelper (client) { this.client = client } -IndexHelper.prototype.create = function (indexName, setName, binName, dataType, indexType) { +IndexHelper.prototype.create = function (indexName, setName, binName, dataType, indexType, context) { const index = { ns: options.namespace, set: setName, bin: binName, index: indexName, type: indexType || Aerospike.indexType.DEFAULT, - datatype: dataType + datatype: dataType, + context } return this.client.createIndex(index) .then(job => job.wait(10)) From e55c94647472e3ded50a8df565778d398ad6932a Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 01:17:19 -0600 Subject: [PATCH 02/23] Added support for queries on a secondary index located in a CDT context. CLIENT-1803 Added support for queries on a secondary index located in a CDT context. Modified query.where to replace the current filter rather than add another filter. Added context property to index filter classes and methods. Added unit tests for the above functionality. Linted code. --- lib/client.js | 8 +- lib/filter.js | 48 +++--- lib/query.js | 17 +-- src/include/query.h | 7 +- src/main/commands/query_apply.cc | 7 +- src/main/commands/query_async.cc | 8 +- src/main/commands/query_background.cc | 8 +- src/main/commands/query_foreach.cc | 7 +- src/main/commands/query_pages.cc | 28 +++- src/main/query.cc | 29 ++-- test/query.js | 203 +++++++++++++++++++++++++- 11 files changed, 308 insertions(+), 62 deletions(-) diff --git a/lib/client.js b/lib/client.js index 65494430..e6422c2e 100644 --- a/lib/client.js +++ b/lib/client.js @@ -991,9 +991,9 @@ Client.prototype.connect = function (callback) { * created based on the type of values stored in the bin. This option needs to * be specified if the bin to be indexed contains list or map values and the * individual entries of the list or keys/values of the map should be indexed. - * @param {string} options.context - The {@link CdtContext} on which the index is to be created. * @param {module:aerospike.indexDataType} options.datatype - The data type of * the index to be created, e.g. Numeric, String or Geo. + * @param {Object} options.context - The {@link CdtContext} on which the index is to be created. * @param {InfoPolicy} [policy] - The Info Policy to use for this operation. * @param {jobCallback} [callback] - The function to call when the operation completes. * @@ -1009,6 +1009,7 @@ Client.prototype.connect = function (callback) { * @example * * const Aerospike = require('aerospike') + * const Context = Aerospike.cdt.Context * * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! * var config = { @@ -1025,12 +1026,15 @@ Client.prototype.connect = function (callback) { * let indexName = 'recentLocationsIdx' * let indexType = Aerospike.indexType.LIST * let dataType = Aerospike.indexDataType.GEO2DSPHERE + * let context = new Context().addListIndex(0) * let options = { ns: namespace, * set: set, * bin: binName, * index: indexName, * type: indexType, - * datatype: dataType } + * datatype: dataType, + * context: context } + * * let policy = new Aerospike.InfoPolicy({ timeout: 100 }) * * client.createIndex(options, policy, (error, job) => { diff --git a/lib/filter.js b/lib/filter.js index 9152ca94..0c820786 100644 --- a/lib/filter.js +++ b/lib/filter.js @@ -30,10 +30,11 @@ const GeoJSON = require('./geojson') * @example * * const Aerospike = require('aerospike') + * const Context = Aerospike.cdt.Context * * Aerospike.connect().then(async (client) => { * // find any records that have a recent location within 1000m radius of the specified coordinates - * let geoFilter = Aerospike.filter.geoWithinRadius('recent', 103.8, 1.305, 1000, Aerospike.indexType.LIST) + * let geoFilter = Aerospike.filter.geoWithinRadius('recent', 103.8, 1.305, 1000, Aerospike.indexType.LIST, new Context().addListIndex(0)) * let query = client.query('test', 'demo') * query.where(geoFilter) * @@ -53,11 +54,12 @@ const GeoJSON = require('./geojson') * module:aerospike/filter} module. */ class SindexFilterPredicate { - constructor (predicate, bin, dataType, indexType, props) { + constructor (predicate, bin, dataType, indexType, context, props) { this.predicate = predicate this.bin = bin this.datatype = dataType this.type = indexType || as.indexType.DEFAULT + this.context = context if (props) { Object.assign(this, props) } @@ -66,16 +68,16 @@ class SindexFilterPredicate { exports.SindexFilterPredicate = SindexFilterPredicate class EqualPredicate extends SindexFilterPredicate { - constructor (bin, value, dataType, indexType) { - super(as.predicates.EQUAL, bin, dataType, indexType, { + constructor (bin, value, dataType, indexType, context) { + super(as.predicates.EQUAL, bin, dataType, indexType, context, { val: value }) } } class RangePredicate extends SindexFilterPredicate { - constructor (bin, min, max, dataType, indexType) { - super(as.predicates.RANGE, bin, dataType, indexType, { + constructor (bin, min, max, dataType, indexType, context) { + super(as.predicates.RANGE, bin, dataType, indexType, context, { min, max }) @@ -83,8 +85,8 @@ class RangePredicate extends SindexFilterPredicate { } class GeoPredicate extends SindexFilterPredicate { - constructor (bin, value, indexType) { - super(as.predicates.RANGE, bin, as.indexDataType.GEO2DSPHERE, indexType, { + constructor (bin, value, indexType, context) { + super(as.predicates.RANGE, bin, as.indexDataType.GEO2DSPHERE, indexType, context, { val: value }) } @@ -124,12 +126,13 @@ function dataTypeOf (value) { * @param {number} max - Upper end of the range (inclusive). * @param {number} [indexType=Aerospike.indexType.DEFAULT] - One of {@link * module:aerospike.indexType}, i.e. LIST or MAPVALUES. + * @param {Object} context - The {@link CdtContext} of the index. * @returns {module:aerospike/filter~SindexFilterPredicate} SI * filter predicate, that can be applied to queries using {@link Query#where}. */ -exports.range = function (bin, min, max, indexType) { +exports.range = function (bin, min, max, indexType, context) { const dataType = as.indexDataType.NUMERIC - return new RangePredicate(bin, min, max, dataType, indexType) + return new RangePredicate(bin, min, max, dataType, indexType, context) } /** @@ -157,14 +160,15 @@ exports.equal = function (bin, value) { * list or map in the bin. * @param {number} indexType - One of {@link module:aerospike.indexType}, * i.e. LIST, MAPVALUES or MAPKEYS. + * @param {Object} context - The {@link CdtContext} of the index. * @returns {module:aerospike/filter~SindexFilterPredicate} SI * filter predicate, that can be applied to queries using {@link Query#where}. * * @since v2.0 */ -exports.contains = function (bin, value, indexType) { +exports.contains = function (bin, value, indexType, context) { const dataType = dataTypeOf(value) - return new EqualPredicate(bin, value, dataType, indexType) + return new EqualPredicate(bin, value, dataType, indexType, context) } /** @@ -178,18 +182,19 @@ exports.contains = function (bin, value, indexType) { * @param {GeoJSON} value - GeoJSON region value. * @param {number} [indexType=Aerospike.indexType.DEFAULT] - One of {@link * module:aerospike.indexType}, i.e. LIST or MAPVALUES. + * @param {Object} context - The {@link CdtContext} of the index. * @returns {module:aerospike/filter~SindexFilterPredicate} SI * filter predicate, that can be applied to queries using {@link Query#where}. * * @since v2.0 */ -exports.geoWithinGeoJSONRegion = function (bin, value, indexType) { +exports.geoWithinGeoJSONRegion = function (bin, value, indexType, context) { if (value instanceof GeoJSON) { value = value.toString() } else if (typeof value === 'object') { value = JSON.stringify(value) } - return new GeoPredicate(bin, value, indexType) + return new GeoPredicate(bin, value, indexType, context) } /** @@ -203,18 +208,19 @@ exports.geoWithinGeoJSONRegion = function (bin, value, indexType) { * @param {GeoJSON} value - GeoJSON point value. * @param {number} [indexType=Aerospike.indexType.DEFAULT] - One of {@link * module:aerospike.indexType}, i.e. LIST or MAPVALUES. + * @param {Object} context - The {@link CdtContext} of the index. * @returns {module:aerospike/filter~SindexFilterPredicate} SI * filter predicate, that can be applied to queries using {@link Query#where}. * * @since v2.0 */ -exports.geoContainsGeoJSONPoint = function (bin, value, indexType) { +exports.geoContainsGeoJSONPoint = function (bin, value, indexType, context) { if (value instanceof GeoJSON) { value = value.toString() } else if (typeof value === 'object') { value = JSON.stringify(value) } - return new GeoPredicate(bin, value, indexType) + return new GeoPredicate(bin, value, indexType, context) } /** @@ -230,14 +236,15 @@ exports.geoContainsGeoJSONPoint = function (bin, value, indexType) { * @param {number} radius - Radius in meters. * @param {number} [indexType=Aerospike.indexType.DEFAULT] - One of {@link * module:aerospike.indexType}, i.e. LIST or MAPVALUES. + * @param {Object} context - The {@link CdtContext} of the index. * @returns {module:aerospike/filter~SindexFilterPredicate} SI * filter predicate, that can be applied to queries using {@link Query#where}. * * @since v2.0 */ -exports.geoWithinRadius = function (bin, lon, lat, radius, indexType) { +exports.geoWithinRadius = function (bin, lon, lat, radius, indexType, context) { const circle = GeoJSON.Circle(lon, lat, radius) - return new GeoPredicate(bin, circle.toString(), indexType) + return new GeoPredicate(bin, circle.toString(), indexType, context) } /** @@ -252,12 +259,13 @@ exports.geoWithinRadius = function (bin, lon, lat, radius, indexType) { * @param {number} lat - Latitude of the point. * @param {number} [indexType=Aerospike.indexType.DEFAULT] - One of {@link * module:aerospike.indexType}, i.e. LIST or MAPVALUES. + * @param {Object} context - The {@link CdtContext} of the index. * @returns {module:aerospike/filter~SindexFilterPredicate} SI * filter predicate, that can be applied to queries using {@link Query#where}. * * @since v2.0 */ -exports.geoContainsPoint = function (bin, lon, lat, indexType) { +exports.geoContainsPoint = function (bin, lon, lat, indexType, context) { const point = GeoJSON.Point(lon, lat) - return new GeoPredicate(bin, point.toString(), indexType) + return new GeoPredicate(bin, point.toString(), indexType, context) } diff --git a/lib/query.js b/lib/query.js index e8b047a2..2344cf19 100644 --- a/lib/query.js +++ b/lib/query.js @@ -473,20 +473,6 @@ Query.prototype.select = function (bins) { * }) * * @see {@link module:aerospike/filter} to create SI filters. - * - * const Aerospike = require('aerospike') - * - * Aerospike.connect().then(client => { - * let query = client.query('test', 'demo') - * - * let tagsFilter = Aerospike.filter.contains('tags', 'blue', Aerospike.indexType.LIST) - * query.where(tagsFilter) - * - * let stream = query.foreach() - * stream.on('data', record => { console.info(record.bins.tags) }) - * stream.on('error', error => { throw error }) - * stream.on('end', () => client.close()) - * }) */ Query.prototype.where = function (indexFilter) { if (indexFilter instanceof filter.SindexFilterPredicate) { @@ -497,7 +483,7 @@ Query.prototype.where = function (indexFilter) { } Query.prototype.setSindexFilter = function (sindexFilter) { - this.filters = this.filters || [] + this.filters = [] this.filters.push(sindexFilter) } @@ -586,6 +572,7 @@ Query.prototype.foreach = function (policy, dataCb, errorCb, endCb) { if (this.paginate) { args.push(this.queryState) args.push(this.maxRecords) + args.push(this.filters[0].context ? { context: this.filters[0].context } : null) cmd = new Commands.QueryPages(stream, args) } else { cmd = new Commands.Query(stream, args) diff --git a/src/include/query.h b/src/include/query.h index d715bce8..f097a4fa 100644 --- a/src/include/query.h +++ b/src/include/query.h @@ -34,8 +34,9 @@ struct query_udata { void setup_query(as_query *query, v8::Local ns, v8::Local set, v8::Local maybe_options, - LogInfo *log); -void setup_options(as_query *query, v8::Local options, LogInfo *log); + as_cdt_ctx* context, bool* with_context, LogInfo *log); +void setup_options(as_query *query, v8::Local options, as_cdt_ctx* context, bool* with_context, LogInfo *log); void setup_query_pages(as_query ** query, v8::Local ns, v8::Local set, - v8::Localmaybe_options, uint8_t* bytes, uint32_t bytes_size, LogInfo *log); + v8::Localmaybe_options, uint8_t* bytes, uint32_t bytes_size, + as_cdt_ctx* context, bool* with_context, LogInfo *log); void free_query(as_query *query, as_policy_query *policy); diff --git a/src/main/commands/query_apply.cc b/src/main/commands/query_apply.cc index f54b28d7..3268e257 100644 --- a/src/main/commands/query_apply.cc +++ b/src/main/commands/query_apply.cc @@ -46,11 +46,16 @@ class QueryApplyCommand : public AerospikeCommand { cf_free(policy); if (val != NULL) cf_free(val); + if(with_context){ + as_cdt_ctx_destroy(&context); + } } as_policy_query *policy = NULL; as_query query; as_val *val = NULL; + as_cdt_ctx context; + bool with_context = false; }; static bool query_foreach_callback(const as_val *val, void *udata) @@ -71,7 +76,7 @@ static void *prepare(const Nan::FunctionCallbackInfo &info) new QueryApplyCommand(client, info[4].As()); LogInfo *log = client->log; - setup_query(&cmd->query, info[0], info[1], info[2], log); + setup_query(&cmd->query, info[0], info[1], info[2], &cmd->context, &cmd->with_context, log); if (info[3]->IsObject()) { cmd->policy = (as_policy_query *)cf_malloc(sizeof(as_policy_query)); diff --git a/src/main/commands/query_async.cc b/src/main/commands/query_async.cc index 60b6d6f0..2599baec 100644 --- a/src/main/commands/query_async.cc +++ b/src/main/commands/query_async.cc @@ -53,8 +53,10 @@ NAN_METHOD(AerospikeClient::QueryAsync) as_status status; as_partition_filter pf; bool pf_defined = false; + as_cdt_ctx context; + bool with_context = false; - setup_query(&query, info[0], info[1], info[2], log); + setup_query(&query, info[0], info[1], info[2], &context, &with_context, log); if (info[3]->IsObject()) { if (querypolicy_from_jsobject(&policy, info[3].As(), log) != @@ -95,4 +97,8 @@ NAN_METHOD(AerospikeClient::QueryAsync) Cleanup: delete cmd; free_query(&query, p_policy); + if(with_context){ + as_cdt_ctx_destroy(&context); + } + } diff --git a/src/main/commands/query_background.cc b/src/main/commands/query_background.cc index f8e31f45..54f096b6 100644 --- a/src/main/commands/query_background.cc +++ b/src/main/commands/query_background.cc @@ -44,11 +44,16 @@ class QueryBackgroundCommand : public AerospikeCommand { free_query(&query, NULL); if (policy != NULL) cf_free(policy); + if(with_context){ + as_cdt_ctx_destroy(&context); + } } as_policy_write *policy = NULL; uint64_t query_id = 0; as_query query; + as_cdt_ctx context; + bool with_context = false; }; static void *prepare(const Nan::FunctionCallbackInfo &info) @@ -59,7 +64,8 @@ static void *prepare(const Nan::FunctionCallbackInfo &info) new QueryBackgroundCommand(client, info[5].As()); LogInfo *log = client->log; - setup_query(&cmd->query, info[0], info[1], info[2], log); + + setup_query(&cmd->query, info[0], info[1], info[2], &cmd->context, &cmd->with_context, log); if (info[3]->IsObject()) { cmd->policy = (as_policy_write *)cf_malloc(sizeof(as_policy_write)); diff --git a/src/main/commands/query_foreach.cc b/src/main/commands/query_foreach.cc index df68f53c..5e440f1d 100644 --- a/src/main/commands/query_foreach.cc +++ b/src/main/commands/query_foreach.cc @@ -54,6 +54,9 @@ class QueryForeachCommand : public AerospikeCommand { as_queue_mt_destroy(results); results = NULL; } + if(with_context){ + as_cdt_ctx_destroy(&context); + } } as_policy_query *policy = NULL; @@ -62,6 +65,8 @@ class QueryForeachCommand : public AerospikeCommand { uint32_t max_q_size; uint32_t signal_interval = 0; uv_async_t async_handle; + as_cdt_ctx context; + bool with_context = false; }; // Push the record from the server to a queue. @@ -151,7 +156,7 @@ static void *prepare(const Nan::FunctionCallbackInfo &info) new QueryForeachCommand(client, info[4].As()); LogInfo *log = client->log; - setup_query(&cmd->query, info[0], info[1], info[2], log); + setup_query(&cmd->query, info[0], info[1], info[2], &cmd->context, &cmd->with_context, log); if (info[3]->IsObject()) { cmd->policy = (as_policy_query *)cf_malloc(sizeof(as_policy_query)); diff --git a/src/main/commands/query_pages.cc b/src/main/commands/query_pages.cc index f0755513..f1e7b58f 100644 --- a/src/main/commands/query_pages.cc +++ b/src/main/commands/query_pages.cc @@ -21,6 +21,7 @@ #include "policy.h" #include "log.h" #include "query.h" +#include "operations.h" extern "C" { #include @@ -40,13 +41,14 @@ NAN_METHOD(AerospikeClient::QueryPages) TYPE_CHECK_OPT(info[2], IsObject, "Options must be an object"); TYPE_CHECK_OPT(info[3], IsObject, "Policy must be an object"); TYPE_CHECK_OPT(info[4], IsObject, "saved_query must be an object"); - TYPE_CHECK_OPT(info[5], IsNumber, "max_records must be an object"); - TYPE_CHECK_REQ(info[6], IsFunction, "Callback must be a function"); + TYPE_CHECK_OPT(info[5], IsNumber, "max_records must be a number"); + TYPE_CHECK_OPT(info[6], IsObject, "context must be an object"); + TYPE_CHECK_REQ(info[7], IsFunction, "Callback must be a function"); AerospikeClient *client = Nan::ObjectWrap::Unwrap(info.This()); AsyncCommand *cmd = - new AsyncCommand("Query", client, info[6].As()); + new AsyncCommand("Query", client, info[7].As()); LogInfo *log = client->log; as_policy_query* p_policy = NULL; @@ -54,23 +56,36 @@ NAN_METHOD(AerospikeClient::QueryPages) as_partition_filter pf; bool pf_defined = false; as_status status; + as_cdt_ctx context; + bool with_context = false; struct query_udata* qu = (query_udata*) cf_malloc(sizeof(struct query_udata)); qu->cmd = cmd; qu->count = 0; + if (info[6]->IsObject()) { + if (get_optional_cdt_context(&context, &with_context, info[6].As(), "context", log) != + AS_NODE_PARAM_OK) { + as_v8_error(log, "Parsing context arguments for query index filter failed"); + Nan::ThrowTypeError("Error in filter context"); + } + } + if (info[4]->IsObject()) { uint32_t bytes_size = 0; load_bytes_size(info[4].As(), &bytes_size, log); uint8_t* bytes = new uint8_t[bytes_size]; load_bytes(info[4].As(), bytes, bytes_size, log); - setup_query_pages(&qu->query, info[0], info[1], Nan::Null(), bytes, bytes_size, log); + setup_query_pages(&qu->query, info[0], info[1], Nan::Null(), bytes, bytes_size, &context, &with_context, log); delete bytes; } else{ - setup_query_pages(&qu->query, info[0], info[1], info[2], NULL, 0, log); + setup_query_pages(&qu->query, info[0], info[1], info[2], NULL, 0, &context, &with_context, log); } + if(with_context) { + qu->query->where.entries[0].ctx = &context; + } if (info[3]->IsObject()) { if (querypolicy_from_jsobject(&policy, info[3].As(), log) != @@ -120,5 +135,8 @@ NAN_METHOD(AerospikeClient::QueryPages) if (p_policy && policy.base.filter_exp) { as_exp_destroy(policy.base.filter_exp); } + if(with_context) { + as_cdt_ctx_destroy(&context); + } } \ No newline at end of file diff --git a/src/main/query.cc b/src/main/query.cc index 64af4442..779d14fd 100644 --- a/src/main/query.cc +++ b/src/main/query.cc @@ -31,7 +31,7 @@ extern "C" { using namespace v8; void setup_query(as_query *query, Local ns, Local set, - Local maybe_options, LogInfo *log) + Local maybe_options, as_cdt_ctx* context, bool* with_context, LogInfo *log) { as_namespace as_ns = {'\0'}; as_set as_set = {'\0'}; @@ -50,18 +50,18 @@ void setup_query(as_query *query, Local ns, Local set, // TODO: Return param error } } - as_query_init(query, as_ns, as_set); if (!maybe_options->IsObject()) { return; } - setup_options(query, maybe_options.As(), log); + + setup_options(query, maybe_options.As(), context, with_context, log); } -void setup_options(as_query *query, Local options, LogInfo *log) +void setup_options(as_query *query, Local options, as_cdt_ctx* context, bool* with_context, LogInfo *log) { Local filters_val = @@ -76,6 +76,14 @@ void setup_options(as_query *query, Local options, LogInfo *log) for (int i = 0; i < size; i++) { Local filter = Nan::Get(filters, i).ToLocalChecked().As(); + if(!(*with_context)){ + if (get_optional_cdt_context(context, with_context, filter, "context", log) != + AS_NODE_PARAM_OK) { + as_v8_error(log, "Parsing context arguments for query index filter failed"); + Nan::ThrowTypeError("Error in filter context"); + } + } + Local bin = Nan::Get(filter, Nan::New("bin").ToLocalChecked()) .ToLocalChecked(); @@ -115,7 +123,7 @@ void setup_options(as_query *query, Local options, LogInfo *log) if (v8min->IsNumber() && v8max->IsNumber()) { const int64_t min = Nan::To(v8min).FromJust(); const int64_t max = Nan::To(v8max).FromJust(); - as_query_where(query, bin_name, predicate, type, + as_query_where_with_ctx(query, bin_name, *with_context ? context : NULL, predicate, type, datatype, min, max); as_v8_debug(log, "Integer range predicate from %llu to %llu", @@ -140,7 +148,7 @@ void setup_options(as_query *query, Local options, LogInfo *log) "The region value passed is not a GeoJSON string"); } const char *bin_val = strdup(*Nan::Utf8String(value)); - as_query_where(query, bin_name, predicate, type, datatype, + as_query_where_with_ctx(query, bin_name, *with_context ? context : NULL, predicate, type, datatype, bin_val); as_v8_debug(log, "Geo range predicate %s", bin_val); } @@ -153,7 +161,7 @@ void setup_options(as_query *query, Local options, LogInfo *log) .ToLocalChecked(); if (value->IsNumber()) { const int64_t val = Nan::To(value).FromJust(); - as_query_where(query, bin_name, predicate, type, + as_query_where_with_ctx(query, bin_name, *with_context ? context : NULL, predicate, type, datatype, val); as_v8_debug(log, "Integer equality predicate %d", val); } @@ -175,7 +183,7 @@ void setup_options(as_query *query, Local options, LogInfo *log) "predicate - value is not a string"); } const char *bin_val = strdup(*Nan::Utf8String(value)); - as_query_where(query, bin_name, predicate, type, datatype, + as_query_where_with_ctx(query, bin_name, *with_context ? context : NULL, predicate, type, datatype, bin_val); as_v8_debug(log, "String equality predicate %s", bin_val); } @@ -253,7 +261,8 @@ void setup_options(as_query *query, Local options, LogInfo *log) } void setup_query_pages(as_query** query, Local ns, Local set, - Local maybe_options, uint8_t* bytes, uint32_t bytes_size, LogInfo *log) + Local maybe_options, uint8_t* bytes, uint32_t bytes_size, + as_cdt_ctx* context, bool* with_context, LogInfo *log) { as_namespace as_ns = {'\0'}; as_set as_set = {'\0'}; @@ -285,7 +294,7 @@ void setup_query_pages(as_query** query, Local ns, Local set, return; } - setup_options(*query, maybe_options.As(), log); + setup_options(*query, maybe_options.As(), context, with_context, log); } diff --git a/test/query.js b/test/query.js index 717f346a..8e51c20a 100644 --- a/test/query.js +++ b/test/query.js @@ -24,6 +24,7 @@ const Query = require('../lib/query') const Job = require('../lib/job') const helper = require('./test_helper') const exp = Aerospike.exp +const Context = Aerospike.cdt.Context const AerospikeError = Aerospike.AerospikeError const GeoJSON = Aerospike.GeoJSON @@ -79,7 +80,37 @@ describe('Queries', function () { { name: 'filter', value: 1 }, { name: 'filter', value: 2 }, { name: 'filter', value: 3 }, - { name: 'filter', value: 4 } + { name: 'filter', value: 4 }, + + { name: 'nested int list match', li: { nested: [1, 5, 9] } }, + { name: 'nested int list non-match', li: { nested: [500, 501, 502] } }, + { name: 'nested int map match', mi: { nested: { a: 1, b: 5, c: 9 } } }, + { name: 'nested int map non-match', mi: { nested: { a: 500, b: 501, c: 502 } } }, + { name: 'nested string list match', ls: { nested: ['banana', 'blueberry'] } }, + { name: 'nested string list non-match', ls: { nested: ['tomato', 'cuccumber'] } }, + { name: 'nested string map match', ms: { nested: { a: 'banana', b: 'blueberry' } } }, + { name: 'nested string map non-match', ms: { nested: { a: 'tomato', b: 'cuccumber' } } }, + { name: 'nested string mapkeys match', mks: { nested: { banana: 1, blueberry: 2 } } }, + { name: 'nested string mapkeys non-match', mks: { nested: { tomato: 3, cuccumber: 4 } } }, + { name: 'nested point match', g: { nested: GeoJSON.Point(103.913, 1.308) } }, + { name: 'nested point non-match', g: { nested: GeoJSON.Point(-122.101, 37.421) } }, + { name: 'nested point list match', lg: { nested: [GeoJSON.Point(103.913, 1.308), GeoJSON.Point(105.913, 3.308)] } }, + { name: 'nested point list non-match', lg: { nested: [GeoJSON.Point(-122.101, 37.421), GeoJSON.Point(-120.101, 39.421)] } }, + { name: 'nested point map match', mg: { nested: { a: GeoJSON.Point(103.913, 1.308), b: GeoJSON.Point(105.913, 3.308) } } }, + { name: 'nested point map non-match', mg: { nested: { a: GeoJSON.Point(-122.101, 37.421), b: GeoJSON.Point(-120.101, 39.421) } } }, + { name: 'nested region match', g: { nested: GeoJSON.Polygon([102.913, 0.308], [102.913, 2.308], [104.913, 2.308], [104.913, 0.308], [102.913, 0.308]) } }, + { name: 'nested region non-match', g: { nested: GeoJSON.Polygon([-121.101, 36.421], [-121.101, 38.421], [-123.101, 38.421], [-123.101, 36.421], [-121.101, 36.421]) } }, + { name: 'nested region list match', lg: { nested: [GeoJSON.Polygon([102.913, 0.308], [102.913, 2.308], [104.913, 2.308], [104.913, 0.308], [102.913, 0.308])] } }, + { name: 'nested region list non-match', lg: { nested: [GeoJSON.Polygon([-121.101, 36.421], [-121.101, 38.421], [-123.101, 38.421], [-123.101, 36.421], [-121.101, 36.421])] } }, + { name: 'nested region map match', mg: { nested: { a: GeoJSON.Polygon([102.913, 0.308], [102.913, 2.308], [104.913, 2.308], [104.913, 0.308], [102.913, 0.308]) } } }, + { name: 'nested region map non-match', mg: { nested: [GeoJSON.Polygon([-121.101, 36.421], [-121.101, 38.421], [-123.101, 38.421], [-123.101, 36.421], [-121.101, 36.421])] } }, + { name: 'nested aggregate', nested: { value: 10 } }, + { name: 'nested aggregate', nested: { value: 20 } }, + { name: 'nested aggregate', nested: { value: 30 } }, + { name: 'nested aggregate', nested: { doubleNested: { value: 10 } } }, + { name: 'nested aggregate', nested: { doubleNested: { value: 20 } } }, + { name: 'nested aggregate', nested: { doubleNested: { value: 30 } } } + ] const numberOfSamples = samples.length const indexes = [ @@ -93,7 +124,18 @@ describe('Queries', function () { ['qidxStrMapKeys', 'mks', STRING, MAPKEYS], ['qidxGeo', 'g', GEO2DSPHERE], ['qidxGeoList', 'lg', GEO2DSPHERE, LIST], - ['qidxGeoMap', 'mg', GEO2DSPHERE, MAPVALUES] + ['qidxGeoMap', 'mg', GEO2DSPHERE, MAPVALUES], + // CDT context indexes + ['qidxNameNested', 'name', STRING, MAPKEYS, new Context().addMapKey('nested')], + ['qidxIntListNested', 'li', NUMERIC, LIST, new Context().addMapKey('nested')], + ['qidxIntMapNested', 'mi', NUMERIC, MAPVALUES, new Context().addMapKey('nested')], + ['qidxStrListNested', 'ls', STRING, LIST, new Context().addMapKey('nested')], + ['qidxStrMapNested', 'ms', STRING, MAPVALUES, new Context().addMapKey('nested')], + ['qidxStrMapKeysNested', 'mks', STRING, MAPKEYS, new Context().addMapKey('nested')], + ['qidxGeoListNested', 'lg', GEO2DSPHERE, LIST, new Context().addMapKey('nested')], + ['qidxGeoMapNested', 'mg', GEO2DSPHERE, MAPVALUES, new Context().addMapKey('nested')], + ['qidxAggregateMapNested', 'nested', STRING, MAPKEYS], + ['qidxAggregateMapDoubleNested', 'nested', STRING, MAPKEYS, new Context().addMapKey('doubleNested')] ] let keys = [] @@ -122,7 +164,7 @@ describe('Queries', function () { putgen.put(numberOfSamples, generators) .then((records) => { keys = records.map((rec) => rec.key) }) .then(() => Promise.all(indexes.map(idx => - helper.index.create(idx[0], testSet, idx[1], idx[2], idx[3])))), + helper.index.create(idx[0], testSet, idx[1], idx[2], idx[3], idx[4])))), helper.udf.register('udf.lua') ]) }) @@ -200,6 +242,22 @@ describe('Queries', function () { }) }) + it('should apply a stream UDF to the nested context', function (done) { + const args = { + filters: [filter.contains('name', 'value', MAPKEYS, new Context().addMapKey('nested'))] + } + const query = client.query(helper.namespace, testSet, args) + query.setUdf('udf', 'even') + const stream = query.foreach() + const results = [] + stream.on('error', error => { throw error }) + stream.on('data', record => results.push(record.bins)) + stream.on('end', () => { + expect(results.sort()).to.eql([]) + done() + }) + }) + describe('query.paginate()', function () { it('paginates with the correct amount of keys and pages', async function () { let recordsReceived = 0 @@ -292,6 +350,32 @@ describe('Queries', function () { } }) + it('Paginates correctly using query.results() on an index with a cdt context', async function () { + let recordTotal = 0 + let recordsReceived = 0 + let pageTotal = 0 + const lastPage = 1 + const maxRecs = 5 + const query = client.query(helper.namespace, testSet, { paginate: true, maxRecords: maxRecs, filters: [filter.contains('nested', 'value', MAPKEYS, new Context().addMapKey('doubleNested'))] }) + let results = [] + while (1) { + console.log(results) + results = await query.results() + console.log(results) + recordsReceived += results.length + results = [] + pageTotal += 1 + recordTotal += recordsReceived + if (recordsReceived !== maxRecs) { + expect(query.hasNextPage()).to.equal(false) + expect(pageTotal).to.equal(lastPage) + expect(recordTotal).to.equal(3) + break + } + recordsReceived = 0 + } + }) + it('Throw error when query.UDF is set and query.paginate is true', async function () { const maxRecs = 2 const query = client.query(helper.namespace, testSet, { paginate: true, maxRecords: maxRecs, filters: [filter.equal('name', 'filter')] }) @@ -481,10 +565,20 @@ describe('Queries', function () { verifyQueryResults(args, 'int list match', done) }) + it('should match integers in a list within a range in a nested context', function (done) { + const args = { filters: [filter.range('li', 3, 7, LIST, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested int list match', done) + }) + it('should match integers in a map within a range', function (done) { const args = { filters: [filter.range('mi', 3, 7, MAPVALUES)] } verifyQueryResults(args, 'int map match', done) }) + + it('should match integers in a map within a range in a nested context', function (done) { + const args = { filters: [filter.range('mi', 3, 7, MAPVALUES, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested int map match', done) + }) }) describe('filter.contains()', function () { @@ -493,26 +587,51 @@ describe('Queries', function () { verifyQueryResults(args, 'int list match', done) }) + it('should match lists containing an integer in a nested context', function (done) { + const args = { filters: [filter.contains('li', 5, LIST, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested int list match', done) + }) + it('should match maps containing an integer value', function (done) { const args = { filters: [filter.contains('mi', 5, MAPVALUES)] } verifyQueryResults(args, 'int map match', done) }) + it('should match maps containing an integer value in a nested context', function (done) { + const args = { filters: [filter.contains('mi', 5, MAPVALUES, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested int map match', done) + }) + it('should match lists containing a string', function (done) { const args = { filters: [filter.contains('ls', 'banana', LIST)] } verifyQueryResults(args, 'string list match', done) }) + it('should match lists containing a string in a nested context', function (done) { + const args = { filters: [filter.contains('ls', 'banana', LIST, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested string list match', done) + }) + it('should match maps containing a string value', function (done) { const args = { filters: [filter.contains('ms', 'banana', MAPVALUES)] } verifyQueryResults(args, 'string map match', done) }) + it('should match maps containing a string value in a nested context', function (done) { + const args = { filters: [filter.contains('ms', 'banana', MAPVALUES, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested string map match', done) + }) + it('should match maps containing a string key', function (done) { const args = { filters: [filter.contains('mks', 'banana', MAPKEYS)] } verifyQueryResults(args, 'string mapkeys match', done) }) + it('should match maps containing a string key in a nested context', function (done) { + const args = { filters: [filter.contains('mks', 'banana', MAPKEYS, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested string mapkeys match', done) + }) + it('throws a type error if the comparison value is of invalid type', function () { const fn = () => filter.contains('list', { foo: 'bar' }, LIST) expect(fn).to.throw(TypeError) @@ -532,12 +651,24 @@ describe('Queries', function () { verifyQueryResults(args, 'point list match', done) }) + it('should match locations in a list within a GeoJSON region in a nested context', function (done) { + const region = new GeoJSON({ type: 'Polygon', coordinates: [[[103, 1.3], [104, 1.3], [104, 1.4], [103, 1.4], [103, 1.3]]] }) + const args = { filters: [filter.geoWithinGeoJSONRegion('lg', region, LIST, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested point list match', done) + }) + it('should match locations in a map within a GeoJSON region', function (done) { const region = new GeoJSON({ type: 'Polygon', coordinates: [[[103, 1.3], [104, 1.3], [104, 1.4], [103, 1.4], [103, 1.3]]] }) const args = { filters: [filter.geoWithinGeoJSONRegion('mg', region, MAPVALUES)] } verifyQueryResults(args, 'point map match', done) }) + it('should match locations in a map within a GeoJSON region in a nested context', function (done) { + const region = new GeoJSON({ type: 'Polygon', coordinates: [[[103, 1.3], [104, 1.3], [104, 1.4], [103, 1.4], [103, 1.3]]] }) + const args = { filters: [filter.geoWithinGeoJSONRegion('mg', region, MAPVALUES, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested point map match', done) + }) + it('accepts a plain object as GeoJSON', function (done) { const region = { type: 'Polygon', coordinates: [[[103, 1.3], [104, 1.3], [104, 1.4], [103, 1.4], [103, 1.3]]] } const args = { filters: [filter.geoWithinGeoJSONRegion('g', region)] } @@ -556,10 +687,20 @@ describe('Queries', function () { verifyQueryResults(args, 'point list match', done) }) + it('should match locations in a list within a radius from another location in a nested context', function (done) { + const args = { filters: [filter.geoWithinRadius('lg', 103.9135, 1.3085, 15000, LIST, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested point list match', done) + }) + it('should match locations in a map within a radius from another location', function (done) { const args = { filters: [filter.geoWithinRadius('mg', 103.9135, 1.3085, 15000, MAPVALUES)] } verifyQueryResults(args, 'point map match', done) }) + + it('should match locations in a map within a radius from another location in a nested context', function (done) { + const args = { filters: [filter.geoWithinRadius('mg', 103.9135, 1.3085, 15000, MAPVALUES, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested point map match', done) + }) }) describe('filter.geoContainsGeoJSONPoint()', function () { @@ -575,12 +716,24 @@ describe('Queries', function () { verifyQueryResults(args, 'region list match', done) }) + it('should match regions in a list that contain a GeoJSON point in a nested context', function (done) { + const point = new GeoJSON({ type: 'Point', coordinates: [103.913, 1.308] }) + const args = { filters: [filter.geoContainsGeoJSONPoint('lg', point, LIST, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested region list match', done) + }) + it('should match regions in a map that contain a GeoJSON point', function (done) { const point = new GeoJSON({ type: 'Point', coordinates: [103.913, 1.308] }) const args = { filters: [filter.geoContainsGeoJSONPoint('mg', point, MAPVALUES)] } verifyQueryResults(args, 'region map match', done) }) + it('should match regions in a map that contain a GeoJSON point in a nested context', function (done) { + const point = new GeoJSON({ type: 'Point', coordinates: [103.913, 1.308] }) + const args = { filters: [filter.geoContainsGeoJSONPoint('mg', point, MAPVALUES, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested region map match', done) + }) + it('accepts a plain object as GeoJSON', function (done) { const point = { type: 'Point', coordinates: [103.913, 1.308] } const args = { filters: [filter.geoContainsGeoJSONPoint('g', point)] } @@ -599,10 +752,20 @@ describe('Queries', function () { verifyQueryResults(args, 'region list match', done) }) + it('should match regions in a list that contain a lng/lat coordinate pair in a nested context', function (done) { + const args = { filters: [filter.geoContainsPoint('lg', 103.913, 1.308, LIST, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested region list match', done) + }) + it('should match regions in a map that contain a lng/lat coordinate pair', function (done) { const args = { filters: [filter.geoContainsPoint('mg', 103.913, 1.308, MAPVALUES)] } verifyQueryResults(args, 'region map match', done) }) + + it('should match regions in a map that contain a lng/lat coordinate pair in a nested context', function (done) { + const args = { filters: [filter.geoContainsPoint('mg', 103.913, 1.308, MAPVALUES, new Context().addMapKey('nested'))] } + verifyQueryResults(args, 'nested region map match', done) + }) }) }) }) @@ -651,6 +814,30 @@ describe('Queries', function () { }) }) + it('should apply a user defined function and aggregate the results from a map', function (done) { + const args = { + filters: [filter.contains('nested', 'value', MAPKEYS)] + } + const query = client.query(helper.namespace, testSet, args) + query.apply('udf', 'count', function (error, result) { + if (error) throw error + expect(result).to.equal(3) + done() + }) + }) + + it('should apply a user defined function and aggregate the results from a nested map', function (done) { + const args = { + filters: [filter.contains('nested', 'value', MAPKEYS, new Context().addMapKey('doubleNested'))] + } + const query = client.query(helper.namespace, testSet, args) + query.apply('udf', 'count', function (error, result) { + if (error) throw error + expect(result).to.equal(3) + done() + }) + }) + it('should apply a user defined function with arguments and aggregate the results', function (done) { const args = { filters: [filter.equal('name', 'aggregate')] @@ -698,6 +885,16 @@ describe('Queries', function () { expect(job).to.be.instanceof(Job) }) }) + it('returns a Promise that resolves to a Job with a filter containing a CDT context', function () { + const args = { + filters: [filter.contains('nested', 'value', MAPKEYS, new Context().addMapKey('doubleNested'))] + } + const query = client.query(helper.namespace, testSet, args) + return query.background('udf', 'noop') + .then(job => { + expect(job).to.be.instanceof(Job) + }) + }) }) describe('query.operate()', function () { From c2d0156d725ba7f2b4f7c7a1a7647e8922bfc7bb Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 02:23:03 -0600 Subject: [PATCH 03/23] Added CDT context serialization and deserialization (base64). CLIENT-1990 Added CDT context serialization and deserialization. Added maximum and minimum values for Index and Rank CDT context. --- lib/cdt_context.js | 29 +++++++++++++ lib/client.js | 90 ++++++++++++++++++++++++++++++++++++++++ src/include/client.h | 2 + src/include/operations.h | 1 + src/main/cdt_ctx.cc | 76 +++++++++++++++++++++++++++++++++ src/main/client.cc | 2 + test/cdt_context.js | 32 +++++++++++++- test/client.js | 69 ++++++++++++++++++++++++++++++ 8 files changed, 300 insertions(+), 1 deletion(-) diff --git a/lib/cdt_context.js b/lib/cdt_context.js index 6a9a6ef8..eb504dde 100644 --- a/lib/cdt_context.js +++ b/lib/cdt_context.js @@ -33,6 +33,10 @@ const MAP_RANK = 0x21 const MAP_KEY = 0x22 /** @private **/ const MAP_VALUE = 0x23 +/** @private **/ +const int32Max = 2147483647 +/** @private **/ +const int32Min = -2147483648 /** * @summary Nested CDT context type. @@ -63,6 +67,11 @@ class CdtContext { * @return {CdtContext} Updated CDT context, so calls can be chained. */ addListIndex (index) { + if (int32Max < index) { + throw new Error('index overflow, largest supported integer is ' + int32Max) + } else if (int32Min > index) { + throw new Error('index underflow, smallest supported integer is ' + int32Min) + } return this.add(LIST_INDEX, index) } @@ -82,6 +91,11 @@ class CdtContext { * @return {CdtContext} Updated CDT context, so calls can be chained. */ addListIndexCreate (index, order, pad) { + if (int32Max < index) { + throw new Error('index overflow, largest supported integer is' + int32Max) + } else if (int32Min > index) { + throw new Error('index underflow, smallest supported integer is' + int32Min) + } if (order) { return this.add(LIST_INDEX | 0xc0, index) } else { @@ -106,6 +120,11 @@ class CdtContext { * @return {CdtContext} Updated CDT context, so calls can be chained. */ addListRank (rank) { + if (int32Max < rank) { + throw new Error('rank overflow, largest supported integer is' + int32Max) + } else if (int32Min > rank) { + throw new Error('rank underflow, smallest supported integer is' + int32Min) + } return this.add(LIST_RANK, rank) } @@ -135,6 +154,11 @@ class CdtContext { * @return {CdtContext} Updated CDT context, so calls can be chained. */ addMapIndex (index) { + if (int32Max < index) { + throw new Error('index overflow, largest supported integer is' + int32Max) + } else if (int32Min > index) { + throw new Error('index underflow, smallest supported integer is' + int32Min) + } return this.add(MAP_INDEX, index) } @@ -151,6 +175,11 @@ class CdtContext { * @return {CdtContext} Updated CDT context, so calls can be chained. */ addMapRank (rank) { + if (int32Max < rank) { + throw new Error('rank overflow, largest supported integer is' + int32Max) + } else if (int32Min > rank) { + throw new Error('rank underflow, smallest supported integer is' + int32Min) + } return this.add(MAP_RANK, rank) } diff --git a/lib/client.js b/lib/client.js index 8917cc47..d70ca955 100644 --- a/lib/client.js +++ b/lib/client.js @@ -22,6 +22,7 @@ const EventEmitter = require('events') const as = require('bindings')('aerospike.node') const AerospikeError = require('./error') +const Context = require('./cdt_context') const Commands = require('./commands') const Config = require('./config') const EventLoop = require('./event_loop') @@ -210,6 +211,95 @@ Client.prototype.getNodes = function () { return this.as_client.getNodes() } +/** + * @function Client#contextToBase64 + * + * @summary Returns a serialized CDT Context + * + * @param {Object} context - {@link CdtContext} + * + * @return {String} serialized context - base64 representation of the CDT Context + * + * @since v5.6.0 + * + * @example How to use CDT context serialization + * + * const Aerospike = require('aerospike'); + * const Context = Aerospike.cdt.Context + * // Define host configuration + * let config = { + * hosts: '192.168.33.10:3000', + * policies: { + * operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0}), + * write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}), + * read : new Aerospike.ReadPolicy({socketTimeout : 0, totalTimeout : 0}) + * } + * } + * + * + * Aerospike.connect(config, async (error, client) => { + * // Create a context + * let context = new Context().addMapKey('nested') + * + * // Create keys for records to be written + * let recordKey = new Aerospike.Key('test', 'demo', 'record') + * let contextKey = new Aerospike.Key('test', 'demo', 'context') + * + * // Put record with a CDT + * await client.put(recordKey, {exampleBin: {nested: {food: 'blueberry', drink: 'koolaid'}}}) + * + * // Test the context with client.operate() + * var ops = [ + * Aerospike.maps.getByKey('exampleBin', 'food', Aerospike.maps.returnType.KEY_VALUE).withContext(context) + * ] + * let results = await client.operate(recordKey, ops) + * console.log(results.bins.exampleBin) // [ 'food', 'blueberry' ] + * + * // Serialize CDT Context + * let serializedContext = client.contextToBase64(context) + * + * // Put record with bin containing the serialized record + * await client.put(contextKey, {context: serializedContext}) + * + * // Get context when needed for operation + * let contextRecord = await client.get(contextKey) + * + * // Deserialize CDT Context + * context = client.contextFromBase64(contextRecord.bins.context) + * + * // Test the context with client.operate() + * ops = [ + * Aerospike.maps.getByKey('exampleBin', 'food', Aerospike.maps.returnType.KEY_VALUE).withContext(context) + * ] + * results = await client.operate(recordKey, ops) + * console.log(results.bins.exampleBin) // [ 'food', 'blueberry' ] + * + * // Close the client + * client.close() + * }) + */ +Client.prototype.contextToBase64 = function (context) { + return this.as_client.contextToBase64({ context }) +} + +/** + * @function Client#contextFromBase64 + * + * @summary Returns a deserialized CDT Context + * + * @param {String} serializedContext - base64 serialized {@link CdtContext} + * + * @return {CdtContext} Deserialized CDT Context + * + * @since v5.6.0 + * + */ +Client.prototype.contextFromBase64 = function (serializedContext) { + const context = new Context() + context.items = this.as_client.contextFromBase64({ context: serializedContext }) + return context +} + /** * @function Client#addSeedHost * diff --git a/src/include/client.h b/src/include/client.h index de89af4a..6fdb82e9 100644 --- a/src/include/client.h +++ b/src/include/client.h @@ -83,6 +83,8 @@ class AerospikeClient : public Nan::ObjectWrap { static NAN_METHOD(BatchApply); static NAN_METHOD(BatchRemove); static NAN_METHOD(BatchSelect); + static NAN_METHOD(ContextFromBase64); + static NAN_METHOD(ContextToBase64); static NAN_METHOD(Close); static NAN_METHOD(Connect); static NAN_METHOD(ExistsAsync); diff --git a/src/include/operations.h b/src/include/operations.h index 1d41eafa..4bccec84 100644 --- a/src/include/operations.h +++ b/src/include/operations.h @@ -44,6 +44,7 @@ int get_optional_cdt_context(as_cdt_ctx *context, bool *has_context, as_cdt_ctx* get_optional_cdt_context_heap(int * rc, v8::Local obj, const char *prop, const LogInfo *log); +int get_v8_cdt_context(as_cdt_ctx *context, v8::Local items); v8::Local scalar_opcode_values(); v8::Local list_opcode_values(); diff --git a/src/main/cdt_ctx.cc b/src/main/cdt_ctx.cc index 23811f61..bbe43dd6 100644 --- a/src/main/cdt_ctx.cc +++ b/src/main/cdt_ctx.cc @@ -26,6 +26,82 @@ extern "C" { using namespace v8; +NAN_METHOD(AerospikeClient::ContextToBase64) +{ + TYPE_CHECK_REQ(info[0], IsObject, "Context must be an object"); + + as_cdt_ctx context; + bool has_context = false; + + if (info[0]->IsObject()) { + get_optional_cdt_context(&context, &has_context, info[0].As(), "context", NULL); + } + + if(has_context){ + uint32_t capacity = as_cdt_ctx_base64_capacity(&context); + char serializedContext[capacity]; + as_cdt_ctx_to_base64(&context, serializedContext, capacity);; + as_cdt_ctx_destroy(&context); + info.GetReturnValue().Set(Nan::New(serializedContext).ToLocalChecked()); + } + else{ + Nan::ThrowError("Context is invalid, cannot serialize"); + } + +} + +NAN_METHOD(AerospikeClient::ContextFromBase64) +{ + TYPE_CHECK_REQ(info[0], IsObject, "Serialized context must be an object"); + + char* serializedContext = NULL; + if (info[0]->IsObject()) { + if(get_string_property(&serializedContext, info[0].As(), "context", NULL) != AS_NODE_PARAM_OK){ + Nan::ThrowError("Serialized context is invalid"); + return; + } + } + + as_cdt_ctx context; + as_cdt_ctx_from_base64(&context, serializedContext); + Local v8_items = Nan::New(context.list.size); + get_v8_cdt_context(&context, v8_items); + cf_free(serializedContext); + as_cdt_ctx_destroy(&context); + info.GetReturnValue().Set(v8_items); + +} + +int get_v8_cdt_context(as_cdt_ctx *context, Local items) +{ + Nan::HandleScope scope; + for(uint32_t i = 0; i < context->list.size; i++){ + + as_cdt_ctx_item* item = (as_cdt_ctx_item*) as_vector_get(&context->list, i); + Local v8Item = Nan::New(2); + + if((item->type & 0xF) > 0x1){ + Nan::Set(v8Item, 0, Nan::New(item->type)); + Nan::Set(v8Item, 1, val_to_jsvalue(item->val.pval, NULL)); + + Nan::Set(items, i, v8Item); + } + else{ + Nan::Set(v8Item, 0, Nan::New(item->type)); + //First 31 bits mask + int32_t ival = item->val.ival & 0x7FFFFFFF; + //Signed bit mask + if(item->val.ival & 0x8000000000000000){ + ival = ival | 0x80000000; + } + Nan::Set(v8Item, 1, Nan::New(ival)); + + Nan::Set(items, i, v8Item); + } + } + return AS_NODE_PARAM_OK; +} + int get_optional_cdt_context(as_cdt_ctx *context, bool *has_context, Local obj, const char *prop, const LogInfo *log) diff --git a/src/main/client.cc b/src/main/client.cc index b382e805..3dee670b 100644 --- a/src/main/client.cc +++ b/src/main/client.cc @@ -289,6 +289,8 @@ void AerospikeClient::Init() Nan::SetPrototypeMethod(tpl, "batchApply", BatchApply); Nan::SetPrototypeMethod(tpl, "batchRemove", BatchRemove); Nan::SetPrototypeMethod(tpl, "batchSelect", BatchSelect); + Nan::SetPrototypeMethod(tpl, "contextFromBase64", ContextFromBase64); + Nan::SetPrototypeMethod(tpl, "contextToBase64", ContextToBase64); Nan::SetPrototypeMethod(tpl, "close", Close); Nan::SetPrototypeMethod(tpl, "connect", Connect); Nan::SetPrototypeMethod(tpl, "existsAsync", ExistsAsync); diff --git a/test/cdt_context.js b/test/cdt_context.js index 3bed967a..278e56dc 100644 --- a/test/cdt_context.js +++ b/test/cdt_context.js @@ -16,7 +16,7 @@ 'use strict' -/* eslint-env mocha */ +/* global expect, describe, it */ const Aerospike = require('../lib/aerospike') const helper = require('./test_helper') @@ -49,6 +49,12 @@ describe('Aerospike.cdt.Context', function () { .then(assertResultEql({ nested: 5 })) .then(cleanup) }) + it('Throws an error when index is too large', function () { + expect(() => new Context().addListIndex(2147483648)).to.throw(Error) + }) + it('Throws an error when index is too small', function () { + expect(() => new Context().addListIndex(-2147483649)).to.throw(Error) + }) }) describe('Context.addListIndexCreate', function () { @@ -127,6 +133,12 @@ describe('Aerospike.cdt.Context', function () { .then(assertError(status.ERR_OP_NOT_APPLICABLE)) .then(cleanup) }) + it('Throws an error when index is too large', function () { + expect(() => new Context().addListIndexCreate(2147483648)).to.throw(Error) + }) + it('Throws an error when index is too small', function () { + expect(() => new Context().addListIndexCreate(-2147483649)).to.throw(Error) + }) }) describe('Context.addListRank', function () { @@ -139,6 +151,12 @@ describe('Aerospike.cdt.Context', function () { .then(assertResultEql({ nested: 3 })) .then(cleanup) }) + it('Throws an error when rank is too large', function () { + expect(() => new Context().addListRank(2147483648)).to.throw(Error) + }) + it('Throws an error when rank is too small', function () { + expect(() => new Context().addListRank(-2147483649)).to.throw(Error) + }) }) describe('Context.addListValue', function () { @@ -163,6 +181,12 @@ describe('Aerospike.cdt.Context', function () { .then(assertResultEql({ nested: 3 })) .then(cleanup) }) + it('Throws an error when index is too large', function () { + expect(() => new Context().addMapIndex(2147483648)).to.throw(Error) + }) + it('Throws an error when index is too small', function () { + expect(() => new Context().addMapIndex(-2147483649)).to.throw(Error) + }) }) describe('Context.addMapRank', function () { @@ -175,6 +199,12 @@ describe('Aerospike.cdt.Context', function () { .then(assertResultEql({ nested: 3 })) .then(cleanup) }) + it('Throws an error when rank is too large', function () { + expect(() => new Context().addMapRank(2147483648)).to.throw(Error) + }) + it('Throws an error when rank is too small', function () { + expect(() => new Context().addMapRank(-2147483649)).to.throw(Error) + }) }) describe('Context.addMapKey', function () { diff --git a/test/client.js b/test/client.js index 3ecb9577..5cf7d11e 100644 --- a/test/client.js +++ b/test/client.js @@ -20,6 +20,7 @@ const Aerospike = require('../lib/aerospike') const Client = Aerospike.Client +const Context = Aerospike.cdt.Context const helper = require('./test_helper') const keygen = helper.keygen @@ -152,6 +153,74 @@ describe('Client', function () { }) }) + describe('Client#contextToBase64', function () { + const client = helper.client + const context = new Context().addMapKey('nested') + it('Serializes a CDT context', function () { + expect(typeof client.contextToBase64(context)).to.equal('string') + }) + it('Throws an error if no context is given', function () { + expect(() => { client.contextToBase64() }).to.throw(Error) + }) + it('Throws an error if a non-object is given', function () { + expect(() => { client.contextToBase64('test') }).to.throw(Error) + }) + }) + + describe('Client#contextFromBase64', function () { + const client = helper.client + const addListIndex = new Context().addListIndex(5) + const addListIndexCreate = new Context().addListIndexCreate(45, Aerospike.lists.order.KEY_ORDERED, true) + const addListRank = new Context().addListRank(15) + const addListValueString = new Context().addListValue('apple') + const addListValueInt = new Context().addListValue(4500) + const addMapIndex = new Context().addMapIndex(10) + const addMapRank = new Context().addMapRank(11) + const addMapKey = new Context().addMapKey('nested') + const addMapKeyCreate = new Context().addMapKeyCreate('nested', Aerospike.maps.order.ORDERED) + const addMapValueString = new Context().addMapValue('nested') + const addMapValueInt = new Context().addMapValue(1000) + it('Deserializes a cdt context with addListIndex', function () { + expect(client.contextFromBase64(client.contextToBase64(addListIndex))).to.eql(addListIndex) + }) + it('Deserializes a cdt context with addListIndexCreate', function () { + expect(client.contextFromBase64(client.contextToBase64(addListIndexCreate))).to.eql(addListIndexCreate) + }) + it('Deserializes a cdt context with addListRank', function () { + expect(client.contextFromBase64(client.contextToBase64(addListRank))).to.eql(addListRank) + }) + it('Deserializes a cdt context with addListValueString', function () { + expect(client.contextFromBase64(client.contextToBase64(addListValueString))).to.eql(addListValueString) + }) + it('Deserializes a cdt context with addListValueInt', function () { + expect(client.contextFromBase64(client.contextToBase64(addListValueInt))).to.eql(addListValueInt) + }) + it('Deserializes a cdt context with addMapIndex', function () { + expect(client.contextFromBase64(client.contextToBase64(addMapIndex))).to.eql(addMapIndex) + }) + it('Deserializes a cdt context with addMapRank', function () { + expect(client.contextFromBase64(client.contextToBase64(addMapRank))).to.eql(addMapRank) + }) + it('Deserializes a cdt context with addMapKey', function () { + expect(client.contextFromBase64(client.contextToBase64(addMapKey))).to.eql(addMapKey) + }) + it('Deserializes a cdt context with addMapKeyCreate', function () { + expect(client.contextFromBase64(client.contextToBase64(addMapKeyCreate))).to.eql(addMapKeyCreate) + }) + it('Deserializes a cdt context with addMapValueString', function () { + expect(client.contextFromBase64(client.contextToBase64(addMapValueString))).to.eql(addMapValueString) + }) + it('Deserializes a cdt context with addMapValueInt', function () { + expect(client.contextFromBase64(client.contextToBase64(addMapValueInt))).to.eql(addMapValueInt) + }) + it('Throws an error if no value is given', function () { + expect(() => { client.contextFromBase64() }).to.throw(Error) + }) + it('Throws an error if an non-string value is given', function () { + expect(() => { client.contextFromBase64(45) }).to.throw(Error) + }) + }) + context.skip('cluster name', function () { it('should fail to connect to the cluster if the cluster name does not match', function (done) { const config = Object.assign({}, helper.config) From c575ffee3b2a40e7db293d180bd0f35f28718afb Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 02:51:06 -0600 Subject: [PATCH 04/23] Added queryPolicy property 'replica'. CLIENT-2347 Added queryPolicy property 'replica'. Added scanPolicy property 'replica'. Added support for rack aware queries and scans. --- lib/policies/query_policy.js | 8 ++++++++ lib/policies/scan_policy.js | 8 ++++++++ src/main/policy.cc | 10 ++++++++++ 3 files changed, 26 insertions(+) diff --git a/lib/policies/query_policy.js b/lib/policies/query_policy.js index 1e6f0d86..bc9da5a8 100644 --- a/lib/policies/query_policy.js +++ b/lib/policies/query_policy.js @@ -34,6 +34,14 @@ class QueryPolicy extends BasePolicy { props = props || {} super(props) + /** + * Specifies the replica to be consulted for the query operation. + * + * @type number + * @see {@link module:aerospike/policy.replica} for supported policy values. + */ + this.replica = props.replica + /** * Should CDT data types (Lists / Maps) be deserialized to JS data types * (Arrays / Objects) or returned as raw bytes (Buffer). diff --git a/lib/policies/scan_policy.js b/lib/policies/scan_policy.js index ee8f03bf..7488f3c4 100644 --- a/lib/policies/scan_policy.js +++ b/lib/policies/scan_policy.js @@ -34,6 +34,14 @@ class ScanPolicy extends BasePolicy { props = props || {} super(props) + /** + * Specifies the replica to be consulted for the scan operation. + * + * @type number + * @see {@link module:aerospike/policy.replica} for supported policy values. + */ + this.replica = props.replica + /** * Specifies whether a {@link * http://www.aerospike.com/docs/guide/durable_deletes.html|tombstone} diff --git a/src/main/policy.cc b/src/main/policy.cc index 4bb80082..93477256 100644 --- a/src/main/policy.cc +++ b/src/main/policy.cc @@ -546,6 +546,11 @@ int querypolicy_from_jsobject(as_policy_query *policy, Local obj, AS_NODE_PARAM_OK) { return rc; } + if ((rc = get_optional_uint32_property((uint32_t *)&policy->replica, NULL, + obj, "replica", log)) != + AS_NODE_PARAM_OK) { + return rc; + } if ((rc = get_optional_uint32_property((uint32_t *)&policy->info_timeout, NULL, obj, "infoTimeout", log)) != AS_NODE_PARAM_OK) { @@ -600,6 +605,11 @@ int scanpolicy_from_jsobject(as_policy_scan *policy, Local obj, AS_NODE_PARAM_OK) { return rc; } + if ((rc = get_optional_uint32_property((uint32_t *)&policy->replica, NULL, + obj, "replica", log)) != + AS_NODE_PARAM_OK) { + return rc; + } as_v8_detail(log, "Parsing scan policy: success"); return AS_NODE_PARAM_OK; } From e9dcb14c6e2faacbc42255792ff28f953995c0c4 Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 05:39:12 -0600 Subject: [PATCH 05/23] Improved Client.indexRemove test by making sure the index is deleted. CLIENT-2345 Improved Client.indexRemove test by making sure the index is deleted. --- test/index.js | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/test/index.js b/test/index.js index e3daebc8..61031c69 100644 --- a/test/index.js +++ b/test/index.js @@ -194,15 +194,34 @@ context('secondary indexes', function () { }) }) - describe('Client#indexRemove()', function () { - beforeEach(() => helper.index.create(testIndex.name, helper.set, testIndex.bin, - Aerospike.indexDataType.STRING, Aerospike.indexType.DEFAULT)) - - it('should drop an index', function (done) { - client.indexRemove(helper.namespace, testIndex.name, function (err) { - expect(err).to.be.null() - done() - }) + describe('Client#indexRemove()', async function () { + beforeEach(() => { + helper.index.create(testIndex.name, helper.set, testIndex.bin, + Aerospike.indexDataType.STRING, Aerospike.indexType.DEFAULT) + }) + + it('should drop an index', async function () { + // Wait for index creation to complete + await new Promise(resolve => setTimeout(resolve, 5000)) + + // Do query on the secondary index to ensure proper creation. + let query = client.query(helper.namespace, helper.set) + query.where(Aerospike.filter.equal(testIndex.bin, 'value')) + let results = await query.results() + + await client.indexRemove(helper.namespace, testIndex.name) + + // Do query on the secondary index to ensure proper deletion + query = client.query(helper.namespace, helper.set) + query.where(Aerospike.filter.equal(testIndex.bin, 'value')) + try { + results = await query.results() + // Fail test if this code is reached + expect('fail').to.equal('now') + } catch (error) { + expect(error.code).to.equal(201) + expect('pass').to.equal('pass') + } }) it('should return a Promise if called without callback function', function () { From fe0808022774778f6a9f88a6c557d71f4aba49b9 Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 05:55:00 -0600 Subject: [PATCH 06/23] Linting and npm update. ran npm update. linted code. --- lib/client.js | 30 +++--- package-lock.json | 254 +++++++++++++++++++++++----------------------- test/index.js | 4 +- 3 files changed, 146 insertions(+), 142 deletions(-) diff --git a/lib/client.js b/lib/client.js index e0e8ebcc..fbed15a9 100644 --- a/lib/client.js +++ b/lib/client.js @@ -215,7 +215,7 @@ Client.prototype.getNodes = function () { * @function Client#contextToBase64 * * @summary Returns a serialized CDT Context - * + * * @param {Object} context - {@link CdtContext} * * @return {String} serialized context - base64 representation of the CDT Context @@ -223,7 +223,7 @@ Client.prototype.getNodes = function () { * @since v5.6.0 * * @example How to use CDT context serialization - * + * * const Aerospike = require('aerospike'); * const Context = Aerospike.cdt.Context * // Define host configuration @@ -235,45 +235,45 @@ Client.prototype.getNodes = function () { * read : new Aerospike.ReadPolicy({socketTimeout : 0, totalTimeout : 0}) * } * } - * - * + * + * * Aerospike.connect(config, async (error, client) => { * // Create a context * let context = new Context().addMapKey('nested') - * + * * // Create keys for records to be written * let recordKey = new Aerospike.Key('test', 'demo', 'record') * let contextKey = new Aerospike.Key('test', 'demo', 'context') - * + * * // Put record with a CDT * await client.put(recordKey, {exampleBin: {nested: {food: 'blueberry', drink: 'koolaid'}}}) - * + * * // Test the context with client.operate() * var ops = [ * Aerospike.maps.getByKey('exampleBin', 'food', Aerospike.maps.returnType.KEY_VALUE).withContext(context) * ] * let results = await client.operate(recordKey, ops) * console.log(results.bins.exampleBin) // [ 'food', 'blueberry' ] - * + * * // Serialize CDT Context * let serializedContext = client.contextToBase64(context) - * + * * // Put record with bin containing the serialized record * await client.put(contextKey, {context: serializedContext}) - * + * * // Get context when needed for operation * let contextRecord = await client.get(contextKey) - * + * * // Deserialize CDT Context - * context = client.contextFromBase64(contextRecord.bins.context) - * + * context = client.contextFromBase64(contextRecord.bins.context) + * * // Test the context with client.operate() * ops = [ * Aerospike.maps.getByKey('exampleBin', 'food', Aerospike.maps.returnType.KEY_VALUE).withContext(context) * ] * results = await client.operate(recordKey, ops) * console.log(results.bins.exampleBin) // [ 'food', 'blueberry' ] - * + * * // Close the client * client.close() * }) @@ -288,7 +288,7 @@ Client.prototype.contextToBase64 = function (context) { * @summary Returns a deserialized CDT Context * * @param {String} serializedContext - base64 serialized {@link CdtContext} - * + * * @return {CdtContext} Deserialized CDT Context * * @since v5.6.0 diff --git a/package-lock.json b/package-lock.json index 7a47961b..a0c1db5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,42 +60,42 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", + "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.9.tgz", - "integrity": "sha512-FUGed8kfhyWvbYug/Un/VPJD41rDIgoVVcR+FuzhzOYyRz5uED+Gd3SLZml0Uw2l2aHFb7ZgdW5mGA3G2cCCnQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz", + "integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.8.tgz", - "integrity": "sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz", + "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-compilation-targets": "^7.21.5", - "@babel/helper-module-transforms": "^7.21.5", - "@babel/helpers": "^7.21.5", - "@babel/parser": "^7.21.8", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helpers": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -120,12 +120,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.9.tgz", - "integrity": "sha512-F3fZga2uv09wFdEjEQIJxXALXfz0+JaOb7SabvVMmjHxeVTuGW8wgE8Vp1Hd7O+zMTYtcfEISGRzPkeiaPPsvg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz", + "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==", "dev": true, "dependencies": { - "@babel/types": "^7.21.5", + "@babel/types": "^7.22.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -135,13 +135,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz", - "integrity": "sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz", + "integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.21.5", - "@babel/helper-validator-option": "^7.21.0", + "@babel/compat-data": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -178,142 +178,142 @@ "dev": true }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz", - "integrity": "sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", "dev": true, "dependencies": { - "@babel/types": "^7.21.4" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz", - "integrity": "sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz", + "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.21.5", - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-simple-access": "^7.21.5", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "@babel/types": "^7.21.5" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz", + "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", - "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.5.tgz", - "integrity": "sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz", + "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", + "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-validator-identifier": "^7.22.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -322,9 +322,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.9.tgz", - "integrity": "sha512-q5PNg/Bi1OpGgx5jYlvWZwAorZepEudDMCLtj967aeS7WMont7dUZI46M2XwcIQqvUlMxWfdLFu4S/qSxeUu5g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", + "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -334,33 +334,33 @@ } }, "node_modules/@babel/template": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", - "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/parser": "^7.21.9", - "@babel/types": "^7.21.5" + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.5.tgz", - "integrity": "sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-environment-visitor": "^7.21.5", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.5", - "@babel/types": "^7.21.5", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz", + "integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -369,13 +369,13 @@ } }, "node_modules/@babel/types": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz", - "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", + "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.21.5", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -943,9 +943,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.21.9", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", + "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", "dev": true, "funding": [ { @@ -955,13 +955,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001503", + "electron-to-chromium": "^1.4.431", + "node-releases": "^2.0.12", + "update-browserslist-db": "^1.0.11" }, "bin": { "browserslist": "cli.js" @@ -1045,9 +1049,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001489", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz", - "integrity": "sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==", + "version": "1.0.30001504", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001504.tgz", + "integrity": "sha512-5uo7eoOp2mKbWyfMXnGO9rJWOGU8duvzEiYITW+wivukL7yHH4gX9yuRaobu6El4jPxo6jKZfG+N6fB621GD/Q==", "dev": true, "funding": [ { @@ -1377,9 +1381,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.405", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.405.tgz", - "integrity": "sha512-JdDgnwU69FMZURoesf9gNOej2Cms1XJFfLk24y1IBtnAdhTcJY/mXnokmpmxHN59PcykBP4bgUU98vLY44Lhuw==", + "version": "1.4.433", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.433.tgz", + "integrity": "sha512-MGO1k0w1RgrfdbLVwmXcDhHHuxCn2qRgR7dYsJvWFKDttvYPx6FNzCGG0c/fBBvzK2LDh3UV7Tt9awnHnvAAUQ==", "dev": true }, "node_modules/emoji-regex": { @@ -5191,9 +5195,9 @@ "dev": true }, "node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", + "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", "dependencies": { "lru-cache": "^6.0.0" }, diff --git a/test/index.js b/test/index.js index 61031c69..7a2fd129 100644 --- a/test/index.js +++ b/test/index.js @@ -207,7 +207,7 @@ context('secondary indexes', function () { // Do query on the secondary index to ensure proper creation. let query = client.query(helper.namespace, helper.set) query.where(Aerospike.filter.equal(testIndex.bin, 'value')) - let results = await query.results() + await query.results() await client.indexRemove(helper.namespace, testIndex.name) @@ -215,7 +215,7 @@ context('secondary indexes', function () { query = client.query(helper.namespace, helper.set) query.where(Aerospike.filter.equal(testIndex.bin, 'value')) try { - results = await query.results() + await query.results() // Fail test if this code is reached expect('fail').to.equal('now') } catch (error) { From b7881a95b23c3b1c3b6939ded30a2ff4b1db21db Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 06:13:21 -0600 Subject: [PATCH 07/23] Fixed timeout issue with indexRemove() test Fixed timeout issue with indexRemove() test --- test/index.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/index.js b/test/index.js index 7a2fd129..a2b10a24 100644 --- a/test/index.js +++ b/test/index.js @@ -201,9 +201,6 @@ context('secondary indexes', function () { }) it('should drop an index', async function () { - // Wait for index creation to complete - await new Promise(resolve => setTimeout(resolve, 5000)) - // Do query on the secondary index to ensure proper creation. let query = client.query(helper.namespace, helper.set) query.where(Aerospike.filter.equal(testIndex.bin, 'value')) From 7c93427a5b427dfd96ff670f9c08acb713e0aa08 Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 06:24:08 -0600 Subject: [PATCH 08/23] Update index.js Added increased timeout to avoid errors: 201 AEROSPIKE_ERR_INDEX_NOT_FOUND 203 AEROSPIKE_ERR_INDEX_NOT_READABLE --- test/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/index.js b/test/index.js index a2b10a24..9fbf5b74 100644 --- a/test/index.js +++ b/test/index.js @@ -201,6 +201,10 @@ context('secondary indexes', function () { }) it('should drop an index', async function () { + // Wait for index creation to complete + this.timeout(10000) + await new Promise(resolve => setTimeout(resolve, 5000)) + // Do query on the secondary index to ensure proper creation. let query = client.query(helper.namespace, helper.set) query.where(Aerospike.filter.equal(testIndex.bin, 'value')) From cfcbaa4fa168854bd1b2e9d9989a671c2827bdb3 Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 06:49:24 -0600 Subject: [PATCH 09/23] Troubleshooting windows build issue --- src/main/cdt_ctx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cdt_ctx.cc b/src/main/cdt_ctx.cc index bbe43dd6..bef2d7f5 100644 --- a/src/main/cdt_ctx.cc +++ b/src/main/cdt_ctx.cc @@ -39,7 +39,7 @@ NAN_METHOD(AerospikeClient::ContextToBase64) if(has_context){ uint32_t capacity = as_cdt_ctx_base64_capacity(&context); - char serializedContext[capacity]; + char* serializedContext = new char[capacity]; as_cdt_ctx_to_base64(&context, serializedContext, capacity);; as_cdt_ctx_destroy(&context); info.GetReturnValue().Set(Nan::New(serializedContext).ToLocalChecked()); From 478ae68a27d04607bc1e1ae474b26298d6eda0cb Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 07:51:37 -0600 Subject: [PATCH 10/23] Added delete to match new in cdt_ctx.cc --- src/main/cdt_ctx.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/cdt_ctx.cc b/src/main/cdt_ctx.cc index bef2d7f5..bc3f210e 100644 --- a/src/main/cdt_ctx.cc +++ b/src/main/cdt_ctx.cc @@ -42,6 +42,7 @@ NAN_METHOD(AerospikeClient::ContextToBase64) char* serializedContext = new char[capacity]; as_cdt_ctx_to_base64(&context, serializedContext, capacity);; as_cdt_ctx_destroy(&context); + delete serializedContext; info.GetReturnValue().Set(Nan::New(serializedContext).ToLocalChecked()); } else{ From 6e82cae063d96d2eea1fdc3352746e83859a8d5d Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 07:58:24 -0600 Subject: [PATCH 11/23] Moved delete until after the variable was assigned. Moved delete until after the variable was assigned. --- src/main/cdt_ctx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cdt_ctx.cc b/src/main/cdt_ctx.cc index bc3f210e..00feaf6e 100644 --- a/src/main/cdt_ctx.cc +++ b/src/main/cdt_ctx.cc @@ -42,8 +42,8 @@ NAN_METHOD(AerospikeClient::ContextToBase64) char* serializedContext = new char[capacity]; as_cdt_ctx_to_base64(&context, serializedContext, capacity);; as_cdt_ctx_destroy(&context); - delete serializedContext; info.GetReturnValue().Set(Nan::New(serializedContext).ToLocalChecked()); + delete serializedContext; } else{ Nan::ThrowError("Context is invalid, cannot serialize"); From 87984174febaeef21af5d0b2001f9923bf2e8e15 Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Mon, 19 Jun 2023 09:16:07 -0600 Subject: [PATCH 12/23] Fixed warning when compiling on macOS Fixed warning when compiling on macOS --- src/main/cdt_ctx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cdt_ctx.cc b/src/main/cdt_ctx.cc index 00feaf6e..3d4657af 100644 --- a/src/main/cdt_ctx.cc +++ b/src/main/cdt_ctx.cc @@ -43,7 +43,7 @@ NAN_METHOD(AerospikeClient::ContextToBase64) as_cdt_ctx_to_base64(&context, serializedContext, capacity);; as_cdt_ctx_destroy(&context); info.GetReturnValue().Set(Nan::New(serializedContext).ToLocalChecked()); - delete serializedContext; + delete [] serializedContext; } else{ Nan::ThrowError("Context is invalid, cannot serialize"); From 215f53aff9001a86de8ed369cdc113a0d3cd7364 Mon Sep 17 00:00:00 2001 From: Zohar Elkayam <5897181+realmgic@users.noreply.github.com> Date: Tue, 20 Jun 2023 19:35:59 +0300 Subject: [PATCH 13/23] Update linux-build.yml with new checkout and setup-node --- .github/workflows/linux-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 92026c2d..6dfc7812 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -29,12 +29,12 @@ jobs: - 20.x continue-on-error: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: recursive - run: ./scripts/build-c-client.sh - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} cache: 'npm' From 9a4ec8fb4c12de136e534e7c8c24b74176ff242c Mon Sep 17 00:00:00 2001 From: Zohar Elkayam <5897181+realmgic@users.noreply.github.com> Date: Tue, 20 Jun 2023 19:36:37 +0300 Subject: [PATCH 14/23] Update macOS-build.yml with new checkout --- .github/workflows/macOS-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macOS-build.yml b/.github/workflows/macOS-build.yml index e4365da8..2df7672d 100644 --- a/.github/workflows/macOS-build.yml +++ b/.github/workflows/macOS-build.yml @@ -27,7 +27,7 @@ jobs: needs: setup runs-on: macos-latest # https://github.com/actions/virtual-environments steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: recursive - run: ./scripts/build-package.sh 1 From 2adfa14dadd38070a327397129275fcb1e9b1ccc Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Wed, 21 Jun 2023 08:25:29 -0600 Subject: [PATCH 15/23] Removed -lssl flag within binding.gyp Removed -lssl flag within binding.gyp. Removed Libuv logic in install scripts. Removed some install scripts. modified package.json. updated README.md. --- README.md | 60 +++++++++++++++-------- binding.gyp | 6 +-- package.json | 1 - scripts/build-c-client.sh | 7 --- scripts/build-commands.sh | 99 -------------------------------------- scripts/build-package.sh | 6 --- scripts/postinstall.js | 12 ----- scripts/prebuiltBinding.js | 73 ---------------------------- 8 files changed, 42 insertions(+), 222 deletions(-) delete mode 100644 scripts/postinstall.js delete mode 100755 scripts/prebuiltBinding.js diff --git a/README.md b/README.md index 66c9b64a..83af16d5 100644 --- a/README.md +++ b/README.md @@ -197,43 +197,63 @@ Before starting with the Aerospike Nodejs Client, verify that you have the follo - Xcode 5 or greater. -**Openssl Library** +**OpenSSL Library** +OpenSSL is needed to build the Aerospike C Client. If downloading from NPM at version 5.6.0 or later, you will not need to +have OpenSSL installed to use the Aerospike Nodejs Client. If you are using version 5.5.0 and below, you will need to do +some additional linking to use the client, which is specified below. -The below example shows how to install the Openssl library. +We recommend using brew to install OpenSSL: ```bash brew install openssl -unlink /usr/local/opt/openssl -# Change the below linking based on openssl version and installation path -ln -s /usr/local/Cellar/openssl@x/y.z/ /usr/local/opt/openssl ``` -If you are looking upgrade switch from openssl@1 or an older version of openssl@3, add these variables to your .bashrc, .profile, or .zshrc file. +For a Mac using ARM architecture, OpenSSL should be linked as shown below: + ```bash -export PATH="/usr/local/bin/:/usr/local/opt/openssl/bin:$PATH" -export LDFLAGS="-L/usr/local/opt/openssl/lib" -export CPPFLAGS="-I/usr/local/opt/openssl/include" -export EXT_CFLAGS="-I/usr/local/opt/openssl/include" +# When building from source before version 5.6 with openssl@3 +sudo ln -s /opt/homebrew/opt/openssl@3/ /usr/local/opt/openssl; +# link here if before version 5.6.0 +sudo ln -s /opt/homebrew/opt/openssl@3/ /usr/local/opt/openssl@3; + +# When building from source with openssl@1.1 +sudo ln -s /opt/homebrew/opt/openssl@1.1/ /usr/local/opt/openssl; +# link here if before version 5.6.0 with openssl@1.1 +sudo ln -s /opt/homebrew/opt/openssl@1.1/ /usr/local/opt/openssl@1.1; ``` -Afterwards, source the file that was changed and confirm the desired openssl version is installed +For a Mac using X86 architecture, OpenSSL should be linked as shown below: + ```bash -source ~/.bashrc -source ~/.profile -source ~/.zshrc -openssl version +# When building from source before version 5.6 with openssl@3 +sudo ln -s /opt/homebrew/opt/openssl@3/ /usr/local/opt/openssl; +# link here if before version 5.6.0 +sudo ln -s /opt/homebrew/opt/openssl@3/ /usr/local/opt/openssl@3; + +# When building from source before version 5.6 with openssl@3 +sudo ln -s /opt/homebrew/opt/openssl@3/ /usr/local/opt/openssl; +# link here if before version 5.6.0 with openssl@1.1 +sudo ln -s /opt/homebrew/opt/openssl@1.1/ /usr/local/opt/openssl@1.1; ``` -For 4x client support, install openssl@1.1 version. + +For 4x client support, install OpenSSL@1.1 version. **LIBUV Library** -The example below shows how to install the LIBUV library. +Libuv is needed to build the Aerospike C Client. If downloading from NPM at version 5.6.0 or later, you will not need to +have Libuv installed to use the Aerospike Nodejs Client. If you are using version 5.5.0 and below, you will need to do +some additional linking to use the client, which is specified below. + +We recommend using brew to install Libuv: ```bash brew install libuv -unlink /usr/local/opt/libuv -# Change the below linking based on libuv version and installation path -ln -s /usr/local/Cellar/libuv/1.44.1_1/ /usr/local/opt/libuv +``` + +For Macs using ARM architecture, Libuv should be linked as shown below: + +```bash +sudo ln -s /opt/homebrew/opt/libuv/ /usr/local/opt/libuv; ``` ### Git Repository Installations diff --git a/binding.gyp b/binding.gyp index e94a6884..f1a6456d 100644 --- a/binding.gyp +++ b/binding.gyp @@ -151,8 +151,7 @@ ['OS=="linux"',{ 'libraries': [ '../aerospike-client-c/target/Linux-<(build_arch)/lib/libaerospike.a', - '-lz', - '-lssl' + '-lz' ], 'defines': [ 'AS_USE_LIBUV' @@ -168,8 +167,7 @@ ['OS=="mac"',{ 'libraries': [ '../aerospike-client-c/target/Darwin-<(build_arch)/lib/libaerospike.a', - '-lz', - '-lssl' + '-lz' ], 'defines': [ 'AS_USE_LIBUV' diff --git a/package.json b/package.json index 7efe612c..12f2feec 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "scripts": { "preinstall": "npm install @mapbox/node-pre-gyp", "install": "node-pre-gyp install --fallback-to-build", - "postinstall": "node scripts/postinstall.js", "test": "mocha", "test-noserver": "GLOBAL_CLIENT=false mocha -g '#noserver'", "lint": "standard", diff --git a/scripts/build-c-client.sh b/scripts/build-c-client.sh index e85a04f5..dff5cdc8 100755 --- a/scripts/build-c-client.sh +++ b/scripts/build-c-client.sh @@ -25,16 +25,9 @@ CWD=$(pwd) SCRIPT_DIR=$(dirname $0) BASE_DIR=$(cd "${SCRIPT_DIR}/.."; pwd) -SETUP=$1 . ${SCRIPT_DIR}/build-commands.sh -if [ -n "$1" ]; then setup -fi -download_libuv -rebuild_libuv -check_libuv - rebuild_c_client perform_check diff --git a/scripts/build-commands.sh b/scripts/build-commands.sh index 5ca06a8b..273ac4b2 100755 --- a/scripts/build-commands.sh +++ b/scripts/build-commands.sh @@ -28,32 +28,17 @@ BASE_DIR=$(cd "${SCRIPT_DIR}/.."; pwd) AEROSPIKE_C_HOME=${CWD}/aerospike-client-c OS_FLAVOR=linux AEROSPIKE_NODEJS_RELEASE_HOME=${CWD}/lib/binding -LIBUV_VERSION=1.8.0 -LIBUV_DIR=libuv-v${LIBUV_VERSION} -LIBUV_TAR=${LIBUV_DIR}.tar.gz -LIBUV_URL=http://dist.libuv.org/dist/v1.8.0/${LIBUV_TAR} -LIBUV_ABS_DIR=${CWD}/${LIBUV_DIR} -LIBUV_BUILD=0 build_arch=$(uname -m) if [[ "$OSTYPE" == "darwin"* ]]; then # Mac OSX AEROSPIKE_LIB_HOME=${AEROSPIKE_C_HOME}/target/Darwin-${build_arch} AEROSPIKE_LIBRARY=${AEROSPIKE_LIB_HOME}/lib/libaerospike.a AEROSPIKE_INCLUDE=${AEROSPIKE_LIB_HOME}/include - - LIBUV_DIR=/usr/local/opt/libuv - LIBUV_ABS_DIR=${LIBUV_DIR} - LIBUV_LIBRARY_DIR=${LIBUV_DIR}/lib - LIBUV_INCLUDE_DIR=${LIBUV_DIR}/include - LIBUV_LIBRARY=${LIBUV_LIBRARY_DIR}/libuv.a OS_FLAVOR=darwin elif [[ "$OSTYPE" == "linux"* ]]; then AEROSPIKE_LIB_HOME=${AEROSPIKE_C_HOME}/target/Linux-${build_arch} AEROSPIKE_LIBRARY=${AEROSPIKE_LIB_HOME}/lib/libaerospike.a AEROSPIKE_INCLUDE=${AEROSPIKE_LIB_HOME}/include - LIBUV_LIBRARY_DIR=${LIBUV_DIR}/.libs - LIBUV_INCLUDE_DIR=${CWD}/${LIBUV_DIR}/include - LIBUV_LIBRARY=${CWD}/${LIBUV_LIBRARY_DIR}/libuv.a OS_FLAVOR=linux else # Unknown. @@ -82,66 +67,6 @@ configure_nvm() { fi } -download_libuv() { - if [[ "$OSTYPE" != "darwin"* ]]; then - if [ ! -f ${LIBUV_TAR} ]; then - echo Download ${LIBUV_URL} - wget ${LIBUV_URL} - fi - - if [ ! -d ${LIBUV_DIR} ]; then - echo Extract ${LIBUV_TAR} - tar xf ${LIBUV_TAR} - fi - fi -} - -rebuild_libuv() { - echo "rebuild_libuv" - if [ $LIBUV_BUILD -eq 1 ]; then - if [ ! -f ${LIBUV_LIBRARY} ]; then - echo "Make ${LIBUV_ABS_DIR}" - cd ${LIBUV_ABS_DIR} - sh autogen.sh - ./configure -q - make clean - make V=1 LIBUV_VERSIONBOSE=1 CFLAGS="-w -fPIC" 2>&1 | tee ${CWD}/${0}-libuv-output.log - # make V=1 LIBUV_VERSIONBOSE=1 CFLAGS="-w -fPIC -DDEBUG" 2>&1 | tee ${CWD}/${0}-libuv-output.log - # make V=1 LIBUV_VERSIONBOSE=1 install - cd .. - fi - fi -} - -check_libuv() { - - cd ${CWD} - - printf "\n" >&1 - - if [ $LIBUV_BUILD -eq 1 ]; then - if [ -f ${LIBUV_LIBRARY} ]; then - printf " [✓] %s\n" "${LIBUV_LIBRARY}" >&1 - else - printf " [✗] %s\n" "${LIBUV_LIBRARY}" >&1 - FAILED=1 - fi - fi - - if [ -f ${LIBUV_INCLUDE_DIR}/uv.h ]; then - printf " [✓] %s\n" "${LIBUV_INCLUDE_DIR}/uv.h" >&1 - else - printf " [✗] %s\n" "${LIBUV_INCLUDE_DIR}/uv.h" >&1 - FAILED=1 - fi - - printf "\n" >&1 - - if [ $FAILED ]; then - exit 1 - fi -} - rebuild_c_client() { # if [ ! -f ${AEROSPIKE_LIBRARY} ]; then cd ${AEROSPIKE_C_HOME} @@ -151,29 +76,6 @@ rebuild_c_client() { # fi } -setup() { - if [[ "$OSTYPE" == "darwin"* ]]; then - # # install xcode CLI - # xcode-select —-install - # Check for Homebrew to be present, install if it's missing - if test ! $(which brew); then - echo "Installing homebrew..." - ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" - fi - brew update - PACKAGES=( - openssl - ) - echo "Installing packages..." - brew install ${PACKAGES[@]} - # link openssl - unlink /usr/local/opt/openssl - ln -s /usr/local/Cellar/openssl@3/*/ /usr/local/opt/openssl - export LDFLAGS="-L/usr/local/opt/openssl@3/lib" - export CPPFLAGS="-I/usr/local/opt/openssl@3/include" - fi -} - check_aerospike() { cd ${CWD} @@ -208,6 +110,5 @@ perform_check() { printf "\n" >&1 printf "CHECK\n" >&1 - check_libuv check_aerospike } diff --git a/scripts/build-package.sh b/scripts/build-package.sh index b4e02ee6..41446b16 100755 --- a/scripts/build-package.sh +++ b/scripts/build-package.sh @@ -44,12 +44,6 @@ build_nodejs_client() { configure_nvm -if [ -n "$1" ]; then setup -fi -download_libuv -rebuild_libuv -check_libuv - rebuild_c_client perform_check diff --git a/scripts/postinstall.js b/scripts/postinstall.js deleted file mode 100644 index 1489e3d5..00000000 --- a/scripts/postinstall.js +++ /dev/null @@ -1,12 +0,0 @@ -const fs = require('fs') - -function createDir (folder) { - if (!fs.existsSync(folder)) { - fs.mkdirSync(folder, { recursive: true }) - - console.log('Folder Created Successfully: ' + folder) - } -} - -createDir('./lib/binding/openssl@1') -createDir('./lib/binding/openssl@3') diff --git a/scripts/prebuiltBinding.js b/scripts/prebuiltBinding.js deleted file mode 100755 index 3a1e179f..00000000 --- a/scripts/prebuiltBinding.js +++ /dev/null @@ -1,73 +0,0 @@ -const { exec } = require('child_process') -const fs = require('fs') -exec('openssl version', (error, stdout, stderr) => { - if (error) throw error - exec('uname -s', (error, OS, stderr) => { - if (error) throw error - exec('uname -m', (error, arch, stderr) => { - if (error) throw error - const openssl = stdout.split(' ') - OS = OS.trim() - arch = arch.trim() - const dict = { - v19: 'v111', - v18: 'v108', - v16: 'v93', - v14: 'v83', - Linux: 'linux', - Darwin: 'darwin', - arm64: 'arm64', - x86_64: 'x64', - aarch64: 'arm64' - } - if ((openssl[1][0] === '3') && (openssl[0] !== 'LibreSSL')) { - console.log('lib/binding/openssl@3/node-v111-' + dict[OS] + '-' + dict[arch]) - fs.rename('lib/binding/openssl@3/node-v111-' + dict[OS] + '-' + dict[arch], - 'lib/binding/node-v111-' + dict[OS] + '-' + dict[arch], (err) => { - if (err) throw err - fs.rename('lib/binding/openssl@3/node-v108-' + dict[OS] + '-' + dict[arch], - 'lib/binding/node-v108-' + dict[OS] + '-' + dict[arch], (err) => { - if (err) throw err - fs.rename('lib/binding/openssl@3/node-v93-' + dict[OS] + '-' + dict[arch], - 'lib/binding/node-v93-' + dict[OS] + '-' + dict[arch], (err) => { - if (err) throw err - fs.rename('lib/binding/openssl@3/node-v115-' + dict[OS] + '-' + dict[arch], - 'lib/binding/node-v115-' + dict[OS] + '-' + dict[arch], (err) => { - if (err) return - fs.rm('lib/binding/openssl@3', { recursive: true, force: true }, (e) => { - if (e) throw e - }) - fs.rm('lib/binding/openssl@1', { recursive: true, force: true }, (e) => { - if (e) throw e - }) - }) - }) - }) - }) - } else { - fs.rename('lib/binding/openssl@1/node-v111-' + dict[OS] + '-' + dict[arch], - 'lib/binding/node-v111-' + dict[OS] + '-' + dict[arch], (err) => { - if (err) throw err - fs.rename('lib/binding/openssl@1/node-v108-' + dict[OS] + '-' + dict[arch], - 'lib/binding/node-v108-' + dict[OS] + '-' + dict[arch], (err) => { - if (err) throw err - fs.rename('lib/binding/openssl@1/node-v93-' + dict[OS] + '-' + dict[arch], - 'lib/binding/node-v93-' + dict[OS] + '-' + dict[arch], (err) => { - if (err) throw err - fs.rename('lib/binding/openssl@1/node-v115-' + dict[OS] + '-' + dict[arch], - 'lib/binding/node-v115-' + dict[OS] + '-' + dict[arch], (err) => { - if (err) return - fs.rm('lib/binding/openssl@3', { recursive: true, force: true }, (e) => { - if (e) throw e - }) - fs.rm('lib/binding/openssl@1', { recursive: true, force: true }, (e) => { - if (e) throw e - }) - }) - }) - }) - }) - } - }) - }) -}) From 508bcc32aec826bd77232a4ec437d8618592538e Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Wed, 21 Jun 2023 08:39:47 -0600 Subject: [PATCH 16/23] Added Libuv download back into build scripts Added Libuv download back into build scripts --- scripts/build-c-client.sh | 2 ++ scripts/build-commands.sh | 19 +++++++++++++++++++ scripts/build-package.sh | 2 ++ 3 files changed, 23 insertions(+) diff --git a/scripts/build-c-client.sh b/scripts/build-c-client.sh index dff5cdc8..1e7ec792 100755 --- a/scripts/build-c-client.sh +++ b/scripts/build-c-client.sh @@ -28,6 +28,8 @@ BASE_DIR=$(cd "${SCRIPT_DIR}/.."; pwd) . ${SCRIPT_DIR}/build-commands.sh +download_libuv + rebuild_c_client perform_check diff --git a/scripts/build-commands.sh b/scripts/build-commands.sh index 273ac4b2..1f45b297 100755 --- a/scripts/build-commands.sh +++ b/scripts/build-commands.sh @@ -28,12 +28,17 @@ BASE_DIR=$(cd "${SCRIPT_DIR}/.."; pwd) AEROSPIKE_C_HOME=${CWD}/aerospike-client-c OS_FLAVOR=linux AEROSPIKE_NODEJS_RELEASE_HOME=${CWD}/lib/binding +LIBUV_VERSION=1.45.0 +LIBUV_DIR=libuv-v${LIBUV_VERSION} +LIBUV_TAR=${LIBUV_DIR}.tar.gz +LIBUV_URL=http://dist.libuv.org/dist/v1.45.0/${LIBUV_TAR} build_arch=$(uname -m) if [[ "$OSTYPE" == "darwin"* ]]; then # Mac OSX AEROSPIKE_LIB_HOME=${AEROSPIKE_C_HOME}/target/Darwin-${build_arch} AEROSPIKE_LIBRARY=${AEROSPIKE_LIB_HOME}/lib/libaerospike.a AEROSPIKE_INCLUDE=${AEROSPIKE_LIB_HOME}/include + LIBUV_DIR=/usr/local/opt/libuv OS_FLAVOR=darwin elif [[ "$OSTYPE" == "linux"* ]]; then AEROSPIKE_LIB_HOME=${AEROSPIKE_C_HOME}/target/Linux-${build_arch} @@ -67,6 +72,20 @@ configure_nvm() { fi } +download_libuv() { + if [[ "$OSTYPE" != "darwin"* ]]; then + if [ ! -f ${LIBUV_TAR} ]; then + echo Download ${LIBUV_URL} + wget ${LIBUV_URL} + fi + + if [ ! -d ${LIBUV_DIR} ]; then + echo Extract ${LIBUV_TAR} + tar xf ${LIBUV_TAR} + fi + fi +} + rebuild_c_client() { # if [ ! -f ${AEROSPIKE_LIBRARY} ]; then cd ${AEROSPIKE_C_HOME} diff --git a/scripts/build-package.sh b/scripts/build-package.sh index 41446b16..a2814f64 100755 --- a/scripts/build-package.sh +++ b/scripts/build-package.sh @@ -44,6 +44,8 @@ build_nodejs_client() { configure_nvm +download_libuv + rebuild_c_client perform_check From dabafe92535f091b33b94ef2db3ef79bd3ee1af9 Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Wed, 21 Jun 2023 08:47:49 -0600 Subject: [PATCH 17/23] Added Rebuild_libuv back to build scripts --- scripts/build-c-client.sh | 1 + scripts/build-commands.sh | 27 +++++++++++++++++++++++++++ scripts/build-package.sh | 1 + 3 files changed, 29 insertions(+) diff --git a/scripts/build-c-client.sh b/scripts/build-c-client.sh index 1e7ec792..48dbbd8c 100755 --- a/scripts/build-c-client.sh +++ b/scripts/build-c-client.sh @@ -29,6 +29,7 @@ BASE_DIR=$(cd "${SCRIPT_DIR}/.."; pwd) . ${SCRIPT_DIR}/build-commands.sh download_libuv +rebuild_libuv rebuild_c_client diff --git a/scripts/build-commands.sh b/scripts/build-commands.sh index 1f45b297..adf39dd2 100755 --- a/scripts/build-commands.sh +++ b/scripts/build-commands.sh @@ -32,18 +32,28 @@ LIBUV_VERSION=1.45.0 LIBUV_DIR=libuv-v${LIBUV_VERSION} LIBUV_TAR=${LIBUV_DIR}.tar.gz LIBUV_URL=http://dist.libuv.org/dist/v1.45.0/${LIBUV_TAR} +LIBUV_ABS_DIR=${CWD}/${LIBUV_DIR} +LIBUV_BUILD=0 build_arch=$(uname -m) if [[ "$OSTYPE" == "darwin"* ]]; then # Mac OSX AEROSPIKE_LIB_HOME=${AEROSPIKE_C_HOME}/target/Darwin-${build_arch} AEROSPIKE_LIBRARY=${AEROSPIKE_LIB_HOME}/lib/libaerospike.a AEROSPIKE_INCLUDE=${AEROSPIKE_LIB_HOME}/include + LIBUV_DIR=/usr/local/opt/libuv + LIBUV_ABS_DIR=${LIBUV_DIR} + LIBUV_LIBRARY_DIR=${LIBUV_DIR}/lib + LIBUV_INCLUDE_DIR=${LIBUV_DIR}/include + LIBUV_LIBRARY=${LIBUV_LIBRARY_DIR}/libuv.a OS_FLAVOR=darwin elif [[ "$OSTYPE" == "linux"* ]]; then AEROSPIKE_LIB_HOME=${AEROSPIKE_C_HOME}/target/Linux-${build_arch} AEROSPIKE_LIBRARY=${AEROSPIKE_LIB_HOME}/lib/libaerospike.a AEROSPIKE_INCLUDE=${AEROSPIKE_LIB_HOME}/include + LIBUV_LIBRARY_DIR=${LIBUV_DIR}/.libs + LIBUV_INCLUDE_DIR=${CWD}/${LIBUV_DIR}/include + LIBUV_LIBRARY=${CWD}/${LIBUV_LIBRARY_DIR}/libuv.a OS_FLAVOR=linux else # Unknown. @@ -86,6 +96,23 @@ download_libuv() { fi } +rebuild_libuv() { + echo "rebuild_libuv" + if [ $LIBUV_BUILD -eq 1 ]; then + if [ ! -f ${LIBUV_LIBRARY} ]; then + echo "Make ${LIBUV_ABS_DIR}" + cd ${LIBUV_ABS_DIR} + sh autogen.sh + ./configure -q + make clean + make V=1 LIBUV_VERSIONBOSE=1 CFLAGS="-w -fPIC" 2>&1 | tee ${CWD}/${0}-libuv-output.log + # make V=1 LIBUV_VERSIONBOSE=1 CFLAGS="-w -fPIC -DDEBUG" 2>&1 | tee ${CWD}/${0}-libuv-output.log + # make V=1 LIBUV_VERSIONBOSE=1 install + cd .. + fi + fi +} + rebuild_c_client() { # if [ ! -f ${AEROSPIKE_LIBRARY} ]; then cd ${AEROSPIKE_C_HOME} diff --git a/scripts/build-package.sh b/scripts/build-package.sh index a2814f64..1795ea88 100755 --- a/scripts/build-package.sh +++ b/scripts/build-package.sh @@ -45,6 +45,7 @@ build_nodejs_client() { configure_nvm download_libuv +rebuild_libuv rebuild_c_client From e285a4db246e9c4cb2831205071253adcae63280 Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Wed, 21 Jun 2023 09:10:36 -0600 Subject: [PATCH 18/23] Excluded libuv folder from linting Excluded libuv folder from linting --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 12f2feec..a5e43557 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,8 @@ "ignore": [ "apidocs", "tmp-*.js", - "/*.js" + "/*.js", + "libuv-v*" ] }, "files": [ From bc71216ab992253796641a8affce3596b542ef69 Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Wed, 21 Jun 2023 09:31:25 -0600 Subject: [PATCH 19/23] Fixed compiler warnings --- src/main/async.cc | 4 ++-- src/main/commands/query_pages.cc | 2 +- src/main/commands/scan_pages.cc | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/async.cc b/src/main/async.cc index 41419e33..1c449256 100644 --- a/src/main/async.cc +++ b/src/main/async.cc @@ -195,7 +195,7 @@ bool async_scan_pages_listener(as_error *err, as_record *record, void *udata, query_bytes_to_jsobject(bytes, bytes_size, log), Nan::Null()}; - cmd->Callback(4, {argv}); + cmd->Callback(4, argv); as_scan_destroy(scan); free(bytes); delete cmd; @@ -253,7 +253,7 @@ bool async_query_pages_listener(as_error *err, as_record *record, void *udata, query_bytes_to_jsobject(bytes, bytes_size, log), Nan::Null()}; - cmd->Callback(4, {argv}); + cmd->Callback(4, argv); free_query(query, NULL); free(bytes); delete cmd; diff --git a/src/main/commands/query_pages.cc b/src/main/commands/query_pages.cc index f1e7b58f..3d4335b2 100644 --- a/src/main/commands/query_pages.cc +++ b/src/main/commands/query_pages.cc @@ -77,7 +77,7 @@ NAN_METHOD(AerospikeClient::QueryPages) uint8_t* bytes = new uint8_t[bytes_size]; load_bytes(info[4].As(), bytes, bytes_size, log); setup_query_pages(&qu->query, info[0], info[1], Nan::Null(), bytes, bytes_size, &context, &with_context, log); - delete bytes; + delete [] bytes; } else{ setup_query_pages(&qu->query, info[0], info[1], info[2], NULL, 0, &context, &with_context, log); diff --git a/src/main/commands/scan_pages.cc b/src/main/commands/scan_pages.cc index faf85161..503aa423 100644 --- a/src/main/commands/scan_pages.cc +++ b/src/main/commands/scan_pages.cc @@ -68,7 +68,7 @@ NAN_METHOD(AerospikeClient::ScanPages) uint8_t* bytes = new uint8_t[bytes_size]; load_bytes(info[5].As(), bytes, bytes_size, log); setup_scan_pages(&su->scan, info[0], info[1], Nan::Null(), bytes, bytes_size, log); - delete bytes; + delete [] bytes; } else{ setup_scan_pages(&su->scan, info[0], info[1], info[2], NULL, 0, log); From 1e13010ae53185296f68cd54e6639d956cc7c381 Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Wed, 21 Jun 2023 12:47:23 -0600 Subject: [PATCH 20/23] Replaced documentation in client.js Replaced documentation in client.js. Corrected README.md. Corrected CHANGELOG.md. --- CHANGELOG.md | 20 ++++++++++++- README.md | 5 ++-- lib/client.js | 80 ++++++++++++++++++++------------------------------- 3 files changed, 53 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index baac19b1..c48f8ba6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,31 @@ # Changelog All notable changes to this project will be documented in this file. +## [5.6.0] + +* **New Features** + * [CLIENT-1803] - Added support for creation of a secondary index on elements within a Collection Data Type. + * [CLIENT-1990] - Added support for Collection Data Type (CDT) Context Base64 serialization. + * [CLIENT-2085] - Added support for rack aware queries and scans. + * [CLIENT-2347] - Added the 'replica' property to the QueryPolicy and ScanPolicy Classes. + * [CLIENT-2348] - Added filter support for secondary indices on elements within a Collection Data Type. + +* **Improvements** + * [CLIENT-1823] - Changed the example and parameters in the API Documentation for Client.batchApply. + * [CLIENT-2345] - Improved Client.indexRemove unit test by verifying deletion with a query. + * [CLIENT-2373] - Modified Query.where() to replace the current filter rather than add a filter to Query.filters. + * [CLIENT-2376] - Removed dynamic linking to OpenSSL. + +* **Updates** + * The typescript description file 'index.d.ts' has not been updated. The next release will update 'index.d.ts' and restore typescript support. + ## [5.5.0] * **Breaking Changes** * [CLIENT-2343] - Dropped support for Node.js 14 * **New Features** - * [CLIENT-2108] - Added pagination support for queries and scans. + * [CLIENT-2108] - Added pagination support for queries and scans. Requires Aerospike Server version 6.0 or above. * [CLIENT-2224] - Added support for rack aware reads when the replication factor is three. * [CLIENT-2303] - Added support for Amazon Linux 2023. * [CLIENT-2342] - Added support for Node.js 20 diff --git a/README.md b/README.md index 83af16d5..542499a5 100644 --- a/README.md +++ b/README.md @@ -231,7 +231,7 @@ sudo ln -s /opt/homebrew/opt/openssl@3/ /usr/local/opt/openssl; sudo ln -s /opt/homebrew/opt/openssl@3/ /usr/local/opt/openssl@3; # When building from source before version 5.6 with openssl@3 -sudo ln -s /opt/homebrew/opt/openssl@3/ /usr/local/opt/openssl; +sudo ln -s /opt/homebrew/opt/openssl@1.1/ /usr/local/opt/openssl; # link here if before version 5.6.0 with openssl@1.1 sudo ln -s /opt/homebrew/opt/openssl@1.1/ /usr/local/opt/openssl@1.1; ``` @@ -250,9 +250,10 @@ We recommend using brew to install Libuv: brew install libuv ``` -For Macs using ARM architecture, Libuv should be linked as shown below: +For a Mac using ARM architecture, Libuv should be linked as shown below: ```bash +# When building from source before version 5.6 sudo ln -s /opt/homebrew/opt/libuv/ /usr/local/opt/libuv; ``` diff --git a/lib/client.js b/lib/client.js index fbed15a9..f4962898 100644 --- a/lib/client.js +++ b/lib/client.js @@ -669,9 +669,7 @@ Client.prototype.batchWrite = function (records, policy, callback) { * This method allows multiple sub-commands for each key in the batch. * This method requires server >= 6.0.0. * - * @param {object[]} records - {@link Record} List of batch sub-commands to perform. - * @param {number} records[].type - {@link Record#type} Batch type. - * @param {Key} records[].key - Record Key. + * @param {Key[]} keys - An array of keys, used to locate the records in the cluster. * @param {object[]} udf - Server UDF module/function and argList to apply. * @param {BatchPolicy} [batchPolicy] - The Batch Policy to use for this operation. * @param {BatchApplyPolicy} [batchApplyPolicy] UDF policy configuration parameters. @@ -685,6 +683,8 @@ Client.prototype.batchWrite = function (records, policy, callback) { * * @example * const Aerospike = require('aerospike') + * const batchType = Aerospike.batchType; + * * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! * const config = { * hosts: '192.168.33.10:3000', @@ -694,52 +694,34 @@ Client.prototype.batchWrite = function (records, policy, callback) { * } * } * - * const batchType = Aerospike.batchType - * var batchRecords = [ - * { type: batchType.BATCH_READ, - * key: new Aerospike.Key('test', 'demo', 'key1'), - * bins: ['i', 's'] }, - * { type: batchType.BATCH_READ, - * key: new Aerospike.Key('test', 'demo', 'key2'), - * readAllBins: true }, - * { type: batchType.BATCH_APPLY, - * key: new Aerospike.Key('test', 'demo', 'key4'), - * policy: new Aerospike.BatchApplyPolicy({ - * filterExpression: exp.eq(exp.binInt('i'), exp.int(37)), - * key: Aerospike.policy.key.SEND, - * commitLevel: Aerospike.policy.commitLevel.ALL, - * durableDelete: true - * }), - * udf: { - * module: 'udf', - * funcname: 'function1', - * args: [[1, 2, 3]] - * } - * }, - * { type: batchType.BATCH_APPLY, - * key: new Aerospike.Key('test', 'demo', 'key5'), - * policy: new Aerospike.BatchApplyPolicy({ - * filterExpression: exp.eq(exp.binInt('i'), exp.int(37)), - * key: Aerospike.policy.key.SEND, - * commitLevel: Aerospike.policy.commitLevel.ALL, - * durableDelete: true - * }), - * udf: { - * module: 'udf', - * funcname: 'function2', - * args: [[1, 2, 3]] - * } - * } - * ] - * Aerospike.connect(config, (error, client) => { - * if (error) throw error - * client.batchApply(batchRecords, (error, results) => { - * if (error) throw error - * results.forEach(function (result) { - * console.log(result) - * }) - * }) - * }) + * // Create batch of keys + * let keys = []; + * for(i = 0; i < 10; i++){ + * keys.push(new Aerospike.Key('sandbox', 'ufodata', i + 1)); + * } + * + * ;(async () => { + * // Establishes a connection to the server + * let client = await Aerospike.connect(config); + * + * // Execute the UDF + * let batchResult = await client.batchApply(batchRecords, + * { + * module: 'example', + * funcname: 'getDaysBetween', + * args: ['occurred', 'posted'] + * } + * ); + * + * // Access the records + * batchResult.forEach(result => { + * // Do something + * console.info("%o days between occurrence and post", result.record.bins.SUCCESS); + * }); + * + * // Close the connection to the server + * client.close(); + * })(); */ Client.prototype.batchApply = function (records, udf, batchPolicy, batchApplyPolicy, callback) { if (typeof batchPolicy === 'function') { From f7457a1dcbfbc719f2c8088934cc6b942f27f3cc Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Wed, 21 Jun 2023 15:34:22 -0600 Subject: [PATCH 21/23] Bumped version number to 5.6.0 Bumped version number to 5.6.0 Fixed README.md Ran NPM update --- README.md | 20 ++++++++++++++------ package-lock.json | 16 ++++++++-------- package.json | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 542499a5..a1effea2 100644 --- a/README.md +++ b/README.md @@ -225,17 +225,25 @@ sudo ln -s /opt/homebrew/opt/openssl@1.1/ /usr/local/opt/openssl@1.1; For a Mac using X86 architecture, OpenSSL should be linked as shown below: ```bash -# When building from source before version 5.6 with openssl@3 -sudo ln -s /opt/homebrew/opt/openssl@3/ /usr/local/opt/openssl; -# link here if before version 5.6.0 -sudo ln -s /opt/homebrew/opt/openssl@3/ /usr/local/opt/openssl@3; - -# When building from source before version 5.6 with openssl@3 +# When building from source before version 5.6 with openssl@1.1 sudo ln -s /opt/homebrew/opt/openssl@1.1/ /usr/local/opt/openssl; # link here if before version 5.6.0 with openssl@1.1 sudo ln -s /opt/homebrew/opt/openssl@1.1/ /usr/local/opt/openssl@1.1; ``` +Before version 5.6.0, you may need to some add some variables to your profile for OpenSSL to be found. + +```bash +export PATH="/usr/local/bin/:/usr/local/opt/openssl/bin:$PATH" +export LDFLAGS="-L/usr/local/opt/openssl/lib" +export CPPFLAGS="-I/usr/local/opt/openssl/include" +export EXT_CFLAGS="-I/usr/local/opt/openssl/include" +# Make sure to source the changes to your shell profile +source ~/.bashrc +source ~/.profile +source ~/.zshrc +``` + For 4x client support, install OpenSSL@1.1 version. **LIBUV Library** diff --git a/package-lock.json b/package-lock.json index a0c1db5e..84789e21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "aerospike", - "version": "5.5.0", + "version": "5.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "aerospike", - "version": "5.5.0", + "version": "5.6.0", "cpu": [ "x64", "arm64" @@ -1049,9 +1049,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001504", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001504.tgz", - "integrity": "sha512-5uo7eoOp2mKbWyfMXnGO9rJWOGU8duvzEiYITW+wivukL7yHH4gX9yuRaobu6El4jPxo6jKZfG+N6fB621GD/Q==", + "version": "1.0.30001506", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001506.tgz", + "integrity": "sha512-6XNEcpygZMCKaufIcgpQNZNf00GEqc7VQON+9Rd0K1bMYo8xhMZRAo5zpbnbMNizi4YNgIDAFrdykWsvY3H4Hw==", "dev": true, "funding": [ { @@ -1381,9 +1381,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.433", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.433.tgz", - "integrity": "sha512-MGO1k0w1RgrfdbLVwmXcDhHHuxCn2qRgR7dYsJvWFKDttvYPx6FNzCGG0c/fBBvzK2LDh3UV7Tt9awnHnvAAUQ==", + "version": "1.4.436", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.436.tgz", + "integrity": "sha512-aktOxo8fnrMC8vOIBMVS3PXbT1nrPQ+SouUuN7Y0a+Rw3pOMrvIV92Ybnax7x4tugA+ZpYA5fOHTby7ama8OQQ==", "dev": true }, "node_modules/emoji-regex": { diff --git a/package.json b/package.json index a5e43557..2f3a2cb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aerospike", - "version": "5.5.0", + "version": "5.6.0", "description": "Aerospike Client Library", "keywords": [ "aerospike", From 40582551d18e9c60791e0c3ea621c96af1a5f655 Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Wed, 21 Jun 2023 18:23:19 -0600 Subject: [PATCH 22/23] Updated C Client Updated C Client Added prebuiltBinding.js into the scripts folder Changed prebuiltBinding.js to use promises rather than callbacks --- aerospike-client-c | 2 +- scripts/prebuiltBinding.js | 79 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 scripts/prebuiltBinding.js diff --git a/aerospike-client-c b/aerospike-client-c index 294084c7..ad90542b 160000 --- a/aerospike-client-c +++ b/aerospike-client-c @@ -1 +1 @@ -Subproject commit 294084c753f98d44317b85611915bb43362ed1ca +Subproject commit ad90542b50c36a31614f31d46207cff0d89ef963 diff --git a/scripts/prebuiltBinding.js b/scripts/prebuiltBinding.js new file mode 100644 index 00000000..eae726dc --- /dev/null +++ b/scripts/prebuiltBinding.js @@ -0,0 +1,79 @@ +const fs = require('fs') +const util = require('util') +const exec = util.promisify(require('child_process').exec); +const rename = util.promisify(fs.rename); +const rm = util.promisify(fs.rm); +const dict = { + Linux: 'linux', + Darwin: 'darwin', + arm64: 'arm64', + x86_64: 'x64', + aarch64: 'arm64' +} + +;(async function () { + + + let output = await exec('uname -s') + const os = output.stdout.trim() + output = await exec('uname -m') + const arch = output.stdout.trim() + output = await exec('openssl version') + const version = output.stdout + const openssl = version.split(' ')[1].slice(0, 1) + let deleteList = [] + if(dict[os] === 'linux'){ + + deleteList.push('lib/binding/node-v115-darwin-arm64') + deleteList.push('lib/binding/node-v111-darwin-arm64') + deleteList.push('lib/binding/node-v108-darwin-arm64') + deleteList.push('lib/binding/node-v93-darwin-arm64') + deleteList.push('lib/binding/node-v115-darwin-x64') + deleteList.push('lib/binding/node-v111-darwin-x64') + deleteList.push('lib/binding/node-v108-darwin-x64') + deleteList.push('lib/binding/node-v93-darwin-x64') + + if(dict[arch] === 'arm64'){ + await rename('lib/binding/openssl@' + openssl + '/node-v115-linux-arm64', 'lib/binding/node-v115-linux-arm64') + await rename('lib/binding/openssl@' + openssl + '/node-v111-linux-arm64', 'lib/binding/node-v111-linux-arm64') + await rename('lib/binding/openssl@' + openssl + '/node-v108-linux-arm64', 'lib/binding/node-v108-linux-arm64') + await rename('lib/binding/openssl@' + openssl + '/node-v93-linux-arm64', 'lib/binding/node-v93-linux-arm64') + } + else{ + await rename('lib/binding/openssl@' + openssl + '/node-v115-linux-x64', 'lib/binding/node-v115-linux-x64') + await rename('lib/binding/openssl@' + openssl + '/node-v111-linux-x64', 'lib/binding/node-v111-linux-x64') + await rename('lib/binding/openssl@' + openssl + '/node-v108-linux-x64', 'lib/binding/node-v108-linux-x64') + await rename('lib/binding/openssl@' + openssl + '/node-v93-linux-x64', 'lib/binding/node-v93-linux-x64') + } + await rm('lib/binding/openssl@3', { recursive: true, force: true }) + await rm('lib/binding/openssl@1', { recursive: true, force: true }) + await rm(deleteList[0], { recursive: true, force: true }) + await rm(deleteList[1], { recursive: true, force: true }) + await rm(deleteList[2], { recursive: true, force: true }) + await rm(deleteList[3], { recursive: true, force: true }) + await rm(deleteList[4], { recursive: true, force: true }) + await rm(deleteList[5], { recursive: true, force: true }) + await rm(deleteList[6], { recursive: true, force: true }) + await rm(deleteList[7], { recursive: true, force: true }) + } + else{ + if(dict[arch] === 'arm64'){ + deleteList.push('lib/binding/node-v115-darwin-x64') + deleteList.push('lib/binding/node-v111-darwin-x64') + deleteList.push('lib/binding/node-v108-darwin-x64') + deleteList.push('lib/binding/node-v93-darwin-x64') + } + else{ + deleteList.push('lib/binding/node-v115-darwin-arm64') + deleteList.push('lib/binding/node-v111-darwin-arm64') + deleteList.push('lib/binding/node-v108-darwin-arm64') + deleteList.push('lib/binding/node-v93-darwin-arm64') + } + await rm('lib/binding/openssl@3', { recursive: true, force: true }) + await rm('lib/binding/openssl@1', { recursive: true, force: true }) + await rm(deleteList[0], { recursive: true, force: true }) + await rm(deleteList[1], { recursive: true, force: true }) + await rm(deleteList[2], { recursive: true, force: true }) + await rm(deleteList[3], { recursive: true, force: true }) + } +})() \ No newline at end of file From 70624673289b84a28cf1b7887c7029c772e8da2e Mon Sep 17 00:00:00 2001 From: Dominic Pelini <111786059+DomPeliniAerospike@users.noreply.github.com> Date: Wed, 21 Jun 2023 18:32:16 -0600 Subject: [PATCH 23/23] Update prebuiltBinding.js linted new script. --- scripts/prebuiltBinding.js | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/scripts/prebuiltBinding.js b/scripts/prebuiltBinding.js index eae726dc..5bd14e3b 100644 --- a/scripts/prebuiltBinding.js +++ b/scripts/prebuiltBinding.js @@ -1,8 +1,8 @@ const fs = require('fs') const util = require('util') -const exec = util.promisify(require('child_process').exec); -const rename = util.promisify(fs.rename); -const rm = util.promisify(fs.rm); +const exec = util.promisify(require('child_process').exec) +const rename = util.promisify(fs.rename) +const rm = util.promisify(fs.rm) const dict = { Linux: 'linux', Darwin: 'darwin', @@ -12,8 +12,6 @@ const dict = { } ;(async function () { - - let output = await exec('uname -s') const os = output.stdout.trim() output = await exec('uname -m') @@ -21,9 +19,8 @@ const dict = { output = await exec('openssl version') const version = output.stdout const openssl = version.split(' ')[1].slice(0, 1) - let deleteList = [] - if(dict[os] === 'linux'){ - + const deleteList = [] + if (dict[os] === 'linux') { deleteList.push('lib/binding/node-v115-darwin-arm64') deleteList.push('lib/binding/node-v111-darwin-arm64') deleteList.push('lib/binding/node-v108-darwin-arm64') @@ -33,13 +30,12 @@ const dict = { deleteList.push('lib/binding/node-v108-darwin-x64') deleteList.push('lib/binding/node-v93-darwin-x64') - if(dict[arch] === 'arm64'){ + if (dict[arch] === 'arm64') { await rename('lib/binding/openssl@' + openssl + '/node-v115-linux-arm64', 'lib/binding/node-v115-linux-arm64') await rename('lib/binding/openssl@' + openssl + '/node-v111-linux-arm64', 'lib/binding/node-v111-linux-arm64') await rename('lib/binding/openssl@' + openssl + '/node-v108-linux-arm64', 'lib/binding/node-v108-linux-arm64') await rename('lib/binding/openssl@' + openssl + '/node-v93-linux-arm64', 'lib/binding/node-v93-linux-arm64') - } - else{ + } else { await rename('lib/binding/openssl@' + openssl + '/node-v115-linux-x64', 'lib/binding/node-v115-linux-x64') await rename('lib/binding/openssl@' + openssl + '/node-v111-linux-x64', 'lib/binding/node-v111-linux-x64') await rename('lib/binding/openssl@' + openssl + '/node-v108-linux-x64', 'lib/binding/node-v108-linux-x64') @@ -55,15 +51,13 @@ const dict = { await rm(deleteList[5], { recursive: true, force: true }) await rm(deleteList[6], { recursive: true, force: true }) await rm(deleteList[7], { recursive: true, force: true }) - } - else{ - if(dict[arch] === 'arm64'){ + } else { + if (dict[arch] === 'arm64') { deleteList.push('lib/binding/node-v115-darwin-x64') deleteList.push('lib/binding/node-v111-darwin-x64') deleteList.push('lib/binding/node-v108-darwin-x64') deleteList.push('lib/binding/node-v93-darwin-x64') - } - else{ + } else { deleteList.push('lib/binding/node-v115-darwin-arm64') deleteList.push('lib/binding/node-v111-darwin-arm64') deleteList.push('lib/binding/node-v108-darwin-arm64') @@ -76,4 +70,4 @@ const dict = { await rm(deleteList[2], { recursive: true, force: true }) await rm(deleteList[3], { recursive: true, force: true }) } -})() \ No newline at end of file +})()