New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

flora-solr

Package Overview
Dependencies
Maintainers
4
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

flora-solr - npm Package Compare versions

Comparing version 0.6.1 to 0.7.0

6

Gruntfile.js
'use strict';
module.exports = function (grunt) {
grunt.initConfig({

@@ -23,3 +22,3 @@ mochaTest: {

'mocha_istanbul': {
mocha_istanbul: {
coverage: {

@@ -35,3 +34,3 @@ src: 'test',

eslint: {
target: ['*.js']
target: ['index.js']
},

@@ -53,3 +52,2 @@

grunt.registerTask('test-cov', ['mocha_istanbul:coverage']);
};
'use strict';
var http = require('http');
var url = require('url');
var querystring = require('querystring');
const http = require('http');
const url = require('url');
const querystring = require('querystring');
var _ = require('lodash');
var errors = require('flora-errors');
var ImplementationError = errors.ImplementationError;
const _ = require('lodash');
const { ImplementationError } = require('flora-errors');
var SUPPORTED_FILTERS = ['equal', 'notEqual', 'lessOrEqual', 'greaterOrEqual', 'range'];
var NO_LIMIT = 1000000;
const SUPPORTED_FILTERS = [
'equal',
'notEqual',
'lessOrEqual',
'greaterOrEqual',
'range'
];
/**
* @constructor
* @param {Api} api
* @param {Object} config
*/
var DataSource = module.exports = function (api, config) {
this.options = config;
};
const NO_LIMIT = 1000000;
/**
* @public
* Return true if two filters on same attribute can be used as single range filter.
*
* @param {Array.<Object>} filters
* @return {boolean}
* @private
*/
DataSource.prototype.prepare = function () {};
function filterRangeQueries(filters) {
if (filters.length !== 2) return false;
/**
* @param {Object} request
* @param {Function} callback
*/
DataSource.prototype.process = function (request, callback) {
var requestUrl,
server = request.server || 'default',
params = { wt: 'json' },
queryParts = [];
const rangeOperators = ['lessOrEqual', 'greaterOrEqual'];
const operator1 = filters[0].operator;
const operator2 = filters[1].operator;
if (!this.options.servers[server]) return callback(new Error('Server "' + server + '" not defined'));
return rangeOperators.indexOf(operator1) !== -1 && rangeOperators.indexOf(operator2) !== -1;
}
requestUrl = this.options.servers[server].url + request.collection + '/select';
if (request.attributes) params.fl = request.attributes.join(',');
if (request.order) params.sort= buildSolrOrderString(request.order);
if (request.search) queryParts.push(escapeValueForSolr(request.search));
if (request.filter) {
try {
queryParts.push(buildSolrFilterString(request.filter));
} catch (e) {
return callback(e);
}
}
if (request.queryAddition) queryParts.push(prepareQueryAddition(request.queryAddition));
if (queryParts.length === 0) queryParts.push('*:*');
if (!request.limit) request.limit = NO_LIMIT; // overwrite SOLR default limit for sub-resource processing
if (request.page) params.start = (request.page - 1) * request.limit;
if (!request.limitPer) params.rows = request.limit;
else {
params = _.assign(params, {
group: 'true',
'group.format': 'simple',
'group.main': 'true',
'group.field': request.limitPer,
'group.limit': request.limit,
rows: NO_LIMIT // disable default limit because groups are returned as list
});
}
params.q = queryParts.join(' AND ');
if (request._explain) {
request._explain.url = requestUrl;
request._explain.params = params;
}
querySolr(requestUrl, params, callback);
};
/**
* @param {Function} callback
* Create range filter from a greatOrEqual and lessOrEqual filter.
*
* @param {Array.<string>} attributeFilters
* @return {Object}
* @private
*/
DataSource.prototype.close = function (callback) {
// TODO: implement
if (callback) callback();
};
function createRangeFilter(attributeFilters) {
const rangeFilter = { attribute: attributeFilters[0].attribute, operator: 'range' };
/**
* @param {string} value
*/
DataSource.prototype.escape = escapeValueForSolr;
// make sure greaterOrEqual filter comes first
attributeFilters.sort(filter1 => (filter1.operator === 'greaterOrEqual' ? -1 : 1));
function buildSolrFilterString(floraFilters) {
var orConditions;
orConditions = floraFilters.map(function (andFilters) {
var conditions;
if (andFilters.length > 1) andFilters = rangify(andFilters);
conditions = andFilters.map(convertFilterToSolrSyntax);
return '(' + conditions.join(' AND ') + ')';
});
if (orConditions.length > 1) return '(' + orConditions.join(' OR ') + ')';
return orConditions.join('');
rangeFilter.value = [attributeFilters[0].value, attributeFilters[1].value];
return rangeFilter;
}

@@ -119,15 +63,12 @@

function rangify(filters) {
var groupedAttrs = _.groupBy(filters, 'attribute'),
rangeQueries = _.filter(groupedAttrs, filterRangeQueries),
rangeQueryAttrs;
const groupedAttrs = _.groupBy(filters, 'attribute');
const rangeQueries = _.filter(groupedAttrs, filterRangeQueries);
if (! rangeQueries.length) return filters;
if (!rangeQueries.length) return filters;
rangeQueryAttrs = rangeQueries.map(function (rangeQuery) {
return rangeQuery[0].attribute;
});
const rangeQueryAttrs = rangeQueries.map(rangeQuery => rangeQuery[0].attribute);
return filters.filter(function (filter) { // copy non-range query attributes
return rangeQueryAttrs.indexOf(filter.attribute) === -1;
})
// copy non-range query attributes
return filters
.filter(filter => rangeQueryAttrs.indexOf(filter.attribute) === -1)
.concat(rangeQueries.map(createRangeFilter));

@@ -137,36 +78,22 @@ }

/**
* Return true if two filters on same attribute can be used as single range filter.
*
* @param {Array.<Object>} filters
* @return {boolean}
* @param {string} value
* @return {string}
* @private
*/
function filterRangeQueries(filters) {
var rangeOperators, operator1, operator2;
if (filters.length !== 2) return false;
rangeOperators = ['lessOrEqual', 'greaterOrEqual'];
operator1 = filters[0].operator;
operator2 = filters[1].operator;
return rangeOperators.indexOf(operator1) !== -1 && rangeOperators.indexOf(operator2) !== -1;
function escapeSpecialChars(value) {
const specialCharRegex = /(\\|\/|\+|-|&|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:)/g;
return value.replace(specialCharRegex, '\\$1');
}
/**
* Create range filter from a greatOrEqual and lessOrEqual filter.
* Escape strings and convert boolean values.
*
* @param {Array.<string>} attributeFilters
* @return {Object}
* @param {*} value
* @return {*}
* @private
*/
function createRangeFilter(attributeFilters) {
var rangeFilter = { attribute: attributeFilters[0].attribute, operator: 'range' };
attributeFilters.sort(function (filter1) { // make sure greaterOrEqual filter comes first
return filter1.operator === 'greaterOrEqual' ? -1 : 1;
});
rangeFilter.value = [attributeFilters[0].value, attributeFilters[1].value];
return rangeFilter;
function escapeValueForSolr(value) {
if (typeof value === 'string') value = escapeSpecialChars(value);
else if (typeof value === 'boolean') value = value === false ? 0 : 1;
return value;
}

@@ -180,7 +107,7 @@

function convertFilterToSolrSyntax(filter) {
var value = filter.value,
operator = filter.operator;
let value = filter.value;
const operator = filter.operator;
if (SUPPORTED_FILTERS.indexOf(filter.operator) === -1) {
throw new ImplementationError('DataSource "flora-solr" does not support "' + filter.operator + '" filters');
throw new ImplementationError(`DataSource "flora-solr" does not support "${filter.operator}" filters`);
}

@@ -199,39 +126,25 @@

return filter.attribute + ':' + value;
} else {
return '-' + filter.attribute + ':' + value;
}
} else { // convert composite keys to SOLR syntax
return value
.map(function (values) {
var conditions = values.map(function (val, index) {
return filter.attribute[index] + ':' + escapeValueForSolr(val);
});
return '(' + conditions.join(' AND ') + ')';
})
.join(' OR ');
return '-' + filter.attribute + ':' + value;
}
}
/**
* Escape strings and convert boolean values.
*
* @param {*} value
* @return {*}
* @private
*/
function escapeValueForSolr(value) {
if (typeof value === 'string') value = escapeSpecialChars(value);
else if (typeof value === 'boolean') value = value === false ? 0 : 1;
return value;
// convert composite keys to SOLR syntax
return value
.map((values) => {
const conditions = values.map((val, index) => filter.attribute[index] + ':' + escapeValueForSolr(val));
return '(' + conditions.join(' AND ') + ')';
})
.join(' OR ');
}
/**
*
* @param {string} value
* @return {string}
* @private
*/
function escapeSpecialChars(value) {
var specialCharRegex = /(\\|\/|\+|-|&|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:)/g;
return value.replace(specialCharRegex, '\\$1');
function buildSolrFilterString(floraFilters) {
const orConditions = floraFilters.map((andFilters) => {
if (andFilters.length > 1) andFilters = rangify(andFilters);
const conditions = andFilters.map(convertFilterToSolrSyntax);
return '(' + conditions.join(' AND ') + ')';
});
if (orConditions.length > 1) return '(' + orConditions.join(' OR ') + ')';
return orConditions.join('');
}

@@ -245,6 +158,5 @@

function buildSolrOrderString(floraOrders) {
var orderCriteria = floraOrders.map(function (order) {
return order.attribute + ' ' + order.direction;
});
return orderCriteria.join(',');
return floraOrders
.map(order => (order.attribute + ' ' + order.direction))
.join(',');
}

@@ -275,3 +187,3 @@

function querySolr(requestUrl, params, callback) {
var options = url.parse(requestUrl);
const options = url.parse(requestUrl);
options.method = 'POST';

@@ -282,14 +194,12 @@ options.headers = {

var req = http.request(options, function processSolrReponse(res) {
var chunks = [];
const req = http.request(options, (res) => {
const chunks = [];
res.on('data', function (chunk) {
chunks.push(chunk);
});
res.on('data', chunk => chunks.push(chunk));
res.on('end', function () {
var data = parseData(Buffer.concat(chunks).toString('utf8'));
res.on('end', () => {
const data = parseData(Buffer.concat(chunks).toString('utf8'));
if (res.statusCode >= 400 || data instanceof Error) {
var error = new Error('Solr error: ' + res.statusCode + ' ' + http.STATUS_CODES[res.statusCode]);
const error = new Error('Solr error: ' + res.statusCode + ' ' + http.STATUS_CODES[res.statusCode]);
if (data instanceof Error) {

@@ -304,3 +214,3 @@ error.message += ': ' + data.message;

callback(null, { totalCount: data.response.numFound, data: data.response.docs });
return callback(null, { totalCount: data.response.numFound, data: data.response.docs });
});

@@ -314,1 +224,87 @@ });

}
class DataSource {
/**
* @param {Api} api
* @param {Object} config
*/
constructor(api, config) {
this.options = config;
}
/**
* @public
*/
prepare() {
}
/**
* @param {Object} request
* @param {Function} callback
*/
process(request, callback) {
const server = request.server || 'default';
const queryParts = [];
let params = { wt: 'json' };
if (!this.options.servers[server]) return callback(new Error(`Server "${server}" not defined`));
const requestUrl = this.options.servers[server].url + request.collection + '/select';
if (request.attributes) params.fl = request.attributes.join(',');
if (request.order) params.sort = buildSolrOrderString(request.order);
if (request.search) queryParts.push(escapeValueForSolr(request.search));
if (request.filter) {
try {
queryParts.push(buildSolrFilterString(request.filter));
} catch (e) {
return callback(e);
}
}
if (request.queryAddition) queryParts.push(prepareQueryAddition(request.queryAddition));
if (queryParts.length === 0) queryParts.push('*:*');
// overwrite SOLR default limit for sub-resource processing
if (!request.limit) request.limit = NO_LIMIT;
if (request.page) params.start = (request.page - 1) * request.limit;
if (!request.limitPer) params.rows = request.limit;
else {
params = _.assign(params, {
group: 'true',
'group.format': 'simple',
'group.main': 'true',
'group.field': request.limitPer,
'group.limit': request.limit,
rows: NO_LIMIT // disable default limit because groups are returned as list
});
}
params.q = queryParts.join(' AND ');
if (request._explain) {
request._explain.url = requestUrl;
request._explain.params = params;
}
return querySolr(requestUrl, params, callback);
}
/**
* @param {Function} callback
*/
close(callback) {
// TODO: implement
if (callback) callback();
}
/**
* @param {string} value
*/
escape(...args) {
return escapeValueForSolr(...args);
}
}
module.exports = DataSource;
{
"name": "flora-solr",
"version": "0.6.1",
"version": "0.7.0",
"description": "Solr connection for Flora",
"main": "index.js",
"scripts": {
"test": "grunt test"
"test": "grunt test",
"lint": "grunt lint"
},

@@ -15,6 +16,3 @@ "author": {

"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/godmodelabs/flora-solr.git"
},
"repository": "godmodelabs/flora-solr",
"contributors": [

@@ -35,6 +33,6 @@ {

"engines": {
"node": ">=0.10.0"
"node": ">=6"
},
"dependencies": {
"flora-errors": "^0.6.0",
"flora-errors": "^0.7.0",
"lodash": "^4.0.0"

@@ -44,3 +42,5 @@ },

"chai": "^3.4.1",
"eslint": "^3.2.2",
"eslint": "^3.11.1",
"eslint-config-airbnb-base": "^11.0.0",
"eslint-plugin-import": "^2.2.0",
"grunt": "^1.0.1",

@@ -51,3 +51,3 @@ "grunt-cli": "^1.2.0",

"grunt-mocha-istanbul": "^5.0.1",
"grunt-mocha-test": "^0.12.7",
"grunt-mocha-test": "^0.13.2",
"istanbul": "^0.4.2",

@@ -57,5 +57,4 @@ "load-grunt-tasks": "^3.4.0",

"mocha-bamboo-reporter": "^1.1.0",
"nock": "8.0.x",
"when": "^3.7.7"
"nock": "9.0.x"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc