diff --git a/NEWS.md b/NEWS.md index 6f61c502..19ad5960 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,11 +1,36 @@ # Changelog -## 2.42.0 +## 2.42.3 Released 2016-mm-dd + +## 2.42.2 + +Released 2016-05-17 + +New features: + - turbo-carto: mapnik substitution tokens support #455 + + +## 2.42.1 + +Released 2016-05-17 +- Upgraded turbo-carto to fix reversed color scales + + +## 2.42.0 + +Released 2016-05-16 + +Bug fixes: + - Fix named maps with analysis #453 + +Enhancements: + - Use split strategy for head/tails turbo-carto quantification + Announcements: - - Upgrades turbo-carto to [0.8.0](https://github.com/CartoDB/turbo-carto/releases/tag/0.8.0) + - Upgrades turbo-carto to [0.9.0](https://github.com/CartoDB/turbo-carto/releases/tag/0.9.0) ## 2.41.1 diff --git a/lib/cartodb/api/overviews_metadata_api.js b/lib/cartodb/api/overviews_metadata_api.js index 2cec6bbb..55b4966f 100644 --- a/lib/cartodb/api/overviews_metadata_api.js +++ b/lib/cartodb/api/overviews_metadata_api.js @@ -1,24 +1,18 @@ +var SubstitutionTokens = require('../utils/substitution-tokens'); + function OverviewsMetadataApi(pgQueryRunner) { this.pgQueryRunner = pgQueryRunner; } module.exports = OverviewsMetadataApi; -// TODO: share this with QueryTablesApi? ... or maintain independence? -var affectedTableRegexCache = { - bbox: /!bbox!/g, - scale_denominator: /!scale_denominator!/g, - pixel_width: /!pixel_width!/g, - pixel_height: /!pixel_height!/g -}; - function prepareSql(sql) { - return sql && sql - .replace(affectedTableRegexCache.bbox, 'ST_MakeEnvelope(0,0,0,0)') - .replace(affectedTableRegexCache.scale_denominator, '0') - .replace(affectedTableRegexCache.pixel_width, '1') - .replace(affectedTableRegexCache.pixel_height, '1') - ; + return sql && SubstitutionTokens.replace(sql, { + bbox: 'ST_MakeEnvelope(0,0,0,0)', + scale_denominator: '0', + pixel_width: '1', + pixel_height: '1' + }); } OverviewsMetadataApi.prototype.getOverviewsMetadata = function (username, sql, callback) { diff --git a/lib/cartodb/cache/named_map_provider_cache.js b/lib/cartodb/cache/named_map_provider_cache.js index a25850dc..9adb29b9 100644 --- a/lib/cartodb/cache/named_map_provider_cache.js +++ b/lib/cartodb/cache/named_map_provider_cache.js @@ -8,15 +8,15 @@ var queue = require('queue-async'); var LruCache = require("lru-cache"); -function NamedMapProviderCache(templateMaps, pgConnection, metadataBackend, userLimitsApi, overviewsAdapter, - turboCartoAdapter) { +function NamedMapProviderCache(templateMaps, pgConnection, metadataBackend, analysisBackend, userLimitsApi, + overviewsAdapter, turboCartoAdapter) { this.templateMaps = templateMaps; this.pgConnection = pgConnection; this.metadataBackend = metadataBackend; this.userLimitsApi = userLimitsApi; this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps); - this.analysisMapConfigAdapter = new AnalysisMapConfigAdapter(); + this.analysisMapConfigAdapter = new AnalysisMapConfigAdapter(analysisBackend); this.overviewsAdapter = overviewsAdapter; this.turboCartoAdapter = turboCartoAdapter; diff --git a/lib/cartodb/server.js b/lib/cartodb/server.js index 3feee602..8117d208 100644 --- a/lib/cartodb/server.js +++ b/lib/cartodb/server.js @@ -159,6 +159,7 @@ module.exports = function(serverOptions) { templateMaps, pgConnection, metadataBackend, + analysisBackend, userLimitsApi, overviewsAdapter, turboCartoAdapter diff --git a/lib/cartodb/utils/style/postgres-datasource.js b/lib/cartodb/utils/style/postgres-datasource.js index fd6e02c1..5db35607 100644 --- a/lib/cartodb/utils/style/postgres-datasource.js +++ b/lib/cartodb/utils/style/postgres-datasource.js @@ -23,6 +23,10 @@ var methodTemplates = Object.keys(methods).reduce(function(methodTemplates, meth return methodTemplates; }, {}); +var method2strategy = { + headtails: 'split' +}; + function PostgresDatasource (pgQueryRunner, username, query) { this.pgQueryRunner = pgQueryRunner; this.username = username; @@ -48,7 +52,7 @@ PostgresDatasource.prototype.getRamp = function (column, buckets, method, callba return a - b; }); - return callback(null, ramp); + return callback(null, { ramp: ramp, strategy: method2strategy[methodName] }); }); }; diff --git a/lib/cartodb/utils/style/turbo-carto-adapter.js b/lib/cartodb/utils/style/turbo-carto-adapter.js index 1c197ac7..d1c0c81f 100644 --- a/lib/cartodb/utils/style/turbo-carto-adapter.js +++ b/lib/cartodb/utils/style/turbo-carto-adapter.js @@ -1,6 +1,7 @@ 'use strict'; var queue = require('queue-async'); +var SubstitutionTokens = require('../substitution-tokens'); function TurboCartoAdapter(turboCartoParser) { this.turboCartoParser = turboCartoParser; @@ -37,13 +38,26 @@ TurboCartoAdapter.prototype._parseCartoCss = function (username, layer, callback }); } - this.turboCartoParser.process(username, layer.options.cartocss, layer.options.sql, function (err, cartocss) { - // Ignore turbo-carto errors and continue - if (!err && cartocss) { - layer.options.cartocss = cartocss; + var sql = SubstitutionTokens.replace(layer.options.sql, { + bbox: 'ST_MakeEnvelope(-20037508.34,-20037508.34,20037508.34,20037508.34,3857)', + scale_denominator: '500000001', + pixel_width: '156412', + pixel_height: '156412' + }); + + this.turboCartoParser.process(username, layer.options.cartocss, sql, function (err, cartocss) { + // Only return turbo-carto errors + if (err && err.name === 'TurboCartoError') { + err = new Error('turbo-carto: ' + err.message); + err.http_status = 400; + return callback(err); } - callback(null, layer); + // Try to continue in the rest of the cases + if (cartocss) { + layer.options.cartocss = cartocss; + } + return callback(null, layer); }); }; diff --git a/lib/cartodb/utils/substitution-tokens.js b/lib/cartodb/utils/substitution-tokens.js new file mode 100644 index 00000000..af09f838 --- /dev/null +++ b/lib/cartodb/utils/substitution-tokens.js @@ -0,0 +1,19 @@ +var SUBSTITUTION_TOKENS = { + bbox: /!bbox!/g, + scale_denominator: /!scale_denominator!/g, + pixel_width: /!pixel_width!/g, + pixel_height: /!pixel_height!/g +}; + +var SubstitutionTokens = { + replace: function(sql, replaceValues) { + Object.keys(replaceValues).forEach(function(token) { + if (SUBSTITUTION_TOKENS[token]) { + sql = sql.replace(SUBSTITUTION_TOKENS[token], replaceValues[token]); + } + }); + return sql; + } +}; + +module.exports = SubstitutionTokens; diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index d0882518..c3b9529d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "windshaft-cartodb", - "version": "2.42.0", + "version": "2.42.3", "dependencies": { "body-parser": { "version": "1.14.2", @@ -80,7 +80,7 @@ }, "type-is": { "version": "1.6.12", - "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.12.tgz", "dependencies": { "media-typer": { @@ -584,7 +584,7 @@ "dependencies": { "mime-types": { "version": "2.1.11", - "from": "mime-types@>=2.1.10 <2.2.0", + "from": "mime-types@>=2.1.6 <2.2.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", "dependencies": { "mime-db": { @@ -773,7 +773,7 @@ }, "mime-types": { "version": "2.1.11", - "from": "mime-types@>=2.1.10 <2.2.0", + "from": "mime-types@>=2.1.6 <2.2.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", "dependencies": { "mime-db": { @@ -976,7 +976,7 @@ "dependencies": { "async": { "version": "1.5.2", - "from": "async@>=1.0.0 <2.0.0", + "from": "async@>=1.5.2 <2.0.0", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz" } } @@ -1215,9 +1215,9 @@ "from": "step-profiler@>=0.3.0 <0.4.0" }, "turbo-carto": { - "version": "0.8.0", - "from": "turbo-carto@0.8.0", - "resolved": "https://registry.npmjs.org/turbo-carto/-/turbo-carto-0.8.0.tgz", + "version": "0.9.2", + "from": "turbo-carto@0.9.2", + "resolved": "https://registry.npmjs.org/turbo-carto/-/turbo-carto-0.9.2.tgz", "dependencies": { "colorbrewer": { "version": "1.0.0", @@ -1225,9 +1225,9 @@ "resolved": "https://registry.npmjs.org/colorbrewer/-/colorbrewer-1.0.0.tgz" }, "cartocolor": { - "version": "1.0.2", - "from": "cartocolor@1.0.2", - "resolved": "https://registry.npmjs.org/cartocolor/-/cartocolor-1.0.2.tgz" + "version": "1.1.0", + "from": "cartocolor@1.1.0", + "resolved": "https://registry.npmjs.org/cartocolor/-/cartocolor-1.1.0.tgz" }, "es6-promise": { "version": "3.1.2", @@ -2910,817 +2910,589 @@ } }, "sqlite3": { - "version": "3.1.3", + "version": "3.1.4", "from": "sqlite3@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-3.1.3.tgz", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-3.1.4.tgz", "dependencies": { "nan": { - "version": "2.2.1", - "from": "nan@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.2.1.tgz" + "version": "2.3.3", + "from": "nan@>=2.3.3 <2.4.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.3.3.tgz" }, "node-pre-gyp": { - "version": "0.6.25", - "from": "node-pre-gyp@~0.6.25", + "version": "0.6.28", + "from": "node-pre-gyp@>=0.6.28 <0.7.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.28.tgz" + }, + "abbrev": { + "version": "1.0.7", + "from": "abbrev@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz" + }, + "ansi": { + "version": "0.3.1", + "from": "ansi@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz" + }, + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + }, + "ansi-styles": { + "version": "2.2.1", + "from": "ansi-styles@>=2.2.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" + }, + "are-we-there-yet": { + "version": "1.1.2", + "from": "are-we-there-yet@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz" + }, + "asn1": { + "version": "0.2.3", + "from": "asn1@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" + }, + "async": { + "version": "1.5.2", + "from": "async@>=1.5.2 <2.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz" + }, + "assert-plus": { + "version": "0.2.0", + "from": "assert-plus@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz" + }, + "aws-sign2": { + "version": "0.6.0", + "from": "aws-sign2@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz" + }, + "aws4": { + "version": "1.4.1", + "from": "aws4@>=1.2.1 <2.0.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz" + }, + "balanced-match": { + "version": "0.4.1", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz" + }, + "block-stream": { + "version": "0.0.9", + "from": "block-stream@*", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz" + }, + "boom": { + "version": "2.10.1", + "from": "boom@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" + }, + "brace-expansion": { + "version": "1.1.4", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.4.tgz" + }, + "caseless": { + "version": "0.11.0", + "from": "caseless@>=0.11.0 <0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" + }, + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" + }, + "combined-stream": { + "version": "1.0.5", + "from": "combined-stream@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz" + }, + "commander": { + "version": "2.9.0", + "from": "commander@>=2.9.0 <3.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + }, + "core-util-is": { + "version": "1.0.2", + "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" + }, + "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", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz" + }, + "delayed-stream": { + "version": "1.0.0", + "from": "delayed-stream@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + }, + "delegates": { + "version": "1.0.0", + "from": "delegates@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" + }, + "ecc-jsbn": { + "version": "0.1.1", + "from": "ecc-jsbn@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" + }, + "escape-string-regexp": { + "version": "1.0.5", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + }, + "extend": { + "version": "3.0.0", + "from": "extend@>=3.0.0 <3.1.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + }, + "extsprintf": { + "version": "1.0.2", + "from": "extsprintf@1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.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": { + "version": "1.0.9", + "from": "fstream@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.9.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" + }, + "generate-object-property": { + "version": "1.2.0", + "from": "generate-object-property@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz" + }, + "glob": { + "version": "7.0.3", + "from": "glob@>=7.0.0 <8.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz" + }, + "graceful-fs": { + "version": "4.1.4", + "from": "graceful-fs@>=4.1.2 <5.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.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" + }, + "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" + }, + "is-my-json-valid": { + "version": "2.13.1", + "from": "is-my-json-valid@>=2.12.4 <3.0.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz" + }, + "is-property": { + "version": "1.0.2", + "from": "is-property@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" + }, + "is-typedarray": { + "version": "1.0.0", + "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" + }, + "jodid25519": { + "version": "1.0.2", + "from": "jodid25519@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz" + }, + "jsbn": { + "version": "0.1.0", + "from": "jsbn@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz" + }, + "json-schema": { + "version": "0.2.2", + "from": "json-schema@0.2.2", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz" + }, + "json-stringify-safe": { + "version": "5.0.1", + "from": "json-stringify-safe@>=5.0.1 <5.1.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + }, + "jsonpointer": { + "version": "2.0.0", + "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" + }, + "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.padstart": { + "version": "4.5.0", + "from": "lodash.padstart@>=4.1.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.5.0.tgz" + }, + "lodash.tostring": { + "version": "4.1.3", + "from": "lodash.tostring@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.3.tgz" + }, + "mime-db": { + "version": "1.23.0", + "from": "mime-db@>=1.23.0 <1.24.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz" + }, + "mime-types": { + "version": "2.1.11", + "from": "mime-types@>=2.1.7 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz" + }, + "minimatch": { + "version": "3.0.0", + "from": "minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.0.tgz" + }, + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + }, + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "node-uuid": { + "version": "1.4.7", + "from": "node-uuid@>=1.4.7 <1.5.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz" + }, + "nopt": { + "version": "3.0.6", + "from": "nopt@>=3.0.1 <3.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" + }, + "npmlog": { + "version": "2.0.3", + "from": "npmlog@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.3.tgz" + }, + "oauth-sign": { + "version": "0.8.2", + "from": "oauth-sign@>=0.8.1 <0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz" + }, + "once": { + "version": "1.3.3", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz" + }, + "path-is-absolute": { + "version": "1.0.0", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + }, + "pinkie": { + "version": "2.0.4", + "from": "pinkie@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + }, + "pinkie-promise": { + "version": "2.0.1", + "from": "pinkie-promise@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "qs": { + "version": "6.1.0", + "from": "qs@>=6.1.0 <6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.1.0.tgz" + }, + "readable-stream": { + "version": "2.1.2", + "from": "readable-stream@>=2.0.0 <3.0.0||>=1.1.13 <2.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.2.tgz" + }, + "request": { + "version": "2.72.0", + "from": "request@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.72.0.tgz" + }, + "rimraf": { + "version": "2.5.2", + "from": "rimraf@>=2.5.0 <2.6.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.2.tgz" + }, + "semver": { + "version": "5.1.0", + "from": "semver@>=5.1.0 <5.2.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.0.tgz" + }, + "sntp": { + "version": "1.0.9", + "from": "sntp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "stringstream": { + "version": "0.0.5", + "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" + }, + "supports-color": { + "version": "2.0.0", + "from": "supports-color@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" + }, + "tar": { + "version": "2.2.1", + "from": "tar@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz" + }, + "tough-cookie": { + "version": "2.2.2", + "from": "tough-cookie@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz" + }, + "tunnel-agent": { + "version": "0.4.3", + "from": "tunnel-agent@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz" + }, + "tweetnacl": { + "version": "0.13.3", + "from": "tweetnacl@>=0.13.0 <0.14.0", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz" + }, + "uid-number": { + "version": "0.0.6", + "from": "uid-number@>=0.0.6 <0.1.0", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + }, + "verror": { + "version": "1.3.6", + "from": "verror@1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz" + }, + "wrappy": { + "version": "1.0.1", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + }, + "xtend": { + "version": "4.0.1", + "from": "xtend@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + }, + "bl": { + "version": "1.1.2", + "from": "bl@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", "dependencies": { - "nopt": { - "version": "3.0.6", - "from": "nopt@~3.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "dependencies": { - "abbrev": { - "version": "1.0.7", - "from": "abbrev@1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz" - } - } - }, - "npmlog": { - "version": "2.0.3", - "from": "npmlog@~2.0.0", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.3.tgz", - "dependencies": { - "ansi": { - "version": "0.3.1", - "from": "ansi@~0.3.1", - "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz" - }, - "are-we-there-yet": { - "version": "1.1.2", - "from": "are-we-there-yet@~1.1.2", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz", - "dependencies": { - "delegates": { - "version": "1.0.0", - "from": "delegates@^1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" - }, - "readable-stream": { - "version": "2.0.6", - "from": "readable-stream@^2.0.0 || ^1.1.13", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "from": "core-util-is@~1.0.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, - "inherits": { - "version": "2.0.1", - "from": "inherits@~2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, - "isarray": { - "version": "1.0.0", - "from": "isarray@~1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "process-nextick-args": { - "version": "1.0.6", - "from": "process-nextick-args@~1.0.6", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@~0.10.x", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "util-deprecate": { - "version": "1.0.2", - "from": "util-deprecate@~1.0.1", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } - } - } - } - }, - "gauge": { - "version": "1.2.7", - "from": "gauge@~1.2.5", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", - "dependencies": { - "has-unicode": { - "version": "2.0.0", - "from": "has-unicode@^2.0.0", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.0.tgz" - }, - "lodash.pad": { - "version": "4.1.0", - "from": "lodash.pad@^4.1.0", - "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.1.0.tgz", - "dependencies": { - "lodash.repeat": { - "version": "4.0.0", - "from": "lodash.repeat@^4.0.0", - "resolved": "https://registry.npmjs.org/lodash.repeat/-/lodash.repeat-4.0.0.tgz" - }, - "lodash.tostring": { - "version": "4.1.2", - "from": "lodash.tostring@^4.0.0", - "resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.2.tgz" - } - } - }, - "lodash.padend": { - "version": "4.2.0", - "from": "lodash.padend@^4.1.0", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.2.0.tgz", - "dependencies": { - "lodash.repeat": { - "version": "4.0.0", - "from": "lodash.repeat@^4.0.0", - "resolved": "https://registry.npmjs.org/lodash.repeat/-/lodash.repeat-4.0.0.tgz" - }, - "lodash.tostring": { - "version": "4.1.2", - "from": "lodash.tostring@^4.0.0", - "resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.2.tgz" - } - } - }, - "lodash.padstart": { - "version": "4.2.0", - "from": "lodash.padstart@^4.1.0", - "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.2.0.tgz", - "dependencies": { - "lodash.repeat": { - "version": "4.0.0", - "from": "lodash.repeat@^4.0.0", - "resolved": "https://registry.npmjs.org/lodash.repeat/-/lodash.repeat-4.0.0.tgz" - }, - "lodash.tostring": { - "version": "4.1.2", - "from": "lodash.tostring@^4.0.0", - "resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.2.tgz" - } - } - } - } - } - } - }, - "request": { - "version": "2.69.0", - "from": "request@2.x", - "resolved": "https://registry.npmjs.org/request/-/request-2.69.0.tgz", - "dependencies": { - "aws-sign2": { - "version": "0.6.0", - "from": "aws-sign2@~0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz" - }, - "aws4": { - "version": "1.3.2", - "from": "aws4@^1.2.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.3.2.tgz", - "dependencies": { - "lru-cache": { - "version": "4.0.1", - "from": "lru-cache@^4.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", - "dependencies": { - "pseudomap": { - "version": "1.0.2", - "from": "pseudomap@^1.0.1", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz" - }, - "yallist": { - "version": "2.0.0", - "from": "yallist@^2.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz" - } - } - } - } - }, - "bl": { - "version": "1.0.3", - "from": "bl@~1.0.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz", - "dependencies": { - "readable-stream": { - "version": "2.0.6", - "from": "readable-stream@~2.0.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "from": "core-util-is@~1.0.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, - "inherits": { - "version": "2.0.1", - "from": "inherits@~2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, - "isarray": { - "version": "1.0.0", - "from": "isarray@~1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "process-nextick-args": { - "version": "1.0.6", - "from": "process-nextick-args@~1.0.6", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@~0.10.x", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "util-deprecate": { - "version": "1.0.2", - "from": "util-deprecate@~1.0.1", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } - } - } - } - }, - "caseless": { - "version": "0.11.0", - "from": "caseless@~0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" - }, - "combined-stream": { - "version": "1.0.5", - "from": "combined-stream@~1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "dependencies": { - "delayed-stream": { - "version": "1.0.0", - "from": "delayed-stream@~1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - } - } - }, - "extend": { - "version": "3.0.0", - "from": "extend@~3.0.0", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" - }, - "forever-agent": { - "version": "0.6.1", - "from": "forever-agent@~0.6.1", - "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", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz", - "dependencies": { - "async": { - "version": "1.5.2", - "from": "async@^1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz" - } - } - }, - "har-validator": { - "version": "2.0.6", - "from": "har-validator@~2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "dependencies": { - "chalk": { - "version": "1.1.3", - "from": "chalk@^1.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "from": "ansi-styles@^2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" - }, - "escape-string-regexp": { - "version": "1.0.5", - "from": "escape-string-regexp@^1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - }, - "has-ansi": { - "version": "2.0.0", - "from": "has-ansi@^2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "dependencies": { - "ansi-regex": { - "version": "2.0.0", - "from": "ansi-regex@^2.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "from": "strip-ansi@^3.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "dependencies": { - "ansi-regex": { - "version": "2.0.0", - "from": "ansi-regex@^2.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" - } - } - }, - "supports-color": { - "version": "2.0.0", - "from": "supports-color@^2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" - } - } - }, - "commander": { - "version": "2.9.0", - "from": "commander@^2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "dependencies": { - "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" - } - } - }, - "is-my-json-valid": { - "version": "2.13.1", - "from": "is-my-json-valid@^2.12.4", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz", - "dependencies": { - "generate-function": { - "version": "2.0.0", - "from": "generate-function@^2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" - }, - "generate-object-property": { - "version": "1.2.0", - "from": "generate-object-property@^1.1.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "dependencies": { - "is-property": { - "version": "1.0.2", - "from": "is-property@^1.0.0", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" - } - } - }, - "jsonpointer": { - "version": "2.0.0", - "from": "jsonpointer@2.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz" - }, - "xtend": { - "version": "4.0.1", - "from": "xtend@^4.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - } - }, - "pinkie-promise": { - "version": "2.0.0", - "from": "pinkie-promise@^2.0.0", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.0.tgz", - "dependencies": { - "pinkie": { - "version": "2.0.4", - "from": "pinkie@^2.0.0", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" - } - } - } - } - }, - "hawk": { - "version": "3.1.3", - "from": "hawk@~3.1.0", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "dependencies": { - "hoek": { - "version": "2.16.3", - "from": "hoek@2.x.x", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" - }, - "boom": { - "version": "2.10.1", - "from": "boom@2.x.x", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" - }, - "cryptiles": { - "version": "2.0.5", - "from": "cryptiles@2.x.x", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" - }, - "sntp": { - "version": "1.0.9", - "from": "sntp@1.x.x", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" - } - } - }, - "http-signature": { - "version": "1.1.1", - "from": "http-signature@~1.1.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "dependencies": { - "assert-plus": { - "version": "0.2.0", - "from": "assert-plus@^0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz" - }, - "jsprim": { - "version": "1.2.2", - "from": "jsprim@^1.2.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.2.2.tgz", - "dependencies": { - "extsprintf": { - "version": "1.0.2", - "from": "extsprintf@1.0.2", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" - }, - "json-schema": { - "version": "0.2.2", - "from": "json-schema@0.2.2", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz" - }, - "verror": { - "version": "1.3.6", - "from": "verror@1.3.6", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz" - } - } - }, - "sshpk": { - "version": "1.7.4", - "from": "sshpk@^1.7.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.7.4.tgz", - "dependencies": { - "asn1": { - "version": "0.2.3", - "from": "asn1@>=0.2.3 <0.3.0", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" - }, - "dashdash": { - "version": "1.13.0", - "from": "dashdash@>=1.10.1 <2.0.0", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.13.0.tgz", - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "from": "assert-plus@^1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" - } - } - }, - "jsbn": { - "version": "0.1.0", - "from": "jsbn@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz" - }, - "tweetnacl": { - "version": "0.14.3", - "from": "tweetnacl@>=0.13.0 <1.0.0", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz" - }, - "jodid25519": { - "version": "1.0.2", - "from": "jodid25519@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz" - }, - "ecc-jsbn": { - "version": "0.1.1", - "from": "ecc-jsbn@>=0.0.1 <1.0.0", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" - } - } - } - } - }, - "is-typedarray": { - "version": "1.0.0", - "from": "is-typedarray@~1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" - }, - "isstream": { - "version": "0.1.2", - "from": "isstream@~0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" - }, - "json-stringify-safe": { - "version": "5.0.1", - "from": "json-stringify-safe@~5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" - }, - "mime-types": { - "version": "2.1.10", - "from": "mime-types@~2.1.7", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.10.tgz", - "dependencies": { - "mime-db": { - "version": "1.22.0", - "from": "mime-db@~1.22.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.22.0.tgz" - } - } - }, - "node-uuid": { - "version": "1.4.7", - "from": "node-uuid@~1.4.7", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz" - }, - "oauth-sign": { - "version": "0.8.1", - "from": "oauth-sign@~0.8.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.1.tgz" - }, - "qs": { - "version": "6.0.2", - "from": "qs@~6.0.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.0.2.tgz" - }, - "stringstream": { - "version": "0.0.5", - "from": "stringstream@~0.0.4", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz" - }, - "tough-cookie": { - "version": "2.2.2", - "from": "tough-cookie@~2.2.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz" - }, - "tunnel-agent": { - "version": "0.4.2", - "from": "tunnel-agent@~0.4.1", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.2.tgz" - } - } - }, - "semver": { - "version": "5.1.0", - "from": "semver@~5.1.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.0.tgz" - }, - "tar": { - "version": "2.2.1", - "from": "tar@~2.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "dependencies": { - "block-stream": { - "version": "0.0.8", - "from": "block-stream@*", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.8.tgz" - }, - "fstream": { - "version": "1.0.8", - "from": "fstream@^1.0.2", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.8.tgz", - "dependencies": { - "graceful-fs": { - "version": "4.1.3", - "from": "graceful-fs@^4.1.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.3.tgz" - } - } - }, - "inherits": { - "version": "2.0.1", - "from": "inherits@2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - } - } - }, - "tar-pack": { - "version": "3.1.3", - "from": "tar-pack@~3.1.0", - "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.1.3.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "dependencies": { - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "fstream": { - "version": "1.0.8", - "from": "fstream@~1.0.8", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.8.tgz", - "dependencies": { - "graceful-fs": { - "version": "4.1.3", - "from": "graceful-fs@^4.1.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.3.tgz" - }, - "inherits": { - "version": "2.0.1", - "from": "inherits@~2.0.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - } - } - }, - "fstream-ignore": { - "version": "1.0.3", - "from": "fstream-ignore@~1.0.3", - "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.3.tgz", - "dependencies": { - "inherits": { - "version": "2.0.1", - "from": "inherits@2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, - "minimatch": { - "version": "3.0.0", - "from": "minimatch@^3.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.0.tgz", - "dependencies": { - "brace-expansion": { - "version": "1.1.3", - "from": "brace-expansion@^1.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.3.tgz", - "dependencies": { - "balanced-match": { - "version": "0.3.0", - "from": "balanced-match@^0.3.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.3.0.tgz" - }, - "concat-map": { - "version": "0.0.1", - "from": "concat-map@0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - } - } - } - } - } - } - }, - "once": { - "version": "1.3.3", - "from": "once@~1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "dependencies": { - "wrappy": { - "version": "1.0.1", - "from": "wrappy@1", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" - } - } - }, - "readable-stream": { - "version": "2.0.6", - "from": "readable-stream@~2.0.4", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "from": "core-util-is@~1.0.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, - "inherits": { - "version": "2.0.1", - "from": "inherits@~2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, - "isarray": { - "version": "1.0.0", - "from": "isarray@~1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "process-nextick-args": { - "version": "1.0.6", - "from": "process-nextick-args@~1.0.6", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@~0.10.x", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "util-deprecate": { - "version": "1.0.2", - "from": "util-deprecate@~1.0.1", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } - } - }, - "uid-number": { - "version": "0.0.6", - "from": "uid-number@~0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz" - } - } - }, - "mkdirp": { - "version": "0.5.1", - "from": "mkdirp@~0.5.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "dependencies": { - "minimist": { - "version": "0.0.8", - "from": "minimist@0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" - } - } - }, - "rc": { - "version": "1.1.6", - "from": "rc@~1.1.0", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.1.6.tgz", - "dependencies": { - "deep-extend": { - "version": "0.4.1", - "from": "deep-extend@~0.4.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz" - }, - "ini": { - "version": "1.3.4", - "from": "ini@~1.3.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz" - }, - "minimist": { - "version": "1.2.0", - "from": "minimist@^1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" - }, - "strip-json-comments": { - "version": "1.0.4", - "from": "strip-json-comments@~1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz" - } - } - }, - "rimraf": { - "version": "2.5.2", - "from": "rimraf@~2.5.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.2.tgz", - "dependencies": { - "glob": { - "version": "7.0.3", - "from": "glob@^7.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz", - "dependencies": { - "inflight": { - "version": "1.0.4", - "from": "inflight@^1.0.4", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", - "dependencies": { - "wrappy": { - "version": "1.0.1", - "from": "wrappy@1", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" - } - } - }, - "inherits": { - "version": "2.0.1", - "from": "inherits@2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, - "minimatch": { - "version": "3.0.0", - "from": "minimatch@2 || 3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.0.tgz", - "dependencies": { - "brace-expansion": { - "version": "1.1.3", - "from": "brace-expansion@^1.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.3.tgz", - "dependencies": { - "balanced-match": { - "version": "0.3.0", - "from": "balanced-match@^0.3.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.3.0.tgz" - }, - "concat-map": { - "version": "0.0.1", - "from": "concat-map@0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - } - } - } - } - }, - "once": { - "version": "1.3.3", - "from": "once@^1.3.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "dependencies": { - "wrappy": { - "version": "1.0.1", - "from": "wrappy@1", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" - } - } - }, - "path-is-absolute": { - "version": "1.0.0", - "from": "path-is-absolute@^1.0.0", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" - } - } - } - } + "readable-stream": { + "version": "2.0.6", + "from": "readable-stream@>=2.0.5 <2.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" + } + } + }, + "dashdash": { + "version": "1.13.1", + "from": "dashdash@>=1.12.0 <2.0.0", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.13.1.tgz", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + } + } + }, + "getpass": { + "version": "0.1.6", + "from": "getpass@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + } + } + }, + "rc": { + "version": "1.1.6", + "from": "rc@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.1.6.tgz", + "dependencies": { + "minimist": { + "version": "1.2.0", + "from": "minimist@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" + } + } + }, + "sshpk": { + "version": "1.8.3", + "from": "sshpk@>=1.7.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.8.3.tgz", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + } + } + }, + "tar-pack": { + "version": "3.1.3", + "from": "tar-pack@>=3.1.0 <3.2.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.1.3.tgz", + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "from": "readable-stream@>=2.0.4 <2.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" } } } diff --git a/package.json b/package.json index 0829613f..5ce84b37 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "windshaft-cartodb", - "version": "2.42.0", + "version": "2.42.3", "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.8.0", + "turbo-carto": "0.9.2", "underscore": "~1.6.0", "windshaft": "1.19.0" }, diff --git a/test/acceptance/analysis/named-maps.js b/test/acceptance/analysis/named-maps.js index 13d84120..26341a0a 100644 --- a/test/acceptance/analysis/named-maps.js +++ b/test/acceptance/analysis/named-maps.js @@ -1,11 +1,11 @@ var assert = require('../../support/assert'); -var step = require('step'); var helper = require('../../support/test_helper'); var CartodbWindshaft = require('../../../lib/cartodb/server'); var serverOptions = require('../../../lib/cartodb/server_options'); var server = new CartodbWindshaft(serverOptions); +var TestClient = require('../../support/test-client'); var LayergroupToken = require('../../../lib/cartodb/models/layergroup_token'); @@ -16,230 +16,259 @@ describe('named-maps analysis', function() { var username = 'localhost'; var widgetsTemplateName = 'widgets-template'; - var layergroupid; - var layergroup; - var keysToDelete; - - beforeEach(function(done) { - keysToDelete = {}; - - var widgetsTemplate = { - version: '0.0.1', - name: widgetsTemplateName, - layergroup: { - version: '1.5.0', - layers: [ - { - "type": "cartodb", - "options": { - "source": { - "id": "HEAD" - }, - "cartocss": '#buffer { polygon-fill: red; }', - "cartocss_version": "2.3.0" - } - } - ], - dataviews: { - pop_max_histogram: { - source: { - id: 'HEAD' + var widgetsTemplate = { + version: '0.0.1', + name: widgetsTemplateName, + layergroup: { + version: '1.5.0', + layers: [ + { + "type": "cartodb", + "options": { + "source": { + "id": "HEAD" }, - type: 'histogram', - options: { - column: 'pop_max' - } + "cartocss": '#buffer { polygon-fill: red; }', + "cartocss_version": "2.3.0" } - }, - analyses: [ - { - "id": "HEAD", - "type": "buffer", - "params": { - "source": { - "id": "2570e105-7b37-40d2-bdf4-1af889598745", - "type": "source", - "params": { - "query": "select * from populated_places_simple_reduced" - } - }, - "radius": 50000 - } + } + ], + dataviews: { + pop_max_histogram: { + source: { + id: 'HEAD' + }, + type: 'histogram', + options: { + column: 'pop_max' } - ] - } - }; - - var template_params = {}; - - step( - function createTemplate() - { - var next = this; - assert.response( - server, - { - url: '/api/v1/map/named?api_key=1234', - method: 'POST', - headers: { - host: username, - 'Content-Type': 'application/json' + } + }, + analyses: [ + { + "id": "HEAD", + "type": "buffer", + "params": { + "source": { + "id": "2570e105-7b37-40d2-bdf4-1af889598745", + "type": "source", + "params": { + "query": "select * from populated_places_simple_reduced" + } }, - data: JSON.stringify(widgetsTemplate) - }, - { - status: 200 - }, - function(res, err) { - next(err, res); + "radius": 50000 } - ); - }, - function instantiateTemplate(err, res) { - assert.ifError(err); + } + ] + } + }; - assert.deepEqual(JSON.parse(res.body), { template_id: widgetsTemplateName }); - var next = this; - assert.response( - server, - { - url: '/api/v1/map/named/' + widgetsTemplateName, - method: 'POST', - headers: { - host: username, - 'Content-Type': 'application/json' - }, - data: JSON.stringify(template_params) - }, - { - status: 200 - }, - function(res) { - next(null, res); - } - ); - }, - function finish(err, res) { - assert.ifError(err); - - layergroup = JSON.parse(res.body); - assert.ok(layergroup.hasOwnProperty('layergroupid'), "Missing 'layergroupid' from: " + res.body); - layergroupid = layergroup.layergroupid; - - assert.ok( - Array.isArray(layergroup.metadata.analyses), - 'Missing "analyses" array metadata from: ' + res.body - ); - var analyses = layergroup.metadata.analyses; - assert.equal(analyses.length, 1, 'Invalid number of analyses in metadata'); - var nodes = analyses[0].nodes; - var nodesIds = Object.keys(nodes); - assert.deepEqual(nodesIds, ['2570e105-7b37-40d2-bdf4-1af889598745', 'HEAD']); - nodesIds.forEach(function(nodeId) { - var node = nodes[nodeId]; - assert.ok(node.hasOwnProperty('url'), 'Missing "url" attribute in node'); - assert.ok(node.hasOwnProperty('status'), 'Missing "status" attribute in node'); - assert.ok(!node.hasOwnProperty('query'), 'Unexpected "query" attribute in node'); - }); - - keysToDelete['map_cfg|' + LayergroupToken.parse(layergroup.layergroupid).token] = 0; - keysToDelete['user:localhost:mapviews:global'] = 5; - - return done(); - } - ); - - }); - - afterEach(function(done) { - step( - function deleteTemplate(err) { - assert.ifError(err); - var next = this; - assert.response( - server, - { - url: '/api/v1/map/named/' + widgetsTemplateName + '?api_key=1234', - method: 'DELETE', - headers: { - host: username - } - }, - { - status: 204 - }, - function(res, err) { - next(err, res); - } - ); - }, - function deleteRedisKeys(err) { - assert.ifError(err); - helper.deleteRedisKeys(keysToDelete, done); - } - ); - }); - - it('should be able to retrieve images from analysis', function(done) { + beforeEach(function createTemplate(done) { assert.response( server, { - url: '/api/v1/map/' + layergroupid + '/6/31/24.png', - method: 'GET', - encoding: 'binary', + url: '/api/v1/map/named?api_key=1234', + method: 'POST', + headers: { + host: username, + 'Content-Type': 'application/json' + }, + data: JSON.stringify(widgetsTemplate) + }, + { + status: 200 + }, + function(res, err) { + assert.deepEqual(JSON.parse(res.body), { template_id: widgetsTemplateName }); + return done(err); + } + ); + }); + + afterEach(function deleteTemplate(done) { + assert.response( + server, + { + url: '/api/v1/map/named/' + widgetsTemplateName + '?api_key=1234', + method: 'DELETE', headers: { host: username } }, { - status: 200, - headers: { - 'Content-Type': 'image/png' - } + status: 204 }, function(res, err) { - if (err) { - return done(err); - } + return done(err); + } + ); + }); - var fixturePath = './test/fixtures/analysis/named-map-buffer.png'; - assert.imageBufferIsSimilarToFile(res.body, fixturePath, IMAGE_TOLERANCE_PER_MIL, function(err) { + describe('layergroup', function() { + var layergroupid; + var layergroup; + var keysToDelete; + + beforeEach(function(done) { + keysToDelete = {}; + + assert.response( + server, + { + url: '/api/v1/map/named/' + widgetsTemplateName, + method: 'POST', + headers: { + host: username, + 'Content-Type': 'application/json' + }, + data: JSON.stringify({}) + }, + { + status: 200 + }, + function(res, err) { + assert.ifError(err); + + layergroup = JSON.parse(res.body); + assert.ok(layergroup.hasOwnProperty('layergroupid'), "Missing 'layergroupid' from: " + res.body); + layergroupid = layergroup.layergroupid; + + assert.ok( + Array.isArray(layergroup.metadata.analyses), + 'Missing "analyses" array metadata from: ' + res.body + ); + var analyses = layergroup.metadata.analyses; + assert.equal(analyses.length, 1, 'Invalid number of analyses in metadata'); + var nodes = analyses[0].nodes; + var nodesIds = Object.keys(nodes); + assert.deepEqual(nodesIds, ['2570e105-7b37-40d2-bdf4-1af889598745', 'HEAD']); + nodesIds.forEach(function(nodeId) { + var node = nodes[nodeId]; + assert.ok(node.hasOwnProperty('url'), 'Missing "url" attribute in node'); + assert.ok(node.hasOwnProperty('status'), 'Missing "status" attribute in node'); + assert.ok(!node.hasOwnProperty('query'), 'Unexpected "query" attribute in node'); + }); + + keysToDelete['map_cfg|' + LayergroupToken.parse(layergroup.layergroupid).token] = 0; + keysToDelete['user:localhost:mapviews:global'] = 5; + + return done(); + } + ); + + }); + + afterEach(function(done) { + helper.deleteRedisKeys(keysToDelete, done); + }); + + it('should be able to retrieve images from analysis', function(done) { + assert.response( + server, + { + url: '/api/v1/map/' + layergroupid + '/6/31/24.png', + method: 'GET', + encoding: 'binary', + headers: { + host: username + } + }, + { + status: 200, + headers: { + 'Content-Type': 'image/png' + } + }, + function(res, err) { + if (err) { + return done(err); + } + + var fixturePath = './test/fixtures/analysis/named-map-buffer.png'; + assert.imageBufferIsSimilarToFile(res.body, fixturePath, IMAGE_TOLERANCE_PER_MIL, function(err) { + assert.ok(!err, err); + done(); + }); + + } + ); + }); + + it('should be able to retrieve dataviews from analysis', function(done) { + assert.response( + server, + { + url: '/api/v1/map/' + layergroupid + '/dataview/pop_max_histogram', + method: 'GET', + headers: { + host: username + } + }, + { + status: 200, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + } + }, + function(res, err) { + if (err) { + return done(err); + } + + var dataview = JSON.parse(res.body); + assert.equal(dataview.type, 'histogram'); + assert.equal(dataview.bins_start, 0); + + done(); + } + ); + }); + + it('should be able to retrieve static map preview via layergroup', function(done) { + assert.response( + server, + { + url: '/api/v1/map/static/center/' + layergroupid + '/4/42/-3/320/240.png', + method: 'GET', + encoding: 'binary', + headers: { + host: username + } + }, + { + status: 200, + headers: { + 'Content-Type': 'image/png' + } + }, + function(res, err) { + if (err) { + return done(err); + } + + var fixturePath = './test/fixtures/analysis/named-map-buffer-layergroup-static-preview.png'; + assert.imageBufferIsSimilarToFile(res.body, fixturePath, IMAGE_TOLERANCE_PER_MIL, function(err) { + assert.ok(!err, err); + done(); + }); + + } + ); + }); + + }); + + describe('auto-instantiation', function() { + it('should be able to retrieve static map preview via fixed url', function(done) { + TestClient.getStaticMap(widgetsTemplateName, function(err, image) { + assert.ok(!err, err); + var fixturePath = './test/fixtures/analysis/named-map-buffer-static-preview.png'; + assert.imageIsSimilarToFile(image, fixturePath, IMAGE_TOLERANCE_PER_MIL, function(err) { assert.ok(!err, err); done(); }); - - } - ); - }); - - it('should be able to retrieve dataviews from analysis', function(done) { - assert.response( - server, - { - url: '/api/v1/map/' + layergroupid + '/dataview/pop_max_histogram', - method: 'GET', - headers: { - host: username - } - }, - { - status: 200, - headers: { - 'Content-Type': 'application/json; charset=utf-8' - } - }, - function(res, err) { - if (err) { - return done(err); - } - - var dataview = JSON.parse(res.body); - assert.equal(dataview.type, 'histogram'); - assert.equal(dataview.bins_start, 0); - - done(); - } - ); + }); + }); }); }); diff --git a/test/acceptance/turbo-cartocss/error-cases.js b/test/acceptance/turbo-cartocss/error-cases.js new file mode 100644 index 00000000..f43a3636 --- /dev/null +++ b/test/acceptance/turbo-cartocss/error-cases.js @@ -0,0 +1,94 @@ +require('../../support/test_helper'); + +var assert = require('../../support/assert'); +var TestClient = require('../../support/test-client'); + +function makeMapconfig(markerWidth, markerFill) { + return { + "version": "1.4.0", + "layers": [ + { + "type": 'mapnik', + "options": { + "cartocss_version": '2.3.0', + "sql": 'SELECT * FROM populated_places_simple_reduced', + "cartocss": createCartocss(markerWidth, markerFill) + } + } + ] + }; +} + +function createCartocss(markerWidth, markerFill) { + return [ + "#populated_places_simple_reduced {", + " marker-fill-opacity: 0.9;", + " marker-line-color: #FFF;", + " marker-line-width: 1;", + " marker-line-opacity: 1;", + " marker-placement: point;", + " marker-type: ellipse;", + " marker-allow-overlap: true;", + " marker-width: " + (markerWidth || '10') + ";", + " marker-fill: " + (markerFill || 'red') + ";", + "}" + ].join('\n'); +} + +var ERROR_RESPONSE = { + status: 400, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + } +}; + +describe('turbo-carto error cases', function() { + afterEach(function (done) { + if (this.testClient) { + this.testClient.drain(done); + } + }); + + it('should return invalid number of ramp error', function(done) { + this.testClient = new TestClient(makeMapconfig('ramp([pop_max], (8,24,96), (8,24,96,128))')); + this.testClient.getLayergroup(ERROR_RESPONSE, function(err, layergroup) { + assert.ok(!err, err); + + assert.ok(layergroup.hasOwnProperty('errors')); + assert.equal(layergroup.errors.length, 1); + assert.ok(layergroup.errors[0].match(/^turbo-carto/)); + assert.ok(layergroup.errors[0].match(/invalid\sramp\slength/i)); + + done(); + }); + }); + + it('should return invalid column from datasource', function(done) { + this.testClient = new TestClient(makeMapconfig(null, 'ramp([wadus_column], (red, green, blue))')); + this.testClient.getLayergroup(ERROR_RESPONSE, function(err, layergroup) { + assert.ok(!err, err); + + assert.ok(layergroup.hasOwnProperty('errors')); + assert.equal(layergroup.errors.length, 1); + assert.ok(layergroup.errors[0].match(/^turbo-carto/)); + assert.ok(layergroup.errors[0].match(/unable\sto\scompute\sramp/i)); + assert.ok(layergroup.errors[0].match(/wadus_column/)); + + done(); + }); + }); + + it('should fail by falling back to normal carto parser', function(done) { + this.testClient = new TestClient(makeMapconfig('ramp([price], (8,24,96), (8,24,96));//(red, green, blue))')); + this.testClient.getLayergroup(ERROR_RESPONSE, function(err, layergroup) { + assert.ok(!err, err); + + assert.ok(layergroup.hasOwnProperty('errors')); + assert.equal(layergroup.errors.length, 1); + assert.ok(!layergroup.errors[0].match(/^turbo-carto/)); + assert.ok(layergroup.errors[0].match(/invalid\scode/i)); + + done(); + }); + }); +}); diff --git a/test/acceptance/turbo-cartocss/regressions.js b/test/acceptance/turbo-cartocss/regressions.js index c55009d5..4f152da3 100644 --- a/test/acceptance/turbo-cartocss/regressions.js +++ b/test/acceptance/turbo-cartocss/regressions.js @@ -3,7 +3,7 @@ require('../../support/test_helper'); var assert = require('../../support/assert'); var TestClient = require('../../support/test-client'); -function makeMapconfig(cartocss) { +function makeMapconfig(sql, cartocss) { return { "version": "1.4.0", "layers": [ @@ -11,19 +11,7 @@ function makeMapconfig(cartocss) { "type": 'mapnik', "options": { "cartocss_version": '2.3.0', - "sql": [ - 'SELECT test_table.*, _prices.price FROM test_table JOIN (' + - ' SELECT 1 AS cartodb_id, 10.00 AS price', - ' UNION', - ' SELECT 2, 10.50', - ' UNION', - ' SELECT 3, 11.00', - ' UNION', - ' SELECT 4, 12.00', - ' UNION', - ' SELECT 5, 21.00', - ') _prices ON _prices.cartodb_id = test_table.cartodb_id' - ].join('\n'), + "sql": sql, "cartocss": cartocss } } @@ -33,42 +21,84 @@ function makeMapconfig(cartocss) { describe('turbo-carto regressions', function() { - var cartocss = [ - "/** simple visualization */", - "", - "Map {", - " buffer-size: 256;", - "}", - "", - "#county_points_with_population{", - " marker-fill-opacity: 0.1;", - " marker-line-color:#FFFFFF;//#CF1C90;", - " marker-line-width: 0;", - " marker-line-opacity: 0.3;", - " marker-placement: point;", - " marker-type: ellipse;", - " //marker-comp-op: overlay;", - " marker-width: [price];", - " [zoom=5]{marker-width: [price]*2;}", - " [zoom=6]{marker-width: [price]*4;}", - " marker-fill: #000000;", - " marker-allow-overlap: true;", - " ", - "", - "}" - ].join('\n'); - - beforeEach(function () { - this.testClient = new TestClient(makeMapconfig(cartocss)); - }); - afterEach(function (done) { - this.testClient.drain(done); + if (this.testClient) { + this.testClient.drain(done); + } }); it('should accept // comments', function(done) { - this.testClient.getTile(0, 0, 0, function(err) { + var cartocss = [ + "/** simple visualization */", + "", + "Map {", + " buffer-size: 256;", + "}", + "", + "#county_points_with_population{", + " marker-fill-opacity: 0.1;", + " marker-line-color:#FFFFFF;//#CF1C90;", + " marker-line-width: 0;", + " marker-line-opacity: 0.3;", + " marker-placement: point;", + " marker-type: ellipse;", + " //marker-comp-op: overlay;", + " marker-width: [cartodb_id];", + " [zoom=5]{marker-width: [cartodb_id]*2;}", + " [zoom=6]{marker-width: [cartodb_id]*4;}", + " marker-fill: #000000;", + " marker-allow-overlap: true;", + " ", + "", + "}" + ].join('\n'); + + this.testClient = new TestClient(makeMapconfig('SELECT * FROM populated_places_simple_reduced', cartocss)); + this.testClient.getLayergroup(function(err, layergroup) { assert.ok(!err, err); + + assert.ok(layergroup.hasOwnProperty('layergroupid')); + assert.ok(!layergroup.hasOwnProperty('errors')); + + done(); + }); + }); + + it('should work with mapnik substitution tokens', function(done) { + var cartocss = [ + "#layer {", + " line-width: 2;", + " line-color: #3B3B58;", + " line-opacity: 1;", + " polygon-opacity: 0.7;", + " polygon-fill: ramp([points_count], (#E5F5F9,#99D8C9,#2CA25F))", + "}" + ].join('\n'); + + var sql = [ + 'WITH hgrid AS (', + ' SELECT CDB_HexagonGrid(', + ' ST_Expand(!bbox!, greatest(!pixel_width!,!pixel_height!) * 100),', + ' greatest(!pixel_width!,!pixel_height!) * 100', + ' ) as cell', + ')', + 'SELECT', + ' hgrid.cell as the_geom_webmercator,', + ' count(1) as points_count,', + ' count(1)/power(100 * CDB_XYZ_Resolution(CDB_ZoomFromScale(!scale_denominator!)), 2) as points_density,', + ' 1 as cartodb_id', + 'FROM hgrid, (SELECT * FROM populated_places_simple_reduced) i', + 'where ST_Intersects(i.the_geom_webmercator, hgrid.cell)', + 'GROUP BY hgrid.cell' + ].join('\n'); + + this.testClient = new TestClient(makeMapconfig(sql, cartocss)); + this.testClient.getLayergroup(function(err, layergroup) { + assert.ok(!err, err); + + assert.ok(layergroup.hasOwnProperty('layergroupid')); + assert.ok(!layergroup.hasOwnProperty('errors')); + done(); }); }); diff --git a/test/fixtures/analysis/named-map-buffer-layergroup-static-preview.png b/test/fixtures/analysis/named-map-buffer-layergroup-static-preview.png new file mode 100644 index 00000000..deb0b60c Binary files /dev/null and b/test/fixtures/analysis/named-map-buffer-layergroup-static-preview.png differ diff --git a/test/fixtures/analysis/named-map-buffer-static-preview.png b/test/fixtures/analysis/named-map-buffer-static-preview.png new file mode 100644 index 00000000..d57b3a2a Binary files /dev/null and b/test/fixtures/analysis/named-map-buffer-static-preview.png differ diff --git a/test/support/prepare_db.sh b/test/support/prepare_db.sh index 928272fd..ceac7c78 100755 --- a/test/support/prepare_db.sh +++ b/test/support/prepare_db.sh @@ -83,7 +83,7 @@ if test x"$PREPARE_PGSQL" = xyes; then cat sql/_CDB_QueryStatements.sql | psql -v ON_ERROR_STOP=1 ${TEST_DB} || exit 1 - SQL_SCRIPTS='CDB_QueryTables CDB_CartodbfyTable CDB_TableMetadata CDB_ForeignTable CDB_UserTables CDB_ColumnNames CDB_ZoomFromScale CDB_Overviews CDB_QuantileBins CDB_JenksBins CDB_HeadsTailsBins CDB_EqualIntervalBins' + SQL_SCRIPTS='CDB_QueryTables CDB_CartodbfyTable CDB_TableMetadata CDB_ForeignTable CDB_UserTables CDB_ColumnNames CDB_ZoomFromScale CDB_Overviews CDB_QuantileBins CDB_JenksBins CDB_HeadsTailsBins CDB_EqualIntervalBins CDB_Hexagon CDB_XYZ' for i in ${SQL_SCRIPTS} do curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/master/scripts-available/$i.sql -o sql/$i.sql diff --git a/test/support/test-client.js b/test/support/test-client.js index 5ced9f98..a9ec5bee 100644 --- a/test/support/test-client.js +++ b/test/support/test-client.js @@ -471,3 +471,41 @@ TestClient.prototype.getNodeStatus = function(nodeName, callback) { TestClient.prototype.drain = function(callback) { helper.deleteRedisKeys(this.keysToDelete, callback); }; + +module.exports.getStaticMap = function getStaticMap(templateName, params, callback) { + if (!callback) { + callback = params; + params = null; + } + + var url = '/api/v1/map/static/named/' + templateName + '/640/480.png'; + + if (params !== null) { + url += '?' + qs.stringify(params); + } + + var requestOptions = { + url: url, + method: 'GET', + headers: { + host: 'localhost' + }, + encoding: 'binary' + }; + + var expectedResponse = { + status: 200, + headers: { + 'Content-Type': 'image/png' + } + }; + + // this could be removed once named maps are invalidated, otherwise you hits the cache + var server = new CartodbWindshaft(serverOptions); + + assert.response(server, requestOptions, expectedResponse, function (res, err) { + helper.deleteRedisKeys({'user:localhost:mapviews:global': 5}, function() { + return callback(err, mapnik.Image.fromBytes(new Buffer(res.body, 'binary'))); + }); + }); +};