From 2970e34a48408ce902948b8a7d6ca0018d037f09 Mon Sep 17 00:00:00 2001 From: liamcottle Date: Tue, 12 Mar 2024 18:31:17 +1300 Subject: [PATCH] implement meshtastic map --- package-lock.json | 786 ++++++++++++++++++++++++++++++++++++++++++ package.json | 9 +- src/index.js | 81 +++++ src/public/icon.png | Bin 0 -> 17271 bytes src/public/index.html | 603 ++++++++++++++++++++++++++++++++ 5 files changed, 1477 insertions(+), 2 deletions(-) create mode 100644 package-lock.json create mode 100644 src/index.js create mode 100644 src/public/icon.png create mode 100644 src/public/index.html diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..1cf8ce6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,786 @@ +{ + "name": "meshtastic-map", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "meshtastic-map", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^1.6.7", + "express": "^4.18.3", + "node-cache": "^5.1.2" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", + "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + } + } +} diff --git a/package.json b/package.json index 4f0c0a5..af1c061 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,15 @@ "name": "meshtastic-map", "version": "1.0.0", "description": "", - "main": "index.js", + "main": "src/index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", - "license": "ISC" + "license": "ISC", + "dependencies": { + "axios": "^1.6.7", + "express": "^4.18.3", + "node-cache": "^5.1.2" + } } diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..d0d7b18 --- /dev/null +++ b/src/index.js @@ -0,0 +1,81 @@ +const path = require('path'); +const axios = require('axios'); +const express = require('express'); +const NodeCache = require("node-cache"); +const cache = new NodeCache(); + +const app = express(); + +// serve files inside the public folder from / +app.use('/', express.static(path.join(__dirname, 'public'))); + +async function getCached(key, ttl, callback) { + + // find data from cache + let data = cache.get(key); + + // update cache + if(!data){ + data = await callback(); + cache.set(key, data, ttl); + } + + // get expiration time in seconds + const cacheTtl = cache.getTtl(key); + const expiresIn = cacheTtl != null + ? Math.ceil((cacheTtl - Date.now()) / 1000) + : 0; + + // return data + return [ data, expiresIn ]; + +} + +app.get('/', async (req, res) => { + res.sendFile(path.join(__dirname, 'public/index.html')); +}); + +app.get('/api', async (req, res) => { + + const links = [ + { + "path": "/api", + "description": "This page", + }, + { + "path": "/api/v1/nodes", + "description": "Meshtastic nodes in JSON format.", + }, + ]; + + const html = links.map((link) => { + return `
  • ${link.path} - ${link.description}
  • `; + }).join(""); + + res.send(html); + +}); + +app.get('/api/v1/nodes', async (req, res) => { + try { + + // get nodes from cache, or retrieve from api + const [ nodes, expiresIn ] = await getCached('nodes', 10, async () => { + const response = await axios.get("https://meshmap.net/nodes2.json"); + return response.data; + }); + + res.json({ + expires_in: expiresIn, + nodes: nodes, + }); + + } catch(err) { + console.error(err); + res.status(500).json({ + message: "Something went wrong, try again later.", + }); + } +}); + +app.listen(8080); diff --git a/src/public/icon.png b/src/public/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ef45782b9b1b2480188c04f16cdcf1f6e1c84bb4 GIT binary patch literal 17271 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 P7#xt2mSVa5yU+gvE)Yks literal 0 HcmV?d00001 diff --git a/src/public/index.html b/src/public/index.html new file mode 100644 index 0000000..68de9aa --- /dev/null +++ b/src/public/index.html @@ -0,0 +1,603 @@ + + + + + + Interactive Meshtastic Map + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + +
    + +
    +
    + + + + + + + \ No newline at end of file