diff --git a/NEWS.md b/NEWS.md index af7ae33f..7886d649 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,11 +1,21 @@ # Changelog -## 2.44.1 +## 2.44.2 Released 2016-mm-dd Announcements: - Upgrades camshaft to [0.12.1](https://github.com/CartoDB/camshaft/releases/tag/0.12.1) + - Upgrades turbo-carto to [0.10.1](https://github.com/CartoDB/turbo-carto/releases/tag/0.10.1) + + +## 2.44.1 + +Released 2016-06-01 + +Improvements: + - Extend overviews support to histogram and aggregation dataviews + - Test improvements ## 2.44.0 diff --git a/lib/cartodb/models/dataview/overviews/aggregation.js b/lib/cartodb/models/dataview/overviews/aggregation.js new file mode 100644 index 00000000..41685ff5 --- /dev/null +++ b/lib/cartodb/models/dataview/overviews/aggregation.js @@ -0,0 +1,141 @@ +var BaseOverviewsDataview = require('./base'); +var BaseDataview = require('../aggregation'); + +var dot = require('dot'); +dot.templateSettings.strip = false; + +var summaryQueryTpl = dot.template([ + 'summary AS (', + ' SELECT', + ' sum(_feature_count) AS count,', + ' sum(CASE WHEN {{=it._column}} IS NULL THEN 1 ELSE 0 END) AS nulls_count', + ' FROM ({{=it._query}}) _cdb_aggregation_nulls', + ')' +].join('\n')); + +var rankedCategoriesQueryTpl = dot.template([ + 'categories AS(', + ' SELECT {{=it._column}} AS category, {{=it._aggregation}} AS value,', + ' row_number() OVER (ORDER BY {{=it._aggregation}} desc) as rank', + ' FROM ({{=it._query}}) _cdb_aggregation_all', + ' GROUP BY {{=it._column}}', + ' ORDER BY 2 DESC', + ')' +].join('\n')); + +var categoriesSummaryQueryTpl = dot.template([ + 'categories_summary AS(', + ' SELECT count(1) categories_count, max(value) max_val, min(value) min_val', + ' FROM categories', + ')' +].join('\n')); + +var rankedAggregationQueryTpl = dot.template([ + 'SELECT CAST(category AS text), value, false as agg, nulls_count, min_val, max_val, count, categories_count', + ' FROM categories, summary, categories_summary', + ' WHERE rank < {{=it._limit}}', + 'UNION ALL', + 'SELECT \'Other\' category, sum(value), true as agg, nulls_count, min_val, max_val, count, categories_count', + ' FROM categories, summary, categories_summary', + ' WHERE rank >= {{=it._limit}}', + 'GROUP BY nulls_count, min_val, max_val, count, categories_count' +].join('\n')); + +var aggregationQueryTpl = dot.template([ + 'SELECT CAST({{=it._column}} AS text) AS category, {{=it._aggregation}} AS value, false as agg,', + ' nulls_count, min_val, max_val, count, categories_count', + 'FROM ({{=it._query}}) _cdb_aggregation_all, summary, categories_summary', + 'GROUP BY category, nulls_count, min_val, max_val, count, categories_count', + 'ORDER BY value DESC' +].join('\n')); + +var CATEGORIES_LIMIT = 6; + + function Aggregation(query, options, queryRewriter, queryRewriteData, params) { + BaseOverviewsDataview.call(this, query, options, BaseDataview, queryRewriter, queryRewriteData, params); + + this.query = query; + this.column = options.column; + this.aggregation = options.aggregation; + this.aggregationColumn = options.aggregationColumn; +} + +Aggregation.prototype = Object.create(BaseOverviewsDataview.prototype); +Aggregation.prototype.constructor = Aggregation; + +module.exports = Aggregation; + +Aggregation.prototype.sql = function(psql, filters, override, callback) { + if (!callback) { + callback = override; + override = {}; + } + + var _query = this.rewrittenQuery(this.query); + + var aggregationSql; + if (!!override.ownFilter) { + aggregationSql = [ + "WITH", + [ + summaryQueryTpl({ + _query: _query, + _column: this.column + }), + rankedCategoriesQueryTpl({ + _query: _query, + _column: this.column, + _aggregation: this.getAggregationSql() + }), + categoriesSummaryQueryTpl({ + _query: _query, + _column: this.column + }) + ].join(',\n'), + aggregationQueryTpl({ + _query: _query, + _column: this.column, + _aggregation: this.getAggregationSql(), + _limit: CATEGORIES_LIMIT + }) + ].join('\n'); + } else { + aggregationSql = [ + "WITH", + [ + summaryQueryTpl({ + _query: _query, + _column: this.column + }), + rankedCategoriesQueryTpl({ + _query: _query, + _column: this.column, + _aggregation: this.getAggregationSql() + }), + categoriesSummaryQueryTpl({ + _query: _query, + _column: this.column + }) + ].join(',\n'), + rankedAggregationQueryTpl({ + _query: _query, + _column: this.column, + _limit: CATEGORIES_LIMIT + }) + ].join('\n'); + } + + return callback(null, aggregationSql); +}; + +var aggregationFnQueryTpl = { + count: dot.template('sum(_feature_count)'), + sum: dot.template('sum({{=it._aggregationColumn}}*_feature_count)') +}; + +Aggregation.prototype.getAggregationSql = function() { + return aggregationFnQueryTpl[this.aggregation]({ + _aggregationFn: this.aggregation, + _aggregationColumn: this.aggregationColumn || 1 + }); +}; diff --git a/lib/cartodb/models/dataview/overviews/base.js b/lib/cartodb/models/dataview/overviews/base.js new file mode 100644 index 00000000..bbf70742 --- /dev/null +++ b/lib/cartodb/models/dataview/overviews/base.js @@ -0,0 +1,88 @@ +var _ = require('underscore'); +var BaseDataview = require('../base'); + +function BaseOverviewsDataview(query, queryOptions, BaseDataview, queryRewriter, queryRewriteData, options) { + this.BaseDataview = BaseDataview; + this.query = query; + this.queryOptions = queryOptions; + this.queryRewriter = queryRewriter; + this.queryRewriteData = queryRewriteData; + this.options = options; + this.baseDataview = new this.BaseDataview(this.query, this.queryOptions); +} + +module.exports = BaseOverviewsDataview; + +BaseOverviewsDataview.prototype = new BaseDataview(); +BaseOverviewsDataview.prototype.constructor = BaseOverviewsDataview; + +// TODO: parameterized these settings +var SETTINGS = { + // use overviews as a default fallback strategy + defaultOverviews: false, + + // minimum ratio of bounding box size to grid size + // (this would ideally be based on the viewport size in pixels) + zoomLevelFactor: 1024.0 +}; + +// Compute zoom level so that the the resolution grid size of the +// selected overview is smaller (zoomLevelFactor times smaller at least) +// than the bounding box size. +BaseOverviewsDataview.prototype.zoomLevelForBbox = function(bbox) { + var pxPerTile = 256.0; + var earthWidth = 360.0; + // TODO: now we assume overviews are computed for 1-pixel tolerance; + // should use extended overviews metadata to compute this properly. + if ( bbox ) { + var bboxValues = _.map(bbox.split(','), function(v) { return +v; }); + var w = Math.abs(bboxValues[2]-bboxValues[0]); + var h = Math.abs(bboxValues[3]-bboxValues[1]); + var maxDim = Math.min(w, h); + + // Find minimum suitable z + // note that the QueryRewirter will use the minimum level overview + // of level >= z if it exists, and otherwise the base table + var z = Math.ceil(-Math.log(maxDim*pxPerTile/earthWidth/SETTINGS.zoomLevelFactor)/Math.log(2.0)); + return Math.max(z, 0); + } + return 0; +}; + +BaseOverviewsDataview.prototype.rewrittenQuery = function(query) { + var zoom_level = this.zoomLevelForBbox(this.options.bbox); + return this.queryRewriter.query(query, this.queryRewriteData, { zoom_level: zoom_level }); +}; + +// Default behaviour +BaseOverviewsDataview.prototype.defaultSql = function(psql, filters, override, callback) { + var query = this.query; + var dataview = this.baseDataview; + if ( SETTINGS.defaultOverviews ) { + query = this.rewrittenQuery(query); + dataview = new this.BaseDataview(query, this.queryOptions); + } + return dataview.sql(psql, filters, override, callback); +}; + +// default implementation that can be override in derived classes: + +BaseOverviewsDataview.prototype.sql = function(psql, filters, override, callback) { + return this.defaultSql(psql, filters, override, callback); +}; + +BaseOverviewsDataview.prototype.search = function(psql, userQuery, callback) { + return this.baseDataview.search(psql, userQuery, callback); +}; + +BaseOverviewsDataview.prototype.format = function(result) { + return this.baseDataview.format(result); +}; + +BaseOverviewsDataview.prototype.getType = function() { + return this.baseDataview.getType(); +}; + +BaseOverviewsDataview.prototype.toString = function() { + return this.baseDataview.toString(); +}; diff --git a/lib/cartodb/models/dataview/overviews/formula.js b/lib/cartodb/models/dataview/overviews/formula.js index aa57792e..adad5f58 100644 --- a/lib/cartodb/models/dataview/overviews/formula.js +++ b/lib/cartodb/models/dataview/overviews/formula.js @@ -1,9 +1,6 @@ -var _ = require('underscore'); -var BaseWidget = require('../base'); +var BaseOverviewsDataview = require('./base'); var BaseDataview = require('../formula'); -var debug = require('debug')('windshaft:widget:formula:overviews'); - var dot = require('dot'); dot.templateSettings.strip = false; @@ -29,76 +26,31 @@ var formulaQueryTpls = { }; function Formula(query, options, queryRewriter, queryRewriteData, params) { - this.base_dataview = new BaseDataview(query, options); - this.query = query; + BaseOverviewsDataview.call(this, query, options, BaseDataview, queryRewriter, queryRewriteData, params); this.column = options.column || '1'; this.operation = options.operation; - this.queryRewriter = queryRewriter; - this.queryRewriteData = queryRewriteData; - this.options = params; } -Formula.prototype = new BaseWidget(); +Formula.prototype = Object.create(BaseOverviewsDataview.prototype); Formula.prototype.constructor = Formula; module.exports = Formula; -var zoom_level_factor = 100.0; - -// Compute zoom level so that the the resolution grid size of the -// selected overview is smaller (zoom_level_factor times smaller at least) -// than the bounding box size. -function zoom_level_for_bbox(bbox) { - var px_per_tile = 256.0; - var earth_width = 360.0; - // TODO: now we assume overviews are computed for 1-pixel tolerance; - // should use extended overviews metadata to compute this properly. - if ( bbox ) { - var bbox_values = _.map(bbox.split(','), function(v) { return +v; }); - var w = Math.abs(bbox_values[2]-bbox_values[0]); - var h = Math.abs(bbox_values[3]-bbox_values[1]); - var max_dim = Math.min(w, h); - - // Find minimum suitable z - // note that the QueryRewirter will use the minimum level overview - // of level >= z if it exists, and otherwise the base table - var z = Math.ceil(-Math.log(max_dim*px_per_tile/earth_width/zoom_level_factor)/Math.log(2.0)); - return Math.max(z, 0); - } - return 0; -} - Formula.prototype.sql = function(psql, filters, override, callback) { - var _query = this.query; var formulaQueryTpl = formulaQueryTpls[this.operation]; if ( formulaQueryTpl ) { // supported formula for use with overviews - var zoom_level = zoom_level_for_bbox(this.options.bbox); - _query = this.queryRewriter.query(_query, this.queryRewriteData, { zoom_level: zoom_level }); var formulaSql = formulaQueryTpl({ - _query: _query, + _query: this.rewrittenQuery(this.query), _operation: this.operation, - _column: this.column + _column: this.column }); - debug(formulaSql); callback = callback || override; return callback(null, formulaSql); } - // For non supported operations (min, max) we're not using overviews. - return this.base_dataview.sql(psql, filters, override, callback); -}; - -Formula.prototype.format = function(result) { - return this.base_dataview.format(result); -}; - -Formula.prototype.getType = function() { - return this.base_dataview.getType(); -}; - -Formula.prototype.toString = function() { - return this.base_dataview.toString(); + // default behaviour + return this.defaultSql(psql, filters, override, callback); }; diff --git a/lib/cartodb/models/dataview/overviews/histogram.js b/lib/cartodb/models/dataview/overviews/histogram.js new file mode 100644 index 00000000..20dd7712 --- /dev/null +++ b/lib/cartodb/models/dataview/overviews/histogram.js @@ -0,0 +1,217 @@ +var _ = require('underscore'); +var BaseOverviewsDataview = require('./base'); +var BaseDataview = require('../histogram'); + +var dot = require('dot'); +dot.templateSettings.strip = false; + +var columnTypeQueryTpl = dot.template( + 'SELECT pg_typeof({{=it.column}})::oid FROM ({{=it.query}}) _cdb_histogram_column_type limit 1' +); +var columnCastTpl = dot.template("date_part('epoch', {{=it.column}})"); + +var BIN_MIN_NUMBER = 6; +var BIN_MAX_NUMBER = 48; + +var basicsQueryTpl = dot.template([ + 'basics AS (', + ' SELECT', + ' max({{=it._column}}) AS max_val, min({{=it._column}}) AS min_val,', + ' sum({{=it._column}}*_feature_count)/sum(_feature_count) AS avg_val, sum(_feature_count) AS total_rows', + ' FROM ({{=it._query}}) _cdb_basics', + ')' +].join(' \n')); + +var overrideBasicsQueryTpl = dot.template([ + 'basics AS (', + ' SELECT', + ' max({{=it._end}}) AS max_val, min({{=it._start}}) AS min_val,', + ' sum({{=it._column}}*_feature_count)/sum(_feature_count) AS avg_val, sum(_feature_count) AS total_rows', + ' FROM ({{=it._query}}) _cdb_basics', + ')' +].join('\n')); + +var iqrQueryTpl = dot.template([ + 'iqrange AS (', + ' SELECT max(quartile_max) - min(quartile_max) AS iqr', + ' FROM (', + ' SELECT quartile, max(_cdb_iqr_column) AS quartile_max from (', + ' SELECT {{=it._column}} AS _cdb_iqr_column, ntile(4) over (order by {{=it._column}}', + ' ) AS quartile', + ' FROM ({{=it._query}}) _cdb_rank) _cdb_quartiles', + ' WHERE quartile = 1 or quartile = 3', + ' GROUP BY quartile', + ' ) _cdb_iqr', + ')' +].join('\n')); + +var binsQueryTpl = dot.template([ + 'bins AS (', + ' SELECT CASE WHEN total_rows = 0 OR iqr = 0', + ' THEN 1', + ' ELSE GREATEST(', + ' LEAST({{=it._minBins}}, CAST(total_rows AS INT)),', + ' LEAST(', + ' CAST(((max_val - min_val) / (2 * iqr * power(total_rows, 1/3))) AS INT),', + ' {{=it._maxBins}}', + ' )', + ' )', + ' END AS bins_number', + ' FROM basics, iqrange, ({{=it._query}}) _cdb_bins', + ' LIMIT 1', + ')' +].join('\n')); + +var overrideBinsQueryTpl = dot.template([ + 'bins AS (', + ' SELECT {{=it._bins}} AS bins_number', + ')' +].join('\n')); + +var nullsQueryTpl = dot.template([ + 'nulls AS (', + ' SELECT', + ' count(*) AS nulls_count', + ' FROM ({{=it._query}}) _cdb_histogram_nulls', + ' WHERE {{=it._column}} IS NULL', + ')' +].join('\n')); + +var histogramQueryTpl = dot.template([ + 'SELECT', + ' (max_val - min_val) / cast(bins_number as float) AS bin_width,', + ' bins_number,', + ' nulls_count,', + ' avg_val,', + ' CASE WHEN min_val = max_val', + ' THEN 0', + ' ELSE GREATEST(1, LEAST(WIDTH_BUCKET({{=it._column}}, min_val, max_val, bins_number), bins_number)) - 1', + ' END AS bin,', + ' min({{=it._column}})::numeric AS min,', + ' max({{=it._column}})::numeric AS max,', + ' sum({{=it._column}}*_feature_count)/sum(_feature_count)::numeric AS avg,', + ' sum(_feature_count) AS freq', + 'FROM ({{=it._query}}) _cdb_histogram, basics, nulls, bins', + 'WHERE {{=it._column}} IS NOT NULL', + 'GROUP BY bin, bins_number, bin_width, nulls_count, avg_val', + 'ORDER BY bin' +].join('\n')); + +function Histogram(query, options, queryRewriter, queryRewriteData, params) { + BaseOverviewsDataview.call(this, query, options, BaseDataview, queryRewriter, queryRewriteData, params); + + this.query = query; + this.column = options.column; + this.bins = options.bins; + + this._columnType = null; +} + +Histogram.prototype = Object.create(BaseOverviewsDataview.prototype); +Histogram.prototype.constructor = Histogram; + +module.exports = Histogram; + + +var DATE_OIDS = { + 1082: true, + 1114: true, + 1184: true +}; + +Histogram.prototype.sql = function(psql, override, callback) { + if (!callback) { + callback = override; + override = {}; + } + + var self = this; + + var _column = this.column; + + var columnTypeQuery = columnTypeQueryTpl({ + column: _column, query: this.rewrittenQuery(this.query) + }); + + if (this._columnType === null) { + psql.query(columnTypeQuery, function(err, result) { + // assume numeric, will fail later + self._columnType = 'numeric'; + if (!err && !!result.rows[0]) { + var pgType = result.rows[0].pg_typeof; + if (DATE_OIDS.hasOwnProperty(pgType)) { + self._columnType = 'date'; + } + } + self.sql(psql, override, callback); + }, true); // use read-only transaction + return null; + } + + if (this._columnType === 'date') { + _column = columnCastTpl({column: _column}); + } + + var _query = this.rewrittenQuery(this.query); + + var basicsQuery, binsQuery; + + if (override && _.has(override, 'start') && _.has(override, 'end') && _.has(override, 'bins')) { + basicsQuery = overrideBasicsQueryTpl({ + _query: _query, + _column: _column, + _start: override.start, + _end: override.end + }); + + binsQuery = [ + overrideBinsQueryTpl({ + _bins: override.bins + }) + ].join(',\n'); + } else { + basicsQuery = basicsQueryTpl({ + _query: _query, + _column: _column + }); + + if (override && _.has(override, 'bins')) { + binsQuery = [ + overrideBinsQueryTpl({ + _bins: override.bins + }) + ].join(',\n'); + } else { + binsQuery = [ + iqrQueryTpl({ + _query: _query, + _column: _column + }), + binsQueryTpl({ + _query: _query, + _minBins: BIN_MIN_NUMBER, + _maxBins: BIN_MAX_NUMBER + }) + ].join(',\n'); + } + } + + + var histogramSql = [ + "WITH", + [ + basicsQuery, + binsQuery, + nullsQueryTpl({ + _query: _query, + _column: _column + }) + ].join(',\n'), + histogramQueryTpl({ + _query: _query, + _column: _column + }) + ].join('\n'); + + return callback(null, histogramSql); +}; diff --git a/lib/cartodb/models/dataview/overviews/index.js b/lib/cartodb/models/dataview/overviews/index.js index 775ceca1..c541973e 100644 --- a/lib/cartodb/models/dataview/overviews/index.js +++ b/lib/cartodb/models/dataview/overviews/index.js @@ -1,3 +1,6 @@ module.exports = { - Formula: require('./formula') + Aggregation: require('./aggregation'), + Formula: require('./formula'), + Histogram: require('./histogram'), + List: require('./list') }; diff --git a/lib/cartodb/models/dataview/overviews/list.js b/lib/cartodb/models/dataview/overviews/list.js new file mode 100644 index 00000000..7e3b3161 --- /dev/null +++ b/lib/cartodb/models/dataview/overviews/list.js @@ -0,0 +1,11 @@ +var BaseOverviewsDataview = require('./base'); +var BaseDataview = require('../list'); + +function List(query, options, queryRewriter, queryRewriteData, params) { + BaseOverviewsDataview.call(this, query, options, BaseDataview, queryRewriter, queryRewriteData, params); +} + +List.prototype = Object.create(BaseOverviewsDataview.prototype); +List.prototype.constructor = List; + +module.exports = List; diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 0867140b..0b51d56d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "windshaft-cartodb", - "version": "2.44.1", + "version": "2.44.2", "dependencies": { "body-parser": { "version": "1.14.2", @@ -80,7 +80,7 @@ }, "type-is": { "version": "1.6.13", - "from": "type-is@>=1.6.10 <1.7.0", + "from": "type-is@>=1.6.6 <1.7.0", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz", "dependencies": { "media-typer": { @@ -90,7 +90,7 @@ }, "mime-types": { "version": "2.1.11", - "from": "mime-types@>=2.1.2 <2.2.0", + "from": "mime-types@>=2.1.11 <2.2.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", "dependencies": { "mime-db": { @@ -1257,9 +1257,9 @@ "resolved": "https://registry.npmjs.org/step-profiler/-/step-profiler-0.3.0.tgz" }, "turbo-carto": { - "version": "0.10.0", - "from": "turbo-carto@0.10.0", - "resolved": "https://registry.npmjs.org/turbo-carto/-/turbo-carto-0.10.0.tgz", + "version": "0.10.1", + "from": "turbo-carto@0.10.1", + "resolved": "https://registry.npmjs.org/turbo-carto/-/turbo-carto-0.10.1.tgz", "dependencies": { "colorbrewer": { "version": "1.0.0", @@ -3066,16 +3066,16 @@ "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" }, - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, "cryptiles": { "version": "2.0.5", "from": "cryptiles@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" }, + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, "deep-extend": { "version": "0.4.1", "from": "deep-extend@>=0.4.0 <0.5.0", @@ -3111,36 +3111,36 @@ "from": "extsprintf@1.0.2", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" }, - "form-data": { - "version": "1.0.0-rc4", - "from": "form-data@>=1.0.0-rc3 <1.1.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz" + "forever-agent": { + "version": "0.6.1", + "from": "forever-agent@>=0.6.1 <0.7.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" }, "fstream": { "version": "1.0.9", "from": "fstream@>=1.0.2 <2.0.0", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.9.tgz" }, - "forever-agent": { - "version": "0.6.1", - "from": "forever-agent@>=0.6.1 <0.7.0", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + "form-data": { + "version": "1.0.0-rc4", + "from": "form-data@>=1.0.0-rc3 <1.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz" }, "fstream-ignore": { "version": "1.0.4", "from": "fstream-ignore@>=1.0.3 <1.1.0", "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.4.tgz" }, - "gauge": { - "version": "1.2.7", - "from": "gauge@>=1.2.5 <1.3.0", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz" - }, "generate-function": { "version": "2.0.0", "from": "generate-function@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" }, + "gauge": { + "version": "1.2.7", + "from": "gauge@>=1.2.5 <1.3.0", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz" + }, "generate-object-property": { "version": "1.2.0", "from": "generate-object-property@>=1.1.0 <2.0.0", @@ -3156,56 +3156,56 @@ "from": "graceful-fs@>=4.1.2 <5.0.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz" }, - "har-validator": { - "version": "2.0.6", - "from": "har-validator@>=2.0.6 <2.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz" - }, "graceful-readlink": { "version": "1.0.1", "from": "graceful-readlink@>=1.0.0", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" }, + "har-validator": { + "version": "2.0.6", + "from": "har-validator@>=2.0.6 <2.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz" + }, "has-ansi": { "version": "2.0.0", "from": "has-ansi@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" }, - "has-unicode": { - "version": "2.0.0", - "from": "has-unicode@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.0.tgz" - }, "hawk": { "version": "3.1.3", "from": "hawk@>=3.1.3 <3.2.0", "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz" }, - "http-signature": { - "version": "1.1.1", - "from": "http-signature@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz" + "has-unicode": { + "version": "2.0.0", + "from": "has-unicode@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.0.tgz" }, "hoek": { "version": "2.16.3", "from": "hoek@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" }, + "http-signature": { + "version": "1.1.1", + "from": "http-signature@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz" + }, "inflight": { "version": "1.0.4", "from": "inflight@>=1.0.4 <2.0.0", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz" }, - "inherits": { - "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, "ini": { "version": "1.3.4", "from": "ini@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz" }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, "is-my-json-valid": { "version": "2.13.1", "from": "is-my-json-valid@>=2.12.4 <3.0.0", @@ -3221,16 +3221,16 @@ "from": "is-typedarray@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" }, - "isarray": { - "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, "isstream": { "version": "0.1.2", "from": "isstream@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, "jodid25519": { "version": "1.0.2", "from": "jodid25519@>=1.0.0 <2.0.0", @@ -3256,31 +3256,31 @@ "from": "jsonpointer@2.0.0", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz" }, - "jsprim": { - "version": "1.2.2", - "from": "jsprim@>=1.2.2 <2.0.0", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.2.2.tgz" - }, "lodash._baseslice": { "version": "4.0.0", "from": "lodash._baseslice@>=4.0.0 <4.1.0", "resolved": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz" }, + "jsprim": { + "version": "1.2.2", + "from": "jsprim@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.2.2.tgz" + }, "lodash._basetostring": { "version": "4.12.0", "from": "lodash._basetostring@>=4.12.0 <4.13.0", "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz" }, - "lodash.pad": { - "version": "4.4.0", - "from": "lodash.pad@>=4.1.0 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.4.0.tgz" - }, "lodash.padend": { "version": "4.5.0", "from": "lodash.padend@>=4.1.0 <5.0.0", "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.5.0.tgz" }, + "lodash.pad": { + "version": "4.4.0", + "from": "lodash.pad@>=4.1.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.4.0.tgz" + }, "lodash.padstart": { "version": "4.5.0", "from": "lodash.padstart@>=4.1.0 <5.0.0", @@ -3406,16 +3406,16 @@ "from": "stringstream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz" }, - "strip-ansi": { - "version": "3.0.1", - "from": "strip-ansi@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - }, "strip-json-comments": { "version": "1.0.4", "from": "strip-json-comments@>=1.0.4 <1.1.0", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz" }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" + }, "supports-color": { "version": "2.0.0", "from": "supports-color@>=2.0.0 <3.0.0", diff --git a/package.json b/package.json index 7bc32995..a8b77dbd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "windshaft-cartodb", - "version": "2.44.1", + "version": "2.44.2", "description": "A map tile server for CartoDB", "keywords": [ "cartodb" @@ -37,7 +37,7 @@ "request": "~2.62.0", "step": "~0.0.6", "step-profiler": "~0.3.0", - "turbo-carto": "0.10.0", + "turbo-carto": "0.10.1", "underscore": "~1.6.0", "windshaft": "1.19.0" },