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 module.exports = function(opts, callback) {
23 var app = express().disable("x-powered-by"),
24 tilelive = require("tilelive-cache")(require("tilelive"), {
25 size: process.env.CACHE_SIZE || opts.cacheSize,
26 sources: process.env.SOURCE_CACHE_SIZE || opts.sourceCacheSize
29 app.enable('trust proxy');
31 callback = callback || function() {};
33 // load and register tilelive modules
34 require("tilelive-modules/loader")(tilelive, opts);
36 if (process.env.NODE_ENV !== "production") {
37 // TODO configurable logging per-style
38 app.use(morgan("dev"));
42 app.use(responseTime());
44 app.use(express.static(path.join(__dirname, "public")));
45 app.use(express.static(path.join(__dirname, "bower_components")));
46 app.use(serve(tilelive, opts.uri));
48 tilelive.load(opts.uri, function(err, src) {
53 return tessera.getInfo(src, function(err, info) {
59 if (info.format === "pbf") {
60 app.use("/_", serve(tilelive, "xray+" + opts.uri));
61 app.use("/_", express.static(path.join(__dirname, "public")));
62 app.use("/_", express.static(path.join(__dirname, "bower_components")));
69 var configPath = path.resolve(opts.config),
70 stats = fs.statSync(configPath),
74 config = require(configPath);
75 } else if (stats.isDirectory()) {
76 config = fs.readdirSync(configPath)
77 .filter(function(filename) {
78 return path.extname(filename) === ".json";
80 .reduce(function(config, filename) {
81 var localConfig = require(path.join(configPath, filename));
83 return Object.keys(localConfig).reduce(function(config, k) {
84 config[k] = localConfig[k];
91 Object.keys(config).forEach(function(prefix) {
92 if (config[prefix].timing !== false) {
93 app.use(prefix, responseTime());
96 if (config[prefix].cors !== false) {
97 app.use(prefix, cors());
100 //app.use(prefix, express.static(path.join(__dirname, "public")));
101 //app.use(prefix, express.static(path.join(__dirname, "bower_components")));
102 app.use(prefix, serve(tilelive, config[prefix]));
105 // serve index.html even on the root
106 app.use("/", express.static(path.join(__dirname, "public")));
107 app.use("/", express.static(path.join(__dirname, "bower_components")));
109 // aggregate index.json on root for multiple sources
110 app.get("/index.json", function(req, res, next) {
112 Object.keys(config).forEach(function(prefix) {
113 queue.push(function(callback) {
114 var url = config[prefix].source || config[prefix];
115 tilelive.load(url, function(err, source) {
120 tessera.getInfo(source, function(err, info) {
126 tilePath = config[prefix].tilePath || "/{z}/{x}/{y}.{format}";
128 if (config[prefix].domains && config[prefix].domains.length > 0) {
129 domains = config[prefix].domains.split(',');
132 if (prefix.length > 1) {
133 info.basename = prefix.substr(1);
136 info.tiles = serve.getTileUrls(domains, req.headers.host, prefix,
137 tilePath, info.format,
138 req.query.key, req.protocol);
139 info.tilejson = "2.0.0";
141 callback(null, info);
146 return async.parallel(queue, function(err, results) {
147 return res.send(results);
152 app.listen(process.env.PORT || opts.port, function() {
153 console.log("Listening at http://%s:%d/", this.address().address, this.address().port);