4 // increase the libuv threadpool size to 1.5x the number of logical CPUs.
5 process.env.UV_THREADPOOL_SIZE = process.env.UV_THREADPOOL_SIZE || Math.ceil(Math.max(4, require('os').cpus().length * 1.5));
7 var fs = require("fs"),
8 path = require("path");
10 var async = require("async"),
11 cors = require("cors"),
12 debug = require("debug"),
13 express = require("express"),
14 morgan = require("morgan"),
15 responseTime = require("response-time");
17 var serve = require("./lib/app"),
18 tessera = require("./lib/index");
20 debug = debug("tessera");
22 var tmstyle = require('tilelive-tmstyle');
23 var tilelivevector = require('tilelive-vector');
24 var mbtiles = require('mbtiles');
26 module.exports = function(opts, callback) {
27 var app = express().disable("x-powered-by"),
28 tilelive = require("tilelive-cache")(require("tilelive"), {
29 size: process.env.CACHE_SIZE || opts.cacheSize,
30 sources: process.env.SOURCE_CACHE_SIZE || opts.sourceCacheSize
33 app.enable('trust proxy');
35 callback = callback || function() {};
37 // load and register tilelive modules
38 require("tilelive-modules/loader")(tilelive, opts);
39 console.log('tilelive : ' + tilelive.protocols);
42 require: ['tilelive-vector', 'tilelive-tmstyle', 'mbtiles']
44 require("tilelive-modules/loader")(tilelive, testOpts);
45 console.log('tilelive2 : ' + tilelive.protocols);
46 if (process.env.NODE_ENV !== "production") {
47 // TODO configurable logging per-style
48 app.use(morgan("dev"));
52 app.use(responseTime());
54 app.use(express.static(path.join(__dirname, "public")));
55 //app.use(express.static(path.join(__dirname, "bower_components")));
56 app.use(serve(tilelive, opts.uri));
58 tilelive.load(opts.uri, function(err, src) {
63 return tessera.getInfo(src, function(err, info) {
69 if (info.format === "pbf") {
70 app.use("/_", serve(tilelive, "xray+" + opts.uri));
71 app.use("/_", express.static(path.join(__dirname, "public")));
72 //app.use("/_", express.static(path.join(__dirname, "bower_components")));
79 var configPath = path.resolve(opts.config),
80 stats = fs.statSync(configPath),
84 config = require(configPath);
85 } else if (stats.isDirectory()) {
86 config = fs.readdirSync(configPath)
87 .filter(function(filename) {
88 return path.extname(filename) === ".json";
90 .reduce(function(config, filename) {
91 var localConfig = require(path.join(configPath, filename));
93 return Object.keys(localConfig).reduce(function(config, k) {
94 config[k] = localConfig[k];
101 Object.keys(config).forEach(function(prefix) {
102 if (config[prefix].timing !== false) {
103 app.use(prefix, responseTime());
106 if (config[prefix].cors !== false) {
107 app.use(prefix, cors());
110 //app.use(prefix, express.static(path.join(__dirname, "public")));
111 //app.use(prefix, express.static(path.join(__dirname, "bower_components")));
112 app.use(prefix, serve(tilelive, config[prefix]));
115 // serve index.html even on the root
116 app.use("/", express.static(path.join(__dirname, "public")));
117 //app.use("/", express.static(path.join(__dirname, "bower_components")));
119 // aggregate index.json on root for multiple sources
120 app.get("/index.json", function(req, res, next) {
122 Object.keys(config).forEach(function(prefix) {
123 queue.push(function(callback) {
124 var url = config[prefix].source || config[prefix];
125 tilelive.load(url, function(err, source) {
130 tessera.getInfo(source, function(err, info) {
136 tilePath = config[prefix].tilePath || "/{z}/{x}/{y}.{format}";
138 if (config[prefix].domains && config[prefix].domains.length > 0) {
139 domains = config[prefix].domains.split(',');
142 if (prefix.length > 1) {
143 info.basename = prefix.substr(1);
146 info.tiles = serve.getTileUrls(domains, req.headers.host, prefix,
147 tilePath, info.format,
148 req.query.key, req.protocol);
149 info.tilejson = "2.0.0";
151 callback(null, info);
156 return async.parallel(queue, function(err, results) {
157 return res.send(results);
162 app.listen(process.env.PORT || opts.port, function() {
163 console.log("Listening at http://%s:%d/", this.address().address, this.address().port);