Merge pull request #485 from CartoDB/mapconfig-dataviews-adapter
Mapconfig dataviews adapter
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
Released 2016-mm-dd
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [2.0.1](https://github.com/CartoDB/camshaft/releases/tag/2.0.1 )
|
||||
- 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)
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ var QueryTables = require('cartodb-query-tables');
|
||||
* @param {TileBackend} tileBackend
|
||||
* @param {PreviewBackend} previewBackend
|
||||
* @param {AttributesBackend} attributesBackend
|
||||
* @param {WidgetBackend} widgetBackend
|
||||
* @param {SurrogateKeysCache} surrogateKeysCache
|
||||
* @param {UserLimitsApi} userLimitsApi
|
||||
* @param {LayergroupAffectedTables} layergroupAffectedTables
|
||||
@@ -29,7 +28,7 @@ var QueryTables = require('cartodb-query-tables');
|
||||
* @constructor
|
||||
*/
|
||||
function LayergroupController(authApi, pgConnection, mapStore, tileBackend, previewBackend, attributesBackend,
|
||||
widgetBackend, surrogateKeysCache, userLimitsApi, layergroupAffectedTables, analysisBackend) {
|
||||
surrogateKeysCache, userLimitsApi, layergroupAffectedTables, analysisBackend) {
|
||||
BaseController.call(this, authApi, pgConnection);
|
||||
|
||||
this.pgConnection = pgConnection;
|
||||
@@ -37,7 +36,6 @@ function LayergroupController(authApi, pgConnection, mapStore, tileBackend, prev
|
||||
this.tileBackend = tileBackend;
|
||||
this.previewBackend = previewBackend;
|
||||
this.attributesBackend = attributesBackend;
|
||||
this.widgetBackend = widgetBackend;
|
||||
this.surrogateKeysCache = surrogateKeysCache;
|
||||
this.userLimitsApi = userLimitsApi;
|
||||
this.layergroupAffectedTables = layergroupAffectedTables;
|
||||
@@ -78,21 +76,19 @@ LayergroupController.prototype.register = function(app) {
|
||||
|
||||
// Undocumented/non-supported API endpoint methods.
|
||||
// Use at your own peril.
|
||||
app.get(app.base_url_mapconfig +
|
||||
'/:token/:layer/widget/:widgetName', cors(), userMiddleware,
|
||||
this.widget.bind(this));
|
||||
|
||||
app.get(app.base_url_mapconfig +
|
||||
'/:token/:layer/widget/:widgetName/search', cors(), userMiddleware,
|
||||
this.widgetSearch.bind(this));
|
||||
|
||||
app.get(app.base_url_mapconfig +
|
||||
'/:token/dataview/:dataviewName', cors(), userMiddleware,
|
||||
this.dataview.bind(this));
|
||||
app.get(app.base_url_mapconfig +
|
||||
'/:token/:layer/widget/:dataviewName', cors(), userMiddleware,
|
||||
this.dataview.bind(this));
|
||||
|
||||
app.get(app.base_url_mapconfig +
|
||||
'/:token/dataview/:dataviewName/search', cors(), userMiddleware,
|
||||
this.dataviewSearch.bind(this));
|
||||
app.get(app.base_url_mapconfig +
|
||||
'/:token/:layer/widget/:dataviewName/search', cors(), userMiddleware,
|
||||
this.dataviewSearch.bind(this));
|
||||
|
||||
app.get(app.base_url_mapconfig +
|
||||
'/:token/analysis/node/:nodeId', cors(), userMiddleware,
|
||||
@@ -181,62 +177,6 @@ LayergroupController.prototype.dataviewSearch = function(req, res) {
|
||||
|
||||
};
|
||||
|
||||
LayergroupController.prototype.widget = function(req, res) {
|
||||
var self = this;
|
||||
|
||||
step(
|
||||
function setupParams() {
|
||||
self.req2params(req, this);
|
||||
},
|
||||
function retrieveList(err) {
|
||||
assert.ifError(err);
|
||||
|
||||
var mapConfigProvider = new MapStoreMapConfigProvider(
|
||||
self.mapStore, req.context.user, self.userLimitsApi, req.params
|
||||
);
|
||||
self.widgetBackend.getWidget(mapConfigProvider, req.params, this);
|
||||
},
|
||||
function finish(err, widget, stats) {
|
||||
req.profiler.add(stats || {});
|
||||
|
||||
if (err) {
|
||||
self.sendError(req, res, err, 'GET WIDGET');
|
||||
} else {
|
||||
self.sendResponse(req, res, widget, 200);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
LayergroupController.prototype.widgetSearch = function(req, res) {
|
||||
var self = this;
|
||||
|
||||
step(
|
||||
function setupParams() {
|
||||
self.req2params(req, this);
|
||||
},
|
||||
function retrieveList(err) {
|
||||
assert.ifError(err);
|
||||
|
||||
var mapConfigProvider = new MapStoreMapConfigProvider(
|
||||
self.mapStore, req.context.user, self.userLimitsApi, req.params
|
||||
);
|
||||
self.widgetBackend.search(mapConfigProvider, req.params, this);
|
||||
},
|
||||
function finish(err, searchResult, stats) {
|
||||
req.profiler.add(stats || {});
|
||||
|
||||
if (err) {
|
||||
self.sendError(req, res, err, 'GET WIDGET');
|
||||
} else {
|
||||
self.sendResponse(req, res, searchResult, 200);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
LayergroupController.prototype.attributes = function(req, res) {
|
||||
var self = this;
|
||||
|
||||
|
||||
@@ -161,15 +161,15 @@ MapController.prototype.create = function(req, res, prepareConfigFn) {
|
||||
},
|
||||
function afterLayergroupCreate(err, layergroup) {
|
||||
assert.ifError(err);
|
||||
var analysesResults = context.analysesResults || [];
|
||||
self.afterLayergroupCreate(req, res, mapConfig, analysesResults, layergroup, this);
|
||||
self.afterLayergroupCreate(req, res, mapConfig, layergroup, this);
|
||||
},
|
||||
function finish(err, layergroup) {
|
||||
if (err) {
|
||||
self.sendError(req, res, err, 'ANONYMOUS LAYERGROUP');
|
||||
} else {
|
||||
addWidgetsUrl(req.context.user, layergroup);
|
||||
|
||||
var analysesResults = context.analysesResults || [];
|
||||
addDataviewsAndWidgetsUrls(req.context.user, layergroup, mapConfig.obj());
|
||||
addAnalysesMetadata(req.context.user, layergroup, analysesResults, true);
|
||||
res.set('X-Layergroup-Id', layergroup.layergroupid);
|
||||
self.send(req, res, layergroup, 200);
|
||||
}
|
||||
@@ -219,7 +219,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
|
||||
},
|
||||
function afterLayergroupCreate(err, layergroup) {
|
||||
assert.ifError(err);
|
||||
self.afterLayergroupCreate(req, res, mapConfig, [], layergroup, this);
|
||||
self.afterLayergroupCreate(req, res, mapConfig, layergroup, this);
|
||||
},
|
||||
function finishTemplateInstantiation(err, layergroup) {
|
||||
if (err) {
|
||||
@@ -228,8 +228,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
|
||||
var templateHash = self.templateMaps.fingerPrint(mapConfigProvider.template).substring(0, 8);
|
||||
layergroup.layergroupid = cdbuser + '@' + templateHash + '@' + layergroup.layergroupid;
|
||||
|
||||
addWidgetsUrl(cdbuser, layergroup);
|
||||
addDataviewsUrls(cdbuser, layergroup, mapConfig.obj());
|
||||
addDataviewsAndWidgetsUrls(cdbuser, layergroup, mapConfig.obj());
|
||||
addAnalysesMetadata(cdbuser, layergroup, mapConfigProvider.analysesResults);
|
||||
|
||||
res.set('X-Layergroup-Id', layergroup.layergroupid);
|
||||
@@ -241,8 +240,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, analysesResults, layergroup, callback) {
|
||||
MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, layergroup, callback) {
|
||||
var self = this;
|
||||
|
||||
var username = req.context.user;
|
||||
@@ -305,10 +303,6 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, an
|
||||
layergroup.layergroupid = layergroup.layergroupid + ':' + result.getLastUpdatedAt();
|
||||
layergroup.last_updated = new Date(result.getLastUpdatedAt()).toISOString();
|
||||
|
||||
// TODO this should take into account several URL patterns
|
||||
addWidgetsUrl(username, layergroup);
|
||||
addDataviewsUrls(username, layergroup, mapconfig.obj());
|
||||
addAnalysesMetadata(username, layergroup, analysesResults, true);
|
||||
if (req.method === 'GET') {
|
||||
var ttl = global.environment.varnish.layergroupTtl || 86400;
|
||||
res.set('Cache-Control', 'public,max-age='+ttl+',must-revalidate');
|
||||
@@ -353,6 +347,12 @@ function addAnalysesMetadata(username, layergroup, analysesResults, includeQuery
|
||||
});
|
||||
}
|
||||
|
||||
// TODO this should take into account several URL patterns
|
||||
function addDataviewsAndWidgetsUrls(username, layergroup, mapConfig) {
|
||||
addDataviewsUrls(username, layergroup, mapConfig);
|
||||
addWidgetsUrl(username, layergroup, mapConfig);
|
||||
}
|
||||
|
||||
function addDataviewsUrls(username, layergroup, mapConfig) {
|
||||
layergroup.metadata.dataviews = layergroup.metadata.dataviews || {};
|
||||
var dataviews = mapConfig.dataviews || {};
|
||||
@@ -365,20 +365,23 @@ function addDataviewsUrls(username, layergroup, mapConfig) {
|
||||
});
|
||||
}
|
||||
|
||||
function addWidgetsUrl(username, layergroup) {
|
||||
|
||||
if (layergroup.metadata && Array.isArray(layergroup.metadata.layers)) {
|
||||
function addWidgetsUrl(username, layergroup, mapConfig) {
|
||||
if (layergroup.metadata && Array.isArray(layergroup.metadata.layers) && Array.isArray(mapConfig.layers)) {
|
||||
layergroup.metadata.layers = layergroup.metadata.layers.map(function(layer, layerIndex) {
|
||||
if (layer.widgets) {
|
||||
Object.keys(layer.widgets).forEach(function(widgetName) {
|
||||
var mapConfigLayer = mapConfig.layers[layerIndex];
|
||||
if (mapConfigLayer.options && mapConfigLayer.options.widgets) {
|
||||
layer.widgets = layer.widgets || {};
|
||||
Object.keys(mapConfigLayer.options.widgets).forEach(function(widgetName) {
|
||||
var resource = layergroup.layergroupid + '/' + layerIndex + '/widget/' + widgetName;
|
||||
layer.widgets[widgetName].url = getUrls(username, resource);
|
||||
layer.widgets[widgetName] = {
|
||||
type: mapConfigLayer.options.widgets[widgetName].type,
|
||||
url: getUrls(username, resource)
|
||||
};
|
||||
});
|
||||
}
|
||||
return layer;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getUrls(username, resource) {
|
||||
|
||||
@@ -102,7 +102,7 @@ Aggregation.prototype.constructor = Aggregation;
|
||||
|
||||
module.exports = Aggregation;
|
||||
|
||||
Aggregation.prototype.sql = function(psql, filters, override, callback) {
|
||||
Aggregation.prototype.sql = function(psql, override, callback) {
|
||||
if (!callback) {
|
||||
callback = override;
|
||||
override = {};
|
||||
|
||||
@@ -56,7 +56,7 @@ Formula.prototype.constructor = Formula;
|
||||
|
||||
module.exports = Formula;
|
||||
|
||||
Formula.prototype.sql = function(psql, filters, override, callback) {
|
||||
Formula.prototype.sql = function(psql, override, callback) {
|
||||
if (!callback) {
|
||||
callback = override;
|
||||
override = {};
|
||||
|
||||
@@ -34,7 +34,7 @@ List.prototype.constructor = List;
|
||||
|
||||
module.exports = List;
|
||||
|
||||
List.prototype.sql = function(psql, filters, override, callback) {
|
||||
List.prototype.sql = function(psql, override, callback) {
|
||||
if (!callback) {
|
||||
callback = override;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
function DataviewsWidgetsMapConfigAdapter() {
|
||||
}
|
||||
|
||||
module.exports = DataviewsWidgetsMapConfigAdapter;
|
||||
|
||||
|
||||
DataviewsWidgetsMapConfigAdapter.prototype.getMapConfig = function(user, requestMapConfig, params, context, callback) {
|
||||
if (!shouldAdapt(requestMapConfig)) {
|
||||
return callback(null, requestMapConfig);
|
||||
}
|
||||
|
||||
// prepare placeholders for new dataviews created from widgets
|
||||
requestMapConfig.analyses = requestMapConfig.analyses || [];
|
||||
requestMapConfig.dataviews = requestMapConfig.dataviews || {};
|
||||
|
||||
requestMapConfig.layers.forEach(function(layer, index) {
|
||||
var layerSourceId = getLayerSourceId(layer);
|
||||
var dataviewSourceId = layerSourceId || 'cdb-layer-source-' + index;
|
||||
// Append a new analysis if layer has no source id but sql.
|
||||
if (!layerSourceId) {
|
||||
requestMapConfig.analyses.push(
|
||||
{
|
||||
id: dataviewSourceId,
|
||||
type: 'source',
|
||||
params: {
|
||||
query: layer.options.sql
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
var source = { id: dataviewSourceId };
|
||||
var layerWidgets = layer.options.widgets;
|
||||
Object.keys(layerWidgets).forEach(function(widgetId) {
|
||||
var dataview = layerWidgets[widgetId];
|
||||
requestMapConfig.dataviews[widgetId] = {
|
||||
source: source,
|
||||
type: dataview.type,
|
||||
options: dataview.options
|
||||
};
|
||||
});
|
||||
|
||||
layer.options.source = source;
|
||||
|
||||
delete layer.options.sql;
|
||||
// don't delete widgets for now as it might be useful for old clients
|
||||
//delete layer.options.widgets;
|
||||
});
|
||||
|
||||
// filters have to be rewritten also
|
||||
var filters = getFilters(params);
|
||||
var layersFilters = filters.layers || [];
|
||||
filters.dataviews = filters.dataviews || {};
|
||||
|
||||
layersFilters.forEach(function(layerFilters) {
|
||||
Object.keys(layerFilters).forEach(function(filterName) {
|
||||
if (!filters.dataviews.hasOwnProperty(filterName)) {
|
||||
filters.dataviews[filterName] = layerFilters[filterName];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
delete filters.layers;
|
||||
|
||||
params.filters = JSON.stringify(filters);
|
||||
|
||||
return callback(null, requestMapConfig);
|
||||
};
|
||||
|
||||
function shouldAdapt(requestMapConfig) {
|
||||
// return false;
|
||||
return Array.isArray(requestMapConfig.layers) && requestMapConfig.layers.some(function hasWidgets(layer) {
|
||||
return layer.options && layer.options.widgets && Object.keys(layer.options.widgets).length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
function getLayerSourceId(layer) {
|
||||
return layer.options.source && layer.options.source.id;
|
||||
}
|
||||
|
||||
function getFilters(params) {
|
||||
var filters = {};
|
||||
if (params.filters) {
|
||||
try {
|
||||
filters = JSON.parse(params.filters);
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ MapConfigOverviewsAdapter.prototype.getMapConfig = function(user, requestMapConf
|
||||
layer = _.extend({}, layer);
|
||||
layer.options = _.extend({}, layer.options, { query_rewrite_data: query_rewrite_data });
|
||||
}
|
||||
done(err, layer);
|
||||
done(null, layer);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ var MapConfigNamedLayersAdapter = require('./models/mapconfig/adapter/mapconfig-
|
||||
var AnalysisMapConfigAdapter = require('./models/mapconfig/adapter/analysis-mapconfig-adapter');
|
||||
var MapConfigOverviewsAdapter = require('./models/mapconfig/adapter/mapconfig-overviews-adapter');
|
||||
var TurboCartoAdapter = require('./models/mapconfig/adapter/turbo-carto-adapter');
|
||||
var DataviewsWidgetsAdapter = require('./models/mapconfig/adapter/dataviews-widgets-adapter');
|
||||
var MapConfigAdapter = require('./models/mapconfig/adapter');
|
||||
|
||||
module.exports = function(serverOptions) {
|
||||
@@ -159,6 +160,7 @@ module.exports = function(serverOptions) {
|
||||
var mapConfigAdapter = new MapConfigAdapter(
|
||||
new MapConfigNamedLayersAdapter(templateMaps, pgConnection),
|
||||
new SqlWrapMapConfigAdapter(),
|
||||
new DataviewsWidgetsAdapter(),
|
||||
new AnalysisMapConfigAdapter(analysisBackend),
|
||||
new MapConfigOverviewsAdapter(overviewsMetadataApi, filterStatsApi),
|
||||
new TurboCartoAdapter(turboCartoParser)
|
||||
@@ -192,7 +194,6 @@ module.exports = function(serverOptions) {
|
||||
tileBackend,
|
||||
previewBackend,
|
||||
attributesBackend,
|
||||
new windshaft.backend.Widget(),
|
||||
surrogateKeysCache,
|
||||
userLimitsApi,
|
||||
layergroupAffectedTablesCache,
|
||||
|
||||
Generated
+148
-148
@@ -105,13 +105,13 @@
|
||||
}
|
||||
},
|
||||
"camshaft": {
|
||||
"version": "0.11.0",
|
||||
"from": "camshaft@0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/camshaft/-/camshaft-0.11.0.tgz",
|
||||
"version": "0.12.1",
|
||||
"from": "camshaft@0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/camshaft/-/camshaft-0.12.1.tgz",
|
||||
"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"
|
||||
},
|
||||
"request": {
|
||||
@@ -270,7 +270,7 @@
|
||||
},
|
||||
"is-my-json-valid": {
|
||||
"version": "2.13.1",
|
||||
"from": "is-my-json-valid@>=2.12.0 <3.0.0",
|
||||
"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",
|
||||
"dependencies": {
|
||||
"generate-function": {
|
||||
@@ -391,9 +391,9 @@
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.13.1",
|
||||
"version": "1.14.0",
|
||||
"from": "dashdash@>=1.12.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.13.1.tgz"
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz"
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.6",
|
||||
@@ -648,7 +648,7 @@
|
||||
"dependencies": {
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"from": "unpipe@>=1.0.0 <1.1.0",
|
||||
"from": "unpipe@1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz"
|
||||
}
|
||||
}
|
||||
@@ -804,7 +804,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": {
|
||||
@@ -1029,7 +1029,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": {
|
||||
@@ -1056,7 +1056,7 @@
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.2.2",
|
||||
"from": "tough-cookie@>=2.2.0 <2.3.0",
|
||||
"from": "tough-cookie@>=0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz"
|
||||
},
|
||||
"http-signature": {
|
||||
@@ -1152,7 +1152,7 @@
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"from": "chalk@>=1.1.1 <2.0.0",
|
||||
"from": "chalk@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
@@ -1318,14 +1318,14 @@
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz"
|
||||
},
|
||||
"windshaft": {
|
||||
"version": "1.19.0",
|
||||
"from": "windshaft@1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/windshaft/-/windshaft-1.19.0.tgz",
|
||||
"version": "2.0.1",
|
||||
"from": "windshaft@2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/windshaft/-/windshaft-2.0.1.tgz",
|
||||
"dependencies": {
|
||||
"abaculus": {
|
||||
"version": "1.1.0-cdb4",
|
||||
"from": "https://github.com/CartoDB/abaculus/tarball/1.1.0-cdb4",
|
||||
"resolved": "https://github.com/CartoDB/abaculus/tarball/1.1.0-cdb4"
|
||||
"version": "1.1.0-cdb5",
|
||||
"from": "https://github.com/CartoDB/abaculus/tarball/1.1.0-cdb5",
|
||||
"resolved": "https://github.com/CartoDB/abaculus/tarball/1.1.0-cdb5"
|
||||
},
|
||||
"canvas": {
|
||||
"version": "1.2.7-cdb1",
|
||||
@@ -2966,56 +2966,56 @@
|
||||
"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"
|
||||
},
|
||||
"ansi": {
|
||||
"version": "0.3.1",
|
||||
"from": "ansi@>=0.3.1 <0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.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-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"
|
||||
"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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.3",
|
||||
"from": "asn1@>=0.2.3 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.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"
|
||||
},
|
||||
"async": {
|
||||
"version": "1.5.2",
|
||||
"from": "async@>=1.5.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.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"
|
||||
},
|
||||
"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",
|
||||
@@ -3031,6 +3031,11 @@
|
||||
"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",
|
||||
@@ -3041,6 +3046,11 @@
|
||||
"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",
|
||||
@@ -3061,16 +3071,16 @@
|
||||
"from": "cryptiles@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.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"
|
||||
},
|
||||
"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",
|
||||
@@ -3081,16 +3091,6 @@
|
||||
"from": "delegates@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"from": "ecc-jsbn@>=0.1.1 <0.2.0",
|
||||
@@ -3106,6 +3106,11 @@
|
||||
"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",
|
||||
@@ -3116,11 +3121,6 @@
|
||||
"from": "form-data@>=1.0.0-rc3 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz"
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.0.2",
|
||||
"from": "extsprintf@1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz"
|
||||
},
|
||||
"fstream": {
|
||||
"version": "1.0.9",
|
||||
"from": "fstream@>=1.0.2 <2.0.0",
|
||||
@@ -3136,55 +3136,55 @@
|
||||
"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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"hoek": {
|
||||
"version": "2.16.3",
|
||||
"from": "hoek@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.4",
|
||||
@@ -3201,6 +3201,11 @@
|
||||
"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",
|
||||
@@ -3211,11 +3216,6 @@
|
||||
"from": "is-property@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.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-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"from": "is-typedarray@>=1.0.0 <1.1.0",
|
||||
@@ -3236,16 +3236,16 @@
|
||||
"from": "jodid25519@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-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"
|
||||
},
|
||||
"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",
|
||||
@@ -3271,31 +3271,31 @@
|
||||
"from": "lodash._basetostring@>=4.12.0 <4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.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.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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"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",
|
||||
@@ -3346,31 +3346,31 @@
|
||||
"from": "once@>=1.3.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.1.0",
|
||||
"from": "qs@>=6.1.0 <6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.1.0.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",
|
||||
@@ -3386,16 +3386,16 @@
|
||||
"from": "rimraf@>=2.5.0 <2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.2.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"
|
||||
},
|
||||
"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",
|
||||
@@ -3421,16 +3421,16 @@
|
||||
"from": "supports-color@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.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"
|
||||
},
|
||||
"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",
|
||||
@@ -3451,11 +3451,6 @@
|
||||
"from": "util-deprecate@>=1.0.1 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.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"
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.3.6",
|
||||
"from": "verror@1.3.6",
|
||||
@@ -3466,6 +3461,11 @@
|
||||
"from": "xtend@>=4.0.0 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.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"
|
||||
},
|
||||
"bl": {
|
||||
"version": "1.1.2",
|
||||
"from": "bl@>=1.1.2 <1.2.0",
|
||||
@@ -3478,6 +3478,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.13.1",
|
||||
"from": "dashdash@>=1.12.0 <2.0.0",
|
||||
@@ -3502,18 +3514,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.8.3",
|
||||
"from": "sshpk@>=1.7.0 <2.0.0",
|
||||
@@ -3579,9 +3579,9 @@
|
||||
}
|
||||
},
|
||||
"mapnik": {
|
||||
"version": "1.4.15-cdb6",
|
||||
"from": "https://github.com/CartoDB/node-mapnik/tarball/1.4.15-cdb6",
|
||||
"resolved": "https://github.com/CartoDB/node-mapnik/tarball/1.4.15-cdb6",
|
||||
"version": "1.4.15-cdb8",
|
||||
"from": "https://github.com/CartoDB/node-mapnik/tarball/1.4.15-cdb8",
|
||||
"resolved": "https://github.com/CartoDB/node-mapnik/tarball/1.4.15-cdb8",
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "1.2.0",
|
||||
@@ -3998,14 +3998,14 @@
|
||||
}
|
||||
},
|
||||
"tilelive-bridge": {
|
||||
"version": "1.3.0-cdb4",
|
||||
"from": "https://github.com/CartoDB/tilelive-bridge/tarball/1.3.0-cdb4",
|
||||
"resolved": "https://github.com/CartoDB/tilelive-bridge/tarball/1.3.0-cdb4",
|
||||
"version": "1.3.0-cdb5",
|
||||
"from": "https://github.com/CartoDB/tilelive-bridge/tarball/1.3.0-cdb5",
|
||||
"resolved": "https://github.com/CartoDB/tilelive-bridge/tarball/1.3.0-cdb5",
|
||||
"dependencies": {
|
||||
"mapnik-pool": {
|
||||
"version": "0.1.1-cdb4",
|
||||
"from": "https://github.com/CartoDB/mapnik-pool/tarball/0.1.1-cdb4",
|
||||
"resolved": "https://github.com/CartoDB/mapnik-pool/tarball/0.1.1-cdb4",
|
||||
"version": "0.1.1-cdb5",
|
||||
"from": "https://github.com/CartoDB/mapnik-pool/tarball/0.1.1-cdb5",
|
||||
"resolved": "https://github.com/CartoDB/mapnik-pool/tarball/0.1.1-cdb5",
|
||||
"dependencies": {
|
||||
"generic-pool": {
|
||||
"version": "2.1.1",
|
||||
@@ -4022,9 +4022,9 @@
|
||||
}
|
||||
},
|
||||
"tilelive-mapnik": {
|
||||
"version": "0.6.15-cdb5",
|
||||
"from": "https://github.com/CartoDB/tilelive-mapnik/tarball/0.6.15-cdb5",
|
||||
"resolved": "https://github.com/CartoDB/tilelive-mapnik/tarball/0.6.15-cdb5",
|
||||
"version": "0.6.15-cdb7",
|
||||
"from": "https://github.com/CartoDB/tilelive-mapnik/tarball/0.6.15-cdb7",
|
||||
"resolved": "https://github.com/CartoDB/tilelive-mapnik/tarball/0.6.15-cdb7",
|
||||
"dependencies": {
|
||||
"generic-pool": {
|
||||
"version": "2.1.1",
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"body-parser": "~1.14.0",
|
||||
"camshaft": "0.11.0",
|
||||
"camshaft": "0.12.1",
|
||||
"cartodb-psql": "~0.6.1",
|
||||
"cartodb-query-tables": "~0.1.0",
|
||||
"cartodb-redis": "~0.13.0",
|
||||
@@ -39,7 +39,7 @@
|
||||
"step-profiler": "~0.3.0",
|
||||
"turbo-carto": "0.10.1",
|
||||
"underscore": "~1.6.0",
|
||||
"windshaft": "1.19.0"
|
||||
"windshaft": "2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"istanbul": "~0.4.3",
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
require('../support/test_helper');
|
||||
|
||||
var assert = require('../support/assert');
|
||||
var TestClient = require('../support/test-client');
|
||||
|
||||
|
||||
describe('use only needed columns', function() {
|
||||
|
||||
function getFeatureByCartodbId(features, cartodbId) {
|
||||
for (var i = 0, len = features.length; i < len; i++) {
|
||||
if (features[i].properties.cartodb_id === cartodbId) {
|
||||
return features[i];
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
var options = { format: 'geojson', layer: 0 };
|
||||
|
||||
afterEach(function(done) {
|
||||
if (this.testClient) {
|
||||
this.testClient.drain(done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it('with aggregation widget, interactivity and cartocss columns', function(done) {
|
||||
var widgetMapConfig = {
|
||||
version: '1.5.0',
|
||||
layers: [{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from populated_places_simple_reduced',
|
||||
cartocss: '#layer0 { marker-fill: red; marker-width: 10; [name="Madrid"] { marker-fill: green; } }',
|
||||
cartocss_version: '2.0.1',
|
||||
widgets: {
|
||||
adm0name: {
|
||||
type: 'aggregation',
|
||||
options: {
|
||||
column: 'adm0name',
|
||||
aggregation: 'sum',
|
||||
aggregationColumn: 'pop_max'
|
||||
}
|
||||
}
|
||||
},
|
||||
interactivity: "cartodb_id,pop_min"
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
this.testClient = new TestClient(widgetMapConfig);
|
||||
this.testClient.getTile(0, 0, 0, options, function (err, res, geojsonTile) {
|
||||
assert.ok(!err, err);
|
||||
assert.deepEqual(getFeatureByCartodbId(geojsonTile.features, 1109).properties, {
|
||||
cartodb_id: 1109,
|
||||
name: 'Mardin',
|
||||
adm0name: 'Turkey',
|
||||
pop_max: 71373,
|
||||
pop_min: 57586
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not duplicate columns', function(done) {
|
||||
var widgetMapConfig = {
|
||||
version: '1.5.0',
|
||||
layers: [{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from populated_places_simple_reduced',
|
||||
cartocss: ['#layer0 {',
|
||||
'marker-fill: red;',
|
||||
'marker-width: 10;',
|
||||
'[name="Madrid"] { marker-fill: green; } ',
|
||||
'[pop_max>100000] { marker-fill: black; } ',
|
||||
'}'].join('\n'),
|
||||
cartocss_version: '2.3.0',
|
||||
widgets: {
|
||||
adm0name: {
|
||||
type: 'aggregation',
|
||||
options: {
|
||||
column: 'adm0name',
|
||||
aggregation: 'sum',
|
||||
aggregationColumn: 'pop_max'
|
||||
}
|
||||
}
|
||||
},
|
||||
interactivity: "cartodb_id,pop_max"
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
this.testClient = new TestClient(widgetMapConfig);
|
||||
this.testClient.getTile(0, 0, 0, options, function (err, res, geojsonTile) {
|
||||
assert.ok(!err, err);
|
||||
assert.deepEqual(getFeatureByCartodbId(geojsonTile.features, 1109).properties, {
|
||||
cartodb_id: 1109,
|
||||
name: 'Mardin',
|
||||
adm0name: 'Turkey',
|
||||
pop_max: 71373
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('with formula widget, no interactivity and no cartocss columns', function(done) {
|
||||
var formulaWidgetMapConfig = {
|
||||
version: '1.5.0',
|
||||
layers: [{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from populated_places_simple_reduced where pop_max > 0 and pop_max < 600000',
|
||||
cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
|
||||
cartocss_version: '2.0.1',
|
||||
interactivity: 'cartodb_id',
|
||||
widgets: {
|
||||
pop_max_f: {
|
||||
type: 'formula',
|
||||
options: {
|
||||
column: 'pop_max',
|
||||
operation: 'count'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
this.testClient = new TestClient(formulaWidgetMapConfig);
|
||||
this.testClient.getTile(0, 0, 0, options, function (err, res, geojsonTile) {
|
||||
assert.ok(!err, err);
|
||||
assert.deepEqual(getFeatureByCartodbId(geojsonTile.features, 1109).properties, {
|
||||
cartodb_id: 1109,
|
||||
pop_max: 71373
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('with cartocss with multiple expressions', function(done) {
|
||||
var formulaWidgetMapConfig = {
|
||||
version: '1.5.0',
|
||||
layers: [{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from populated_places_simple_reduced where pop_max > 0 and pop_max < 600000',
|
||||
cartocss: '#layer0 { marker-fill: red; marker-width: 10; }' +
|
||||
'#layer0 { marker-width: 14; [name="Madrid"] { marker-width: 20; } }' +
|
||||
'#layer0[pop_max>1000] { marker-width: 14; [name="Madrid"] { marker-width: 20; } }' +
|
||||
'#layer0[adm0name=~".*Turkey*"] { marker-width: 14; [name="Madrid"] { marker-width: 20; } }',
|
||||
cartocss_version: '2.0.1',
|
||||
interactivity: 'cartodb_id'
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
this.testClient = new TestClient(formulaWidgetMapConfig);
|
||||
this.testClient.getTile(0, 0, 0, options, function (err, res, geojsonTile) {
|
||||
assert.ok(!err, err);
|
||||
assert.deepEqual(getFeatureByCartodbId(geojsonTile.features, 1109).properties, {
|
||||
cartodb_id: 1109,
|
||||
pop_max:71373,
|
||||
name:"Mardin",
|
||||
adm0name:"Turkey"
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,329 @@
|
||||
require('../../../support/test_helper');
|
||||
|
||||
var assert = require('../../../support/assert');
|
||||
var TestClient = require('../../../support/test-client');
|
||||
|
||||
describe('widgets', function() {
|
||||
|
||||
describe('aggregations', function() {
|
||||
|
||||
afterEach(function(done) {
|
||||
if (this.testClient) {
|
||||
this.testClient.drain(done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
var aggregationMapConfig = {
|
||||
version: '1.5.0',
|
||||
layers: [
|
||||
{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from populated_places_simple_reduced',
|
||||
cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
|
||||
cartocss_version: '2.0.1',
|
||||
widgets: {
|
||||
adm0name: {
|
||||
type: 'aggregation',
|
||||
options: {
|
||||
column: 'adm0name',
|
||||
aggregation: 'count'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
it('can be fetched from a valid aggregation', function(done) {
|
||||
this.testClient = new TestClient(aggregationMapConfig);
|
||||
this.testClient.getWidget('adm0name', { own_filter: 0 }, function (err, res, aggregation) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(aggregation);
|
||||
assert.equal(aggregation.type, 'aggregation');
|
||||
|
||||
assert.equal(aggregation.categories.length, 6);
|
||||
|
||||
assert.deepEqual(
|
||||
aggregation.categories[0],
|
||||
{ category: 'United States of America', value: 769, agg: false }
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
aggregation.categories[aggregation.categories.length - 1],
|
||||
{ category: 'Other', value: 4914, agg: true }
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
var filteredCategoriesScenarios = [
|
||||
{ accept: ['Canada'], values: [256] },
|
||||
{ accept: ['Canada', 'Spain', 'Chile', 'Thailand'], values: [256, 49, 83, 79] },
|
||||
{ accept: ['Canada', 'Spain', 'Chile', 'Thailand', 'Japan'], values: [256, 49, 83, 79, 69] },
|
||||
{ accept: ['Canada', 'Spain', 'Chile', 'Thailand', 'Japan', 'France'], values: [256, 49, 83, 79, 69, 71] },
|
||||
{
|
||||
accept: ['United States of America', 'Canada', 'Spain', 'Chile', 'Thailand', 'Japan', 'France'],
|
||||
values: [769, 256, 49, 83, 79, 69, 71]
|
||||
}
|
||||
];
|
||||
|
||||
filteredCategoriesScenarios.forEach(function(scenario) {
|
||||
it('can filter some categories: ' + scenario.accept.join(', '), function(done) {
|
||||
this.testClient = new TestClient(aggregationMapConfig);
|
||||
var adm0nameFilter = {
|
||||
adm0name: {
|
||||
accept: scenario.accept
|
||||
}
|
||||
};
|
||||
var params = {
|
||||
own_filter: 1,
|
||||
filters: {
|
||||
layers: [
|
||||
adm0nameFilter
|
||||
]
|
||||
}
|
||||
};
|
||||
this.testClient.getWidget('adm0name', params, function (err, res, aggregation) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(aggregation);
|
||||
assert.equal(aggregation.type, 'aggregation');
|
||||
|
||||
assert.equal(aggregation.categories.length, scenario.accept.length);
|
||||
|
||||
var categoriesByCategory = aggregation.categories.reduce(function(byCategory, row) {
|
||||
byCategory[row.category] = row;
|
||||
return byCategory;
|
||||
}, {});
|
||||
|
||||
var scenarioByCategory = scenario.accept.reduce(function(byCategory, category, index) {
|
||||
byCategory[category] = { category: category, value: scenario.values[index], agg: false };
|
||||
return byCategory;
|
||||
}, {});
|
||||
|
||||
Object.keys(categoriesByCategory).forEach(function(category) {
|
||||
assert.deepEqual(categoriesByCategory[category], scenarioByCategory[category]);
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var aggregationSumMapConfig = {
|
||||
version: '1.5.0',
|
||||
layers: [
|
||||
{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from populated_places_simple_reduced',
|
||||
cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
|
||||
cartocss_version: '2.0.1',
|
||||
widgets: {
|
||||
adm0name: {
|
||||
type: 'aggregation',
|
||||
options: {
|
||||
column: 'adm0name',
|
||||
aggregation: 'sum',
|
||||
aggregationColumn: 'pop_max'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
it('can sum other column for aggregation value', function(done) {
|
||||
|
||||
this.testClient = new TestClient(aggregationSumMapConfig);
|
||||
this.testClient.getWidget('adm0name', { own_filter: 0 }, function (err, res, aggregation) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(aggregation);
|
||||
assert.equal(aggregation.type, 'aggregation');
|
||||
|
||||
assert.equal(aggregation.categories.length, 6);
|
||||
|
||||
assert.deepEqual(
|
||||
aggregation.categories[0],
|
||||
{ category: 'China', value: 374537585, agg: false }
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
aggregation.categories[aggregation.categories.length - 1],
|
||||
{ category: 'Other', value: 1412626289, agg: true }
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
var filteredCategoriesSumScenarios = [
|
||||
{ accept: [], values: [] },
|
||||
{ accept: ['Canada'], values: [23955084] },
|
||||
{ accept: ['Canada', 'Spain', 'Chile', 'Thailand'], values: [23955084, 22902774, 14356263, 17492483] },
|
||||
{
|
||||
accept: ['United States of America', 'Canada', 'Spain', 'Chile', 'Thailand', 'Japan', 'France'],
|
||||
values: [239098994, 23955084, 22902774, 14356263, 17492483, 93577001, 25473876]
|
||||
}
|
||||
];
|
||||
|
||||
filteredCategoriesSumScenarios.forEach(function(scenario) {
|
||||
it('can filter some categories with sum aggregation: ' + scenario.accept.join(', '), function(done) {
|
||||
this.testClient = new TestClient(aggregationSumMapConfig);
|
||||
var adm0nameFilter = {
|
||||
adm0name: {
|
||||
accept: scenario.accept
|
||||
}
|
||||
};
|
||||
var params = {
|
||||
own_filter: 1,
|
||||
filters: {
|
||||
layers: [
|
||||
adm0nameFilter
|
||||
]
|
||||
}
|
||||
};
|
||||
this.testClient.getWidget('adm0name', params, function (err, res, aggregation) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(aggregation);
|
||||
assert.equal(aggregation.type, 'aggregation');
|
||||
|
||||
assert.equal(aggregation.categories.length, scenario.accept.length);
|
||||
|
||||
var categoriesByCategory = aggregation.categories.reduce(function(byCategory, row) {
|
||||
byCategory[row.category] = row;
|
||||
return byCategory;
|
||||
}, {});
|
||||
|
||||
var scenarioByCategory = scenario.accept.reduce(function(byCategory, category, index) {
|
||||
byCategory[category] = { category: category, value: scenario.values[index], agg: false };
|
||||
return byCategory;
|
||||
}, {});
|
||||
|
||||
Object.keys(categoriesByCategory).forEach(function(category) {
|
||||
assert.deepEqual(categoriesByCategory[category], scenarioByCategory[category]);
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var numericAggregationMapConfig = {
|
||||
version: '1.5.0',
|
||||
layers: [
|
||||
{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from populated_places_simple_reduced',
|
||||
cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
|
||||
cartocss_version: '2.3.0',
|
||||
widgets: {
|
||||
scalerank: {
|
||||
type: 'aggregation',
|
||||
options: {
|
||||
column: 'scalerank',
|
||||
aggregation: 'count'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
['1', 1].forEach(function(filterValue) {
|
||||
it('can filter numeric categories: ' + (typeof filterValue), function(done) {
|
||||
this.testClient = new TestClient(numericAggregationMapConfig);
|
||||
var scalerankFilter = {
|
||||
scalerank: {
|
||||
accept: [filterValue]
|
||||
}
|
||||
};
|
||||
var params = {
|
||||
own_filter: 1,
|
||||
filters: {
|
||||
layers: [scalerankFilter]
|
||||
}
|
||||
};
|
||||
this.testClient.getWidget('scalerank', params, function (err, res, aggregation) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(aggregation);
|
||||
assert.equal(aggregation.type, 'aggregation');
|
||||
|
||||
assert.equal(aggregation.categories.length, 1);
|
||||
assert.deepEqual(aggregation.categories[0], { category: '1', value: 179, agg: false });
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('search', function() {
|
||||
afterEach(function(done) {
|
||||
if (this.testClient) {
|
||||
this.testClient.drain(done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
['1', 1].forEach(function(userQuery) {
|
||||
it('can search numeric categories: ' + (typeof userQuery), function(done) {
|
||||
this.testClient = new TestClient(numericAggregationMapConfig);
|
||||
var scalerankFilter = {
|
||||
scalerank: {
|
||||
accept: [userQuery]
|
||||
}
|
||||
};
|
||||
var params = {
|
||||
own_filter: 0,
|
||||
filters: {
|
||||
layers: [scalerankFilter]
|
||||
}
|
||||
};
|
||||
this.testClient.widgetSearch('scalerank', userQuery, params, function (err, res, searchResult) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(searchResult);
|
||||
assert.equal(searchResult.type, 'aggregation');
|
||||
|
||||
assert.equal(searchResult.categories.length, 2);
|
||||
assert.deepEqual(
|
||||
searchResult.categories,
|
||||
[{ category: 10, value: 515 }, { category: 1, value: 179 }]
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var adm0name = 'Argentina';
|
||||
[adm0name, adm0name.toLowerCase(), adm0name.toUpperCase()].forEach(function(userQuery) {
|
||||
it('should search with case insensitive: ' + userQuery, function(done) {
|
||||
this.testClient = new TestClient(aggregationMapConfig);
|
||||
this.testClient.widgetSearch('adm0name', userQuery, function (err, res, searchResult) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(searchResult);
|
||||
assert.equal(searchResult.type, 'aggregation');
|
||||
|
||||
assert.equal(searchResult.categories.length, 1);
|
||||
assert.deepEqual(
|
||||
searchResult.categories,
|
||||
[{ category:"Argentina", value:159 }]
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,89 @@
|
||||
require('../../../support/test_helper');
|
||||
|
||||
var assert = require('../../../support/assert');
|
||||
var TestClient = require('../../../support/test-client');
|
||||
|
||||
describe('widgets', function() {
|
||||
|
||||
describe('formula', function() {
|
||||
|
||||
afterEach(function(done) {
|
||||
if (this.testClient) {
|
||||
this.testClient.drain(done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
function widgetsMapConfig(widgets) {
|
||||
return {
|
||||
version: '1.5.0',
|
||||
layers: [
|
||||
{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from populated_places_simple_reduced where pop_max > 0 and pop_max < 600000',
|
||||
cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
|
||||
cartocss_version: '2.0.1',
|
||||
widgets: widgets
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
var operations = {
|
||||
min: [10, 0],
|
||||
max: [599579, 0],
|
||||
count: [5822, 0],
|
||||
avg: [112246.00893163861, 0],
|
||||
sum: [653496264, 0]
|
||||
};
|
||||
|
||||
Object.keys(operations).forEach(function(operation) {
|
||||
it('should do ' + operation + ' over column', function(done) {
|
||||
var widgets = {
|
||||
pop_max_f: {
|
||||
type: 'formula',
|
||||
options: {
|
||||
column: 'pop_max',
|
||||
operation: operation
|
||||
}
|
||||
}
|
||||
};
|
||||
this.testClient = new TestClient(widgetsMapConfig(widgets));
|
||||
this.testClient.getWidget('pop_max_f', function (err, res, result) {
|
||||
assert.ok(!err, err);
|
||||
assert.equal(result.operation, operation);
|
||||
assert.equal(result.result, operations[operation][0]);
|
||||
assert.equal(result.nulls, operations[operation][1]);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('does not require column for count formula', function(done) {
|
||||
var operation = 'count';
|
||||
var widgets = {
|
||||
pop_max_count_f: {
|
||||
type: 'formula',
|
||||
options: {
|
||||
operation: operation
|
||||
}
|
||||
}
|
||||
};
|
||||
this.testClient = new TestClient(widgetsMapConfig(widgets));
|
||||
this.testClient.getWidget('pop_max_count_f', function (err, res, result) {
|
||||
assert.ok(!err, err);
|
||||
assert.equal(result.operation, operation);
|
||||
assert.equal(result.result, operations[operation][0]);
|
||||
assert.equal(result.nulls, operations[operation][1]);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,373 @@
|
||||
require('../../../support/test_helper');
|
||||
|
||||
var assert = require('../../../support/assert');
|
||||
var TestClient = require('../../../support/test-client');
|
||||
|
||||
describe('widgets', function() {
|
||||
|
||||
describe('histograms', function() {
|
||||
|
||||
afterEach(function(done) {
|
||||
if (this.testClient) {
|
||||
this.testClient.drain(done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
function histogramsMapConfig(widgets) {
|
||||
return {
|
||||
version: '1.5.0',
|
||||
layers: [
|
||||
{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from populated_places_simple_reduced',
|
||||
cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
|
||||
cartocss_version: '2.0.1',
|
||||
widgets: widgets || {
|
||||
scalerank: {
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'scalerank'
|
||||
}
|
||||
},
|
||||
pop_max: {
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'pop_max'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
it('can be fetched from a valid histogram', function(done) {
|
||||
this.testClient = new TestClient(histogramsMapConfig());
|
||||
this.testClient.getWidget('scalerank', function (err, res, histogram) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(histogram);
|
||||
assert.equal(histogram.type, 'histogram');
|
||||
validateHistogramBins(histogram);
|
||||
|
||||
assert.ok(histogram.bins.length);
|
||||
|
||||
assert.deepEqual(histogram.bins[0], { bin: 0, freq: 179, min: 1, max: 1, avg: 1 });
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can be fetched from a valid histogram', function(done) {
|
||||
this.testClient = new TestClient(histogramsMapConfig());
|
||||
this.testClient.getWidget('pop_max', function (err, res, histogram) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(histogram);
|
||||
assert.equal(histogram.type, 'histogram');
|
||||
validateHistogramBins(histogram);
|
||||
|
||||
assert.ok(histogram.bins.length);
|
||||
|
||||
assert.deepEqual(
|
||||
histogram.bins[histogram.bins.length - 1],
|
||||
{ bin: 47, freq: 1, min: 35676000, max: 35676000, avg: 35676000 }
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can be fetched from a valid filtered histogram', function(done) {
|
||||
this.testClient = new TestClient(histogramsMapConfig());
|
||||
var popMaxFilter = {
|
||||
pop_max: {
|
||||
min: 1e5,
|
||||
max: 1e7
|
||||
}
|
||||
};
|
||||
var params = {
|
||||
own_filter: 1,
|
||||
filters: {
|
||||
layers: [popMaxFilter]
|
||||
}
|
||||
};
|
||||
this.testClient.getWidget('pop_max', params, function (err, res, histogram) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(histogram);
|
||||
assert.equal(histogram.type, 'histogram');
|
||||
validateHistogramBins(histogram);
|
||||
|
||||
assert.ok(histogram.bins.length);
|
||||
|
||||
assert.deepEqual(
|
||||
histogram.bins[histogram.bins.length - 1],
|
||||
{ bin: 7, min: 8829000, max: 9904000, avg: 9340914.714285715, freq: 7 }
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns array with freq=0 entries for empty bins', function(done) {
|
||||
var histogram20binsMapConfig = {
|
||||
version: '1.5.0',
|
||||
layers: [
|
||||
{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from populated_places_simple_reduced',
|
||||
cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
|
||||
cartocss_version: '2.0.1',
|
||||
widgets: {
|
||||
pop_max: {
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'pop_max'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.testClient = new TestClient(histogram20binsMapConfig);
|
||||
this.testClient.getWidget('pop_max', { start: 0, end: 35676000, bins: 20 }, function (err, res, histogram) {
|
||||
assert.ok(!err, err);
|
||||
assert.equal(histogram.type, 'histogram');
|
||||
validateHistogramBins(histogram);
|
||||
assert.ok(histogram.bins.length);
|
||||
assert.deepEqual(
|
||||
histogram.bins[histogram.bins.length - 1],
|
||||
{ bin: 19, freq: 1, min: 35676000, max: 35676000, avg: 35676000 }
|
||||
);
|
||||
|
||||
var emptyBin = histogram.bins[18];
|
||||
assert.ok(!emptyBin);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can use a fixed number of bins', function(done) {
|
||||
var fixedBinsHistogramMapConfig = histogramsMapConfig({
|
||||
pop_max: {
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'pop_max'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.testClient = new TestClient(fixedBinsHistogramMapConfig);
|
||||
this.testClient.getWidget('pop_max', { bins: 5 }, function (err, res, histogram) {
|
||||
assert.ok(!err, err);
|
||||
assert.equal(histogram.type, 'histogram');
|
||||
|
||||
assert.equal(histogram.bins_count, 5);
|
||||
|
||||
validateHistogramBins(histogram);
|
||||
|
||||
assert.ok(histogram.bins.length);
|
||||
assert.deepEqual(
|
||||
histogram.bins[0],
|
||||
{ bin: 0, min: 0, max: 7067423, avg: 280820.0057731959, freq: 7275 }
|
||||
);
|
||||
assert.deepEqual(
|
||||
histogram.bins[histogram.bins.length - 1],
|
||||
{ bin: 4, freq: 1, min: 35676000, max: 35676000, avg: 35676000 }
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
function validateHistogramBins(histogram) {
|
||||
var binWidth = histogram.bin_width;
|
||||
var start = histogram.bins_start;
|
||||
var end = start + (histogram.bins_count * binWidth);
|
||||
|
||||
var firstBin = histogram.bins[0];
|
||||
assert.equal(firstBin.min, start,
|
||||
'First bin does not match min and start ' + JSON.stringify({
|
||||
min: firstBin.min,
|
||||
start: start
|
||||
})
|
||||
);
|
||||
|
||||
var lastBin = histogram.bins[histogram.bins.length - 1];
|
||||
assert.equal(lastBin.max, end,
|
||||
'Last bin does not match max and end ' + JSON.stringify({
|
||||
max: lastBin.max,
|
||||
end: end
|
||||
})
|
||||
);
|
||||
|
||||
function getBinStartEnd(binIndex) {
|
||||
return {
|
||||
start: start + (binIndex * binWidth),
|
||||
end: start + ((binIndex + 1) * binWidth)
|
||||
};
|
||||
}
|
||||
|
||||
histogram.bins.forEach(function(bin) {
|
||||
var binStartEnd = getBinStartEnd(bin.bin);
|
||||
|
||||
assert.ok(binStartEnd.start <= bin.min,
|
||||
'Bin start bigger than bin min ' + JSON.stringify({
|
||||
bin: bin.bin,
|
||||
min: bin.min,
|
||||
start: binStartEnd.start
|
||||
})
|
||||
);
|
||||
|
||||
assert.ok(binStartEnd.end >= bin.max,
|
||||
'Bin end smaller than bin max ' + JSON.stringify({
|
||||
bin: bin.bin,
|
||||
max: bin.max,
|
||||
end: binStartEnd.end
|
||||
})
|
||||
);
|
||||
|
||||
assert.ok(bin.avg >= bin.min && bin.avg <= bin.max,
|
||||
'Bin avg not between min and max values' + JSON.stringify({
|
||||
bin: bin.bin,
|
||||
avg: bin.avg,
|
||||
min: bin.min,
|
||||
max: bin.max
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
describe('datetime column', function() {
|
||||
afterEach(function(done) {
|
||||
if (this.testClient) {
|
||||
this.testClient.drain(done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
var updatedAtFilter = {
|
||||
updated_at: {
|
||||
min: 0
|
||||
}
|
||||
};
|
||||
|
||||
it('can use a datetime column', function(done) {
|
||||
this.testClient = new TestClient(histogramsMapConfig({
|
||||
updated_at: {
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'updated_at'
|
||||
}
|
||||
}
|
||||
}));
|
||||
this.testClient.getWidget('updated_at', function (err, res, histogram) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(histogram);
|
||||
assert.equal(histogram.type, 'histogram');
|
||||
|
||||
assert.ok(histogram.bins.length);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can use a datetime filtered column', function(done) {
|
||||
this.testClient = new TestClient(histogramsMapConfig({
|
||||
updated_at: {
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'updated_at'
|
||||
}
|
||||
}
|
||||
}));
|
||||
var params = {
|
||||
own_filter: 1,
|
||||
filters: {
|
||||
layers: [updatedAtFilter]
|
||||
}
|
||||
};
|
||||
this.testClient.getWidget('updated_at', params, function (err, res, histogram) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(histogram);
|
||||
assert.equal(histogram.type, 'histogram');
|
||||
|
||||
assert.ok(histogram.bins.length);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can getTile with datetime filtered column', function(done) {
|
||||
this.testClient = new TestClient(histogramsMapConfig({
|
||||
updated_at: {
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'updated_at'
|
||||
}
|
||||
}
|
||||
}));
|
||||
var params = {
|
||||
own_filter: 1,
|
||||
filters: {
|
||||
layers: [updatedAtFilter]
|
||||
}
|
||||
};
|
||||
this.testClient.getTile(0, 0, 0, params, function (err, res, tile) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(tile);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can use two columns with different types', function(done) {
|
||||
this.testClient = new TestClient(histogramsMapConfig({
|
||||
updated_at: {
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'updated_at'
|
||||
}
|
||||
},
|
||||
pop_max: {
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'pop_max'
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
var popMaxFilter = {
|
||||
pop_max: {
|
||||
max: 1e7
|
||||
}
|
||||
};
|
||||
|
||||
var params = {
|
||||
own_filter: 1,
|
||||
filters: {
|
||||
layers: [popMaxFilter]
|
||||
}
|
||||
};
|
||||
|
||||
this.testClient.getWidget('updated_at', params, function (err, res, histogram) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(histogram);
|
||||
assert.equal(histogram.type, 'histogram');
|
||||
|
||||
assert.ok(histogram.bins.length);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,106 @@
|
||||
require('../../../support/test_helper');
|
||||
|
||||
var assert = require('../../../support/assert');
|
||||
var TestClient = require('../../../support/test-client');
|
||||
var _ = require('underscore');
|
||||
|
||||
describe('widgets', function() {
|
||||
|
||||
describe('lists', function() {
|
||||
|
||||
afterEach(function(done) {
|
||||
if (this.testClient) {
|
||||
this.testClient.drain(done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
function listsMapConfig(columns) {
|
||||
return {
|
||||
version: '1.5.0',
|
||||
layers: [
|
||||
{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: 'select * from test_table',
|
||||
cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
|
||||
cartocss_version: '2.0.1',
|
||||
widgets: {
|
||||
places: {
|
||||
type: 'list',
|
||||
options: {
|
||||
columns: columns || ['name', 'address']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
var EXPECTED_NAMES = ['Hawai', 'El Estocolmo', 'El Rey del Tallarín', 'El Lacón', 'El Pico'];
|
||||
|
||||
it('can be fetched from a valid list', function(done) {
|
||||
var columns = ['name', 'address'];
|
||||
this.testClient = new TestClient(listsMapConfig(columns));
|
||||
this.testClient.getWidget('places', function (err, res, list) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(list);
|
||||
assert.equal(list.type, 'list');
|
||||
assert.equal(list.rows.length, 5);
|
||||
|
||||
assert.ok(onlyHasFields(list, columns));
|
||||
|
||||
var names = list.rows.map(function (item) {
|
||||
return item.name;
|
||||
});
|
||||
assert.deepEqual(names, EXPECTED_NAMES);
|
||||
|
||||
var expectedAddresses = [
|
||||
'Calle de Pérez Galdós 9, Madrid, Spain',
|
||||
'Calle de la Palma 72, Madrid, Spain',
|
||||
'Plaza Conde de Toreno 2, Madrid, Spain',
|
||||
'Manuel Fernández y González 8, Madrid, Spain',
|
||||
'Calle Divino Pastor 12, Madrid, Spain'
|
||||
];
|
||||
var addresses = list.rows.map(function (item) {
|
||||
return item.address;
|
||||
});
|
||||
assert.deepEqual(addresses, expectedAddresses);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fetch just one column', function(done) {
|
||||
var columns = ['name'];
|
||||
this.testClient = new TestClient(listsMapConfig(columns));
|
||||
this.testClient.getWidget('places', function (err, res, list) {
|
||||
assert.ok(!err, err);
|
||||
assert.ok(list);
|
||||
assert.equal(list.type, 'list');
|
||||
assert.equal(list.rows.length, 5);
|
||||
|
||||
assert.ok(onlyHasFields(list, columns));
|
||||
|
||||
var names = list.rows.map(function (item) {
|
||||
return item.name;
|
||||
});
|
||||
assert.deepEqual(names, EXPECTED_NAMES);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
function onlyHasFields(list, expectedFields) {
|
||||
var fields = (!!list.rows[0]) ? Object.keys(list.rows[0]) : [];
|
||||
|
||||
return _.difference(fields, expectedFields).length === 0 &&
|
||||
_.difference(expectedFields, fields).length === 0;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
+130
-4
@@ -62,6 +62,7 @@ TestClient.prototype.getWidget = function(widgetName, params, callback) {
|
||||
return next(err);
|
||||
}
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
|
||||
var expectedWidgetURLS = {
|
||||
http: "/api/v1/map/" + parsedBody.layergroupid + "/0/widget/" + widgetName
|
||||
};
|
||||
@@ -69,6 +70,15 @@ TestClient.prototype.getWidget = function(widgetName, params, callback) {
|
||||
assert.ok(
|
||||
parsedBody.metadata.layers[0].widgets[widgetName].url.http.match(expectedWidgetURLS.http)
|
||||
);
|
||||
|
||||
var expectedDataviewsURLS = {
|
||||
http: "/api/v1/map/" + parsedBody.layergroupid + "/dataview/" + widgetName
|
||||
};
|
||||
assert.ok(parsedBody.metadata.dataviews[widgetName]);
|
||||
assert.ok(
|
||||
parsedBody.metadata.dataviews[widgetName].url.http.match(expectedDataviewsURLS.http)
|
||||
);
|
||||
|
||||
return next(null, parsedBody.layergroupid);
|
||||
}
|
||||
);
|
||||
@@ -82,9 +92,12 @@ TestClient.prototype.getWidget = function(widgetName, params, callback) {
|
||||
var urlParams = {
|
||||
own_filter: params.hasOwnProperty('own_filter') ? params.own_filter : 1
|
||||
};
|
||||
if (params && params.bbox) {
|
||||
urlParams.bbox = params.bbox;
|
||||
}
|
||||
['bbox', 'bins', 'start', 'end'].forEach(function(extraParam) {
|
||||
if (params.hasOwnProperty(extraParam)) {
|
||||
urlParams[extraParam] = params[extraParam];
|
||||
}
|
||||
});
|
||||
|
||||
url = '/api/v1/map/' + layergroupId + '/0/widget/' + widgetName + '?' + qs.stringify(urlParams);
|
||||
|
||||
assert.response(server,
|
||||
@@ -113,7 +126,120 @@ TestClient.prototype.getWidget = function(widgetName, params, callback) {
|
||||
function finish(err, res) {
|
||||
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
||||
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
||||
return callback(err, res);
|
||||
var widget;
|
||||
if (!err && res.body) {
|
||||
widget = JSON.parse(res.body);
|
||||
}
|
||||
return callback(err, res, widget);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
TestClient.prototype.widgetSearch = function(widgetName, userQuery, params, callback) {
|
||||
var self = this;
|
||||
|
||||
if (!callback) {
|
||||
callback = params;
|
||||
params = {};
|
||||
}
|
||||
|
||||
var url = '/api/v1/map';
|
||||
if (params && params.filters) {
|
||||
url += '?' + qs.stringify({ filters: JSON.stringify(params.filters) });
|
||||
}
|
||||
|
||||
var layergroupId;
|
||||
step(
|
||||
function createLayergroup() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: url,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify(self.mapConfig)
|
||||
},
|
||||
{
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
}
|
||||
},
|
||||
function(res, err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
|
||||
var expectedWidgetURLS = {
|
||||
http: "/api/v1/map/" + parsedBody.layergroupid + "/0/widget/" + widgetName
|
||||
};
|
||||
assert.ok(parsedBody.metadata.layers[0].widgets[widgetName]);
|
||||
assert.ok(
|
||||
parsedBody.metadata.layers[0].widgets[widgetName].url.http.match(expectedWidgetURLS.http)
|
||||
);
|
||||
|
||||
var expectedDataviewsURLS = {
|
||||
http: "/api/v1/map/" + parsedBody.layergroupid + "/dataview/" + widgetName
|
||||
};
|
||||
assert.ok(parsedBody.metadata.dataviews[widgetName]);
|
||||
assert.ok(
|
||||
parsedBody.metadata.dataviews[widgetName].url.http.match(expectedDataviewsURLS.http)
|
||||
);
|
||||
|
||||
return next(null, parsedBody.layergroupid);
|
||||
}
|
||||
);
|
||||
},
|
||||
function getWidgetSearchResult(err, _layergroupId) {
|
||||
assert.ifError(err);
|
||||
|
||||
var next = this;
|
||||
layergroupId = _layergroupId;
|
||||
|
||||
var urlParams = {
|
||||
q: userQuery,
|
||||
own_filter: params.hasOwnProperty('own_filter') ? params.own_filter : 1
|
||||
};
|
||||
if (params && params.bbox) {
|
||||
urlParams.bbox = params.bbox;
|
||||
}
|
||||
url = '/api/v1/map/' + layergroupId + '/0/widget/' + widgetName + '/search?' + qs.stringify(urlParams);
|
||||
|
||||
assert.response(server,
|
||||
{
|
||||
url: url,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'localhost'
|
||||
}
|
||||
},
|
||||
{
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
}
|
||||
},
|
||||
function(res, err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
next(null, res);
|
||||
}
|
||||
);
|
||||
},
|
||||
function finish(err, res) {
|
||||
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
||||
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
||||
var searchResult;
|
||||
if (!err && res.body) {
|
||||
searchResult = JSON.parse(res.body);
|
||||
}
|
||||
return callback(err, res, searchResult);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
//require('../../../support/test_helper');
|
||||
var assert = require('assert');
|
||||
|
||||
var DataviewsMapConfigAdapter = require('../../../../lib/cartodb/models/mapconfig/adapter/dataviews-widgets-adapter');
|
||||
|
||||
describe('dataviews-widgets-adapter', function() {
|
||||
|
||||
var widgetsMapConfigs = [
|
||||
{
|
||||
"input": {
|
||||
"version": "1.4.0",
|
||||
"layers": [
|
||||
{
|
||||
"type": "mapnik",
|
||||
"options": {
|
||||
"sql": "select * from populated_places_simple_reduced",
|
||||
"cartocss": "#layer { marker-fill: red; marker-width: 32; marker-allow-overlap: true; }",
|
||||
"cartocss_version": "2.3.0",
|
||||
"widgets": {
|
||||
"country_places_count": {
|
||||
"type": "aggregation",
|
||||
"options": {
|
||||
"column": "adm0_a3",
|
||||
"aggregation": "count"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"version": "1.4.0",
|
||||
"layers": [
|
||||
{
|
||||
"type": "mapnik",
|
||||
"options": {
|
||||
"source": {
|
||||
"id": "cdb-layer-source-0"
|
||||
},
|
||||
"cartocss": "#layer { marker-fill: red; marker-width: 32; marker-allow-overlap: true; }",
|
||||
"cartocss_version": "2.3.0",
|
||||
// keep them for now
|
||||
"widgets": {
|
||||
"country_places_count": {
|
||||
"type": "aggregation",
|
||||
"options": {
|
||||
"column": "adm0_a3",
|
||||
"aggregation": "count"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"analyses": [
|
||||
{
|
||||
"id": "cdb-layer-source-0",
|
||||
"type": "source",
|
||||
"params": {
|
||||
"query": "select * from populated_places_simple_reduced"
|
||||
}
|
||||
}
|
||||
],
|
||||
"dataviews": {
|
||||
"country_places_count": {
|
||||
"source": {
|
||||
"id": "cdb-layer-source-0"
|
||||
},
|
||||
"type": "aggregation",
|
||||
"options": {
|
||||
"column": "adm0_a3",
|
||||
"aggregation": "count"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"version": "1.4.0",
|
||||
"layers": [
|
||||
{
|
||||
"type": "mapnik",
|
||||
"options": {
|
||||
"sql": "select * from populated_places_simple_reduced",
|
||||
"cartocss": "#layer { marker-fill: red; marker-width: 32; marker-allow-overlap: true; }",
|
||||
"cartocss_version": "2.3.0",
|
||||
"widgets": {
|
||||
"pop_max": {
|
||||
"type": "histogram",
|
||||
"options": {
|
||||
"column": "pop_max"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"version": "1.4.0",
|
||||
"layers": [
|
||||
{
|
||||
"type": "mapnik",
|
||||
"options": {
|
||||
"source": {
|
||||
"id": "cdb-layer-source-0"
|
||||
},
|
||||
"cartocss": "#layer { marker-fill: red; marker-width: 32; marker-allow-overlap: true; }",
|
||||
"cartocss_version": "2.3.0",
|
||||
// keep them for now
|
||||
"widgets": {
|
||||
"pop_max": {
|
||||
"type": "histogram",
|
||||
"options": {
|
||||
"column": "pop_max"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"analyses": [
|
||||
{
|
||||
"id": "cdb-layer-source-0",
|
||||
"type": "source",
|
||||
"params": {
|
||||
"query": "select * from populated_places_simple_reduced"
|
||||
}
|
||||
}
|
||||
],
|
||||
"dataviews": {
|
||||
"pop_max": {
|
||||
"source": {
|
||||
"id": "cdb-layer-source-0"
|
||||
},
|
||||
"type": "histogram",
|
||||
"options": {
|
||||
"column": "pop_max"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"version": "1.4.0",
|
||||
"layers": [
|
||||
{
|
||||
"type": "mapnik",
|
||||
"options": {
|
||||
"sql": "select * from test_table",
|
||||
"cartocss": "#layer { marker-fill: red; marker-width: 32; marker-allow-overlap: true; }",
|
||||
"cartocss_version": "2.3.0",
|
||||
"widgets": {
|
||||
"names": {
|
||||
"type": "list",
|
||||
"options": {
|
||||
"columns": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"version": "1.4.0",
|
||||
"layers": [
|
||||
{
|
||||
"type": "mapnik",
|
||||
"options": {
|
||||
"source": {
|
||||
"id": "cdb-layer-source-0"
|
||||
},
|
||||
"cartocss": "#layer { marker-fill: red; marker-width: 32; marker-allow-overlap: true; }",
|
||||
"cartocss_version": "2.3.0",
|
||||
// keep them for now
|
||||
"widgets": {
|
||||
"names": {
|
||||
"type": "list",
|
||||
"options": {
|
||||
"columns": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"analyses": [
|
||||
{
|
||||
"id": "cdb-layer-source-0",
|
||||
"type": "source",
|
||||
"params": {
|
||||
"query": "select * from test_table"
|
||||
}
|
||||
}
|
||||
],
|
||||
"dataviews": {
|
||||
"names": {
|
||||
"source": {
|
||||
"id": "cdb-layer-source-0"
|
||||
},
|
||||
"type": "list",
|
||||
"options": {
|
||||
"columns": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"version": "1.4.0",
|
||||
"layers": [
|
||||
{
|
||||
"type": "mapnik",
|
||||
"options": {
|
||||
"sql": "select * from populated_places_simple_reduced",
|
||||
"cartocss": "#layer { marker-fill: red; marker-width: 32; marker-allow-overlap: true; }",
|
||||
"cartocss_version": "2.3.0",
|
||||
"widgets": {
|
||||
"country_places_count": {
|
||||
"type": "aggregation",
|
||||
"options": {
|
||||
"column": "adm0_a3",
|
||||
"aggregation": "count"
|
||||
}
|
||||
},
|
||||
"country_places_histogram": {
|
||||
"type": "histogram",
|
||||
"options": {
|
||||
"column": "pop_max"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"version": "1.4.0",
|
||||
"layers": [
|
||||
{
|
||||
"type": "mapnik",
|
||||
"options": {
|
||||
"source": {
|
||||
"id": "cdb-layer-source-0"
|
||||
},
|
||||
"cartocss": "#layer { marker-fill: red; marker-width: 32; marker-allow-overlap: true; }",
|
||||
"cartocss_version": "2.3.0",
|
||||
// keep them for now
|
||||
"widgets": {
|
||||
"country_places_count": {
|
||||
"type": "aggregation",
|
||||
"options": {
|
||||
"column": "adm0_a3",
|
||||
"aggregation": "count"
|
||||
}
|
||||
},
|
||||
"country_places_histogram": {
|
||||
"type": "histogram",
|
||||
"options": {
|
||||
"column": "pop_max"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"analyses": [
|
||||
{
|
||||
"id": "cdb-layer-source-0",
|
||||
"type": "source",
|
||||
"params": {
|
||||
"query": "select * from populated_places_simple_reduced"
|
||||
}
|
||||
}
|
||||
],
|
||||
"dataviews": {
|
||||
"country_places_count": {
|
||||
"source": {
|
||||
"id": "cdb-layer-source-0"
|
||||
},
|
||||
"type": "aggregation",
|
||||
"options": {
|
||||
"column": "adm0_a3",
|
||||
"aggregation": "count"
|
||||
}
|
||||
},
|
||||
"country_places_histogram": {
|
||||
"source": {
|
||||
"id": "cdb-layer-source-0"
|
||||
},
|
||||
"type": "histogram",
|
||||
"options": {
|
||||
"column": "pop_max"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var user = 'wadus';
|
||||
function params() {
|
||||
return {};
|
||||
}
|
||||
function context() {
|
||||
return {};
|
||||
}
|
||||
|
||||
var dataviewsMapConfigAdapter = new DataviewsMapConfigAdapter();
|
||||
|
||||
widgetsMapConfigs.forEach(function(mapConfig, index) {
|
||||
it('should adapt widgets ' + index, function(done) {
|
||||
dataviewsMapConfigAdapter.getMapConfig(user, mapConfig.input, params(), context(), function(err, result) {
|
||||
assert.deepEqual(result, mapConfig.expected);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,129 @@
|
||||
require('../../../../support/test_helper');
|
||||
var util = require('util');
|
||||
|
||||
var assert = require('../../../../support/assert');
|
||||
var BboxFilter = require('../../../../../lib/cartodb/models/filter/bbox');
|
||||
|
||||
var MAX_EXTENT_MERCATOR_REF = [
|
||||
-BboxFilter.LONGITUDE_MAX_VALUE,
|
||||
-BboxFilter.LATITUDE_MAX_VALUE,
|
||||
BboxFilter.LONGITUDE_MAX_VALUE,
|
||||
BboxFilter.LATITUDE_MAX_VALUE
|
||||
];
|
||||
|
||||
describe('Bounding box filter', function() {
|
||||
|
||||
describe('wrap longitude', function() {
|
||||
var longitudesScenarios = [
|
||||
[[0, 90], [0, 90]],
|
||||
[[-90, 0], [-90, 0]],
|
||||
[[-90, 90], [-90, 90]],
|
||||
[[-990, -720], [90, 360]],
|
||||
[[810, 1080], [90, 360]],
|
||||
[[-180, 180], [-180, 180]]
|
||||
];
|
||||
|
||||
longitudesScenarios.forEach(function(scenario) {
|
||||
it(util.format('should adjust from %j to %j', scenario[0], scenario[1]), function() {
|
||||
var we = BboxFilter.adjustLongitudeRange(scenario[0]);
|
||||
|
||||
assert.equal(
|
||||
we[0], scenario[1][0],
|
||||
util.format('west, got %d, expected %d, scenario: %s',
|
||||
we[1], scenario[1][1], JSON.stringify(scenario)
|
||||
)
|
||||
);
|
||||
assert.equal(
|
||||
we[1], scenario[1][1],
|
||||
util.format('east, got %d, expected %d, scenario: %s',
|
||||
we[1], scenario[1][1], JSON.stringify(scenario)
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createFilter(bbox) {
|
||||
return new BboxFilter({}, { bbox: bbox.join(',') });
|
||||
}
|
||||
|
||||
function createRef(bbox) {
|
||||
return bbox;
|
||||
// return mercator.forward([bbox[0], bbox[1]]).concat(mercator.forward([bbox[2], bbox[3]]));
|
||||
}
|
||||
|
||||
|
||||
it('happy case', function() {
|
||||
var bbox = [-90, -45, 90, 45];
|
||||
var bboxFilter = createFilter(bbox);
|
||||
assert.equal(bboxFilter.bboxes.length, 1);
|
||||
assert.deepEqual(bboxFilter.bboxes[0], createRef(bbox));
|
||||
});
|
||||
|
||||
describe('latitude', function() {
|
||||
it('(hardcoded) clipping out of bounds', function() {
|
||||
var bbox = [-180, -90, 180, 90];
|
||||
var bboxFilter = createFilter(bbox);
|
||||
assert.equal(bboxFilter.bboxes.length, 1);
|
||||
assert.deepEqual(bboxFilter.bboxes[0], MAX_EXTENT_MERCATOR_REF);
|
||||
});
|
||||
|
||||
it('clipping out of bounds', function() {
|
||||
var bbox = [-180, -90, 180, 90];
|
||||
var bboxFilter = createFilter(bbox);
|
||||
assert.equal(bboxFilter.bboxes.length, 1);
|
||||
assert.deepEqual(
|
||||
bboxFilter.bboxes[0],
|
||||
createRef([-180, -BboxFilter.LATITUDE_MAX_VALUE, 180, BboxFilter.LATITUDE_MAX_VALUE])
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('longitude', function() {
|
||||
it('generating multiple bbox for east out of bounds', function() {
|
||||
var bbox = [90, -45, 360, 45];
|
||||
var bboxFilter = createFilter(bbox);
|
||||
|
||||
assert.equal(bboxFilter.bboxes.length, 2, JSON.stringify([bboxFilter.bboxes, bbox]));
|
||||
|
||||
assert.deepEqual(
|
||||
bboxFilter.bboxes[0],
|
||||
createRef([90, -45, 180, 45])
|
||||
);
|
||||
assert.deepEqual(
|
||||
bboxFilter.bboxes[1],
|
||||
createRef([-180, -45, 0, 45])
|
||||
);
|
||||
});
|
||||
|
||||
it('generating multiple bbox for east out of bounds', function() {
|
||||
var bbox = [-270, -45, 0, 45];
|
||||
var bboxFilter = createFilter(bbox);
|
||||
|
||||
assert.equal(bboxFilter.bboxes.length, 2);
|
||||
|
||||
assert.deepEqual(
|
||||
bboxFilter.bboxes[0],
|
||||
createRef([90, -45, 180, 45])
|
||||
);
|
||||
assert.deepEqual(
|
||||
bboxFilter.bboxes[1],
|
||||
createRef([-180, -45, 0, 45])
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('out of bounds', function() {
|
||||
it('wraps longitude', function () {
|
||||
var bbox = [-190, -45, 190, 45];
|
||||
var bboxFilter = createFilter(bbox);
|
||||
|
||||
assert.equal(bboxFilter.bboxes.length, 1);
|
||||
|
||||
assert.deepEqual(
|
||||
bboxFilter.bboxes[0],
|
||||
createRef([-180, -45, 180, 45])
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user