{"version":3,"sources":["jsdelivr-header.js","/npm/csweb-tile@0.1.2/index.ts"],"names":[],"mappings":"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","file":"/npm/csweb-tile@0.1.2/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/csweb-tile@0.1.2/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import http    = require('http');\r\nimport path    = require('path');\r\nimport fs      = require('fs');\r\nimport express = require('express');\r\nimport request = require('request');\r\nimport mkdirp  = require('mkdirp');\r\nimport rmdir   = require('rimraf');\r\nimport async   = require('async');\r\n\r\nvar md5      = require('md5'),\r\n    tilelive = require('tilelive');\r\n\r\n//require('tilelive-bridge').registerProtocols(tilelive);\r\n\r\n// Iterate over all sub-folders in sources.\r\n// Each sub-folder's name needs to match the tilelive module name,\r\n// e.g. all mbtiles need to be in the mbtiles sub folder, as that \r\n// is the name of the corresponding node package.\r\n// Register each sub-folder name that is not empty\r\n// In that folder, open all files.\r\n\r\n/** Interface to describe a tile source */\r\nexport interface ITileSource {\r\n    /** Protocol to use for loading the tile source */\r\n    protocol: string;\r\n    /** Absolute or relative path to the file. If not absolute, the current folder is used. */\r\n    path:     string;\r\n    /** Fallback URI, e.g. when no tile can be found, you can redirect it to this URL. */\r\n    fallbackUri: string;\r\n}\r\n\r\n/** Options */\r\nexport interface ITileSourceOptions {\r\n    /** If true, set headers to enable CORRS. */\r\n    corrs?: boolean;\r\n    /** source folder. If not set, uses ./sources */\r\n    sources?: string;\r\n    /** Specify a source manually by setting its path. If set, ignores 'sources' folder. */\r\n    tileSources?: ITileSource[];\r\n    /** Path to the cache folder, if any. */\r\n    cache?: string;\r\n};\r\n\r\nexport class TileSource {\r\n    cacheFolder: string;\r\n\r\n    constructor(private app: express.Express, options?: ITileSourceOptions) {\r\n        var defaultOptions = <ITileSourceOptions> {\r\n            corrs: true,\r\n            sources: path.join(__dirname, 'tilesources'),\r\n            tileSources: [],\r\n            cache: path.join(__dirname, 'cache')\r\n        };\r\n        if (!options) options = defaultOptions;\r\n\r\n        // enable corrs\r\n        if ((options && typeof options.corrs !== 'undefined' && options.corrs) || defaultOptions.corrs) {\r\n            app.use(function(req, res, next) {\r\n                res.header('Access-Control-Allow-Origin', '*');\r\n                res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');\r\n                next();\r\n            });\r\n        }\r\n\r\n        if (options.cache) {\r\n            this.cacheFolder = options.cache;\r\n            if (!fs.existsSync(this.cacheFolder)) {\r\n               mkdirp(this.cacheFolder, err => {\r\n                   if (err) console.error('Error creating cache folder: ' + err);\r\n               });\r\n            }\r\n        }\r\n\r\n        if (options.tileSources && options.tileSources.length > 0) {\r\n            // Source files are explicitly stated\r\n            options.tileSources.forEach(source => {\r\n                this.load(source.protocol, source.path, source.fallbackUri, this.pathIsAbsolute(source.path) ? '' : __dirname, () => {});\r\n            });\r\n        } else {\r\n            // Folder that contains the source map files.\r\n            var tileFolder = options.sources || defaultOptions.sources;\r\n            fs.readdir(tileFolder, (err, protocols) => {\r\n                if (err) {\r\n                    console.log(`Error reading ${tileFolder}: ` + err);\r\n                    return;\r\n                }\r\n                if (!protocols || protocols.length === 0) {\r\n                    console.log(`No sources found in folder ${tileFolder}.`);\r\n                    return;\r\n                }\r\n\r\n                protocols.forEach(protocol => {\r\n                    let sourceFolder = path.join(tileFolder, protocol);\r\n                    fs.readdir(sourceFolder, (err, files) => {\r\n                        if (err) {\r\n                            console.log(`Error reading folder ${protocol}: ${err}`);\r\n                            return;\r\n                        }\r\n                        var tasks: AsyncFunction<void>[] = [];\r\n                        files.forEach(file => {\r\n                            switch (protocol) {\r\n                                case 'tm2':\r\n                                // case 'mbtiles':\r\n                                // case 'mapnik':\r\n                                // case 'carto+file':\r\n                                    tasks.push((cb: Function) => {\r\n                                        this.load('utfgrid+' + protocol, file, '', sourceFolder, cb);\r\n                                    });\r\n                                    break;\r\n                            }\r\n                            tasks.push((cb: Function) => {\r\n                                this.load(protocol, file, '', sourceFolder, cb);\r\n                            });\r\n                        });\r\n                        async.series<void>(tasks);\r\n                    });\r\n                });\r\n            });\r\n        }\r\n    }\r\n\r\n    private protocols: string[] = [];\r\n    /** Register the protocol. */\r\n    private registerProtocol(protocol: string) {\r\n        if (this.protocols.indexOf(protocol) >= 0) return;\r\n        this.protocols.push(protocol);\r\n        if (/utfgrid/.test(protocol)) {\r\n            if (this.protocols.indexOf('utfgrid') < 0) {\r\n                this.protocols.push('utfgrid');\r\n                this.registerProtocol('mbtiles');\r\n                require('tilelive-vector'  ).registerProtocols(tilelive);\r\n                require('tilelive-bridge'  ).registerProtocols(tilelive);\r\n                require('tilejson'         ).registerProtocols(tilelive);\r\n                require('tilelive-utfgrid' )(tilelive).registerProtocols(tilelive);\r\n                require('tilelive-tmsource')(tilelive).registerProtocols(tilelive);\r\n                require('tilelive-http'    )(tilelive).registerProtocols(tilelive);\r\n            }\r\n            console.log(`Registering protocol ${protocol}.`);\r\n            this.registerProtocol(protocol.replace('utfgrid+', ''));\r\n            return;\r\n        }\r\n        switch (protocol) {\r\n            case 'mapnik':\r\n                require('tilelive-mapnik').registerProtocols(tilelive);\r\n                break;\r\n            case 'tm2':\r\n                require('tilelive-tmstyle' )(tilelive).registerProtocols(tilelive);\r\n                break;\r\n            case 'mbtiles':\r\n                require('mbtiles').registerProtocols(tilelive);\r\n                break;\r\n            default:\r\n                require(protocol).registerProtocols(tilelive);\r\n                break;\r\n        }\r\n        console.log(`Registering protocol ${protocol}.`);\r\n    }\r\n\r\n    /** \r\n     * Returns true if your path is absolute.\r\n     * See http://stackoverflow.com/questions/21698906/how-to-check-if-a-path-is-absolute-or-relative\r\n     */\r\n    private pathIsAbsolute(yourPath: string) {\r\n        return path.resolve(yourPath) === path.normalize(yourPath).replace( RegExp(path.sep + '$'), '');\r\n    }\r\n\r\n    /** \r\n     * Load a file using the proper protocol.\r\n     * NOTE: Only tested for mbtiles.\r\n     * \r\n     * @param  {string} protocol\r\n     * @param  {string} file\r\n     * @param  {string} fallbackUri If specified, used to redirect clients when a lookup fails\r\n     * @param  {string} sourceFolder Source folder. If not specified, the file is absolute.\r\n     * @param  {Function} callback Callback function to call the function asynchronously.\r\n     */\r\n    private load(protocol: string, file: string, fallbackUri: string, sourceFolder: string, callback: Function) {\r\n        if (file[0] === '_') return;\r\n        this.registerProtocol(protocol);\r\n        // var re = new RegExp('/[a-zA-Z\\d]*\\/(?<z>\\d+)\\/(?<x>\\d+)\\/(?<y>\\d+)\\./');\r\n        let sourceFile = sourceFolder ? path.join(sourceFolder, file) : file;\r\n\r\n        var tileliveSource: string;\r\n        switch (protocol) {\r\n            case 'tm2':\r\n                // NOTE I need to remove the drive (host) name, otherwise tmstyle cannot load the data.yml file.\r\n                tileliveSource = `tmstyle://${sourceFile.replace(/(.:)/i, '')}`;\r\n                break;\r\n            case 'utfgrid+tm2':\r\n                // NOTE I need to remove the drive (host) name, otherwise tmstyle cannot load the data.yml file.\r\n                tileliveSource = `utfgrid+tmstyle://${sourceFile.replace(/(.:)/i, '')}`;\r\n                break;\r\n            default:\r\n                tileliveSource = `${protocol}://${sourceFile}`;\r\n                break;\r\n        }\r\n\r\n        var isUtfGrid = /^utfgrid/.test(protocol);\r\n\r\n        tilelive.load(tileliveSource, (err, source) => {\r\n            // console.log(`Loading ${tileliveSource}`);\r\n            if (err) {\r\n                throw err;\r\n            }\r\n            let name: string;\r\n            switch (protocol) {\r\n                case 'utfgrid+mapnik':\r\n                case 'mapnik':\r\n                    name = path.basename(file, '.xml');\r\n                    break;\r\n                case 'utfgrid+tm2':\r\n                case 'tm2':\r\n                    name = path.basename(file, '.tm2');\r\n                    break;\r\n                case 'utfgrid+mbtiles':\r\n                case 'mbtiles':\r\n                    name = path.basename(file, '.mbtiles');\r\n                    break;\r\n            }\r\n\r\n            if (this.cacheFolder) {\r\n                var cachedTileFolder = path.join(this.cacheFolder, name);\r\n                this.checkCache(cachedTileFolder, sourceFile);\r\n            }\r\n\r\n            var ext = isUtfGrid ? 'grid.json' : 'png';\r\n\r\n            var urlPath = `/${name}/:z/:x/:y.${ext}`;\r\n            console.log(`Exposing ${tileliveSource} service at ${urlPath}.`);\r\n\r\n            this.app.get(urlPath, (req, res) => {\r\n                let z = +req.params.z,\r\n                    x = +req.params.x,\r\n                    y = +req.params.y;\r\n\r\n                var dir: string,\r\n                    filename: string;\r\n\r\n                if (this.cacheFolder) {\r\n                    dir = `${cachedTileFolder}/${z}/${x}`;\r\n                    filename = `${dir}/${y}.${ext}`;\r\n                    fs.exists(filename, exists => {\r\n                        if (exists) {\r\n                            res.sendFile(filename);\r\n                        } else {\r\n                            this.getTile(source, req, res, fallbackUri, dir, filename, x, y, z);\r\n                        }\r\n                    });\r\n                } else {\r\n                    this.getTile(source, req, res, fallbackUri, dir, filename, x, y, z);\r\n                }\r\n            });\r\n            callback();\r\n        });\r\n    }\r\n\r\n    /** Get a tile from mapnik */\r\n    private getTile(source, req: express.Request, res: express.Response, fallbackUri: string, dir: string, filename: string, x: number, y: number, z: number) {\r\n        source.getTile(z, x, y, (err, tile, headers) => {\r\n            if (err) {\r\n                if (fallbackUri) {\r\n                    var ext = path.extname(req.url);\r\n                    var newUrl = `${fallbackUri}/${z}/${x}/${y}${ext}`;\r\n                    request(newUrl).pipe(res);\r\n                    // A redirect in the client does not work for Cesium: CORS exception\r\n                    // res.redirect(`${fallbackUri}/${z}/${x}/${y}${ext}`); // http://stackoverflow.com/questions/11355366/nodejs-redirect-url\r\n                } else {\r\n                    res.status(404);\r\n                    res.send(err.message);\r\n                    // console.log('Error getting %s: tile %d, %d, %d', sourceFile, z, x, y);\r\n                    console.log(err.message);\r\n                }\r\n            } else {\r\n                if (this.cacheFolder) {\r\n                    mkdirp(dir, err => {\r\n                        if (err) {\r\n                            console.error(`Error creating cache folder (${dir}): ${err}`);\r\n                        } else {\r\n                            fs.writeFile(filename, headers['Content-Type'] === 'application/json' ? JSON.stringify(tile) : tile, err => {\r\n                                if (err) throw err;\r\n                                //console.log('Saved map image to ' + filename);\r\n                            });\r\n                        }\r\n                    });\r\n                }\r\n                res.set(headers);\r\n                res.send(tile);\r\n            }\r\n        });\r\n    }\r\n\r\n    /** \r\n     * Check whether the cache is still valid, otherwise, delete it. \r\n     * \r\n     * We compute the hash of the style file and if it doesn't exist, we clear the cache and write it to file as [hash].md5. \r\n     * If the file exists, it means that we are dealing with the same source file, and we don't need to do anything.\r\n    */\r\n    private checkCache(cacheFolder: string, sourceFile: string) {\r\n        fs.readFile(sourceFile, (err, buf) => {\r\n            let hash = md5(buf);\r\n            console.log('MD5 hash: ' + hash);\r\n            var md5file = path.join(cacheFolder, hash + '.md5');\r\n            fs.exists(md5file, exists => {\r\n                if (exists) return;\r\n                rmdir(cacheFolder, err => {\r\n                    if (err) console.error('Error deleting cache: ' + err.message);\r\n                    mkdirp(cacheFolder, err => {\r\n                        if (err) {\r\n                            console.error(`Error creating cache folder (${cacheFolder}): ${err.message}`);\r\n                        } else {\r\n                            fs.writeFile(md5file, '', err => {\r\n                                if (err) console.error('Error writing hash: ' + err.message);\r\n                            });\r\n                        }\r\n                    });\r\n                });\r\n            });\r\n        });\r\n    }\r\n\r\n}\r\n"]}