Compare commits

..

13 Commits

Author SHA1 Message Date
77a3a5e288 remove unused docker directory
Some checks failed
Build Docker containers / Build (push) Failing after 9s
2025-04-15 15:51:55 -04:00
e44c578195 update dockerfiles 2025-04-15 15:51:46 -04:00
911983d250 add directory for common assets 2025-04-15 15:51:27 -04:00
c0a59bd30a update docker-compose for new images 2025-04-15 15:41:40 -04:00
4173a97e51 update for new images 2025-04-15 15:39:40 -04:00
8eaf49fd54 cleanup root directory 2025-04-15 15:36:26 -04:00
7f583e73b0 remove src directory 2025-04-15 15:35:04 -04:00
f20031e2ea add mqtt listener 2025-04-15 15:34:49 -04:00
2da0ee24e4 add cli for admin tools 2025-04-15 15:33:50 -04:00
4c39cee484 update docker and git ignore 2025-04-15 15:33:30 -04:00
196063c23b add webapp, move frontend to webapp folder 2025-04-15 15:33:08 -04:00
f97b3b5185 move protos to root 2025-04-15 15:31:23 -04:00
95cf93d747 remove service files 2025-04-15 15:28:29 -04:00
263 changed files with 2379 additions and 32029 deletions

View File

@ -1,2 +1,10 @@
.env
node_modules
*/prisma
!common/prisma
*/node_modules
*/protos
!common/protos
*/Dockerfile
*/.dockerignore
webapp/frontend/node_modules

View File

@ -12,7 +12,14 @@ jobs:
run: docker login git.arinity.org -u matt -p ${{ secrets.DOCKER_PUSH_TOKEN }}
- name: Checkout repository
uses: actions/checkout@v4
- name: Build docker image
run: docker build -t git.arinity.org/ctmesh/map:latest .
- name: Push image
run: docker push git.arinity.org/ctmesh/map:latest
- name: Build web app image
run: docker build -f webapp/Dockerfile -t git.arinity.org/ctmesh:map-web:latest .
- name: Build mqtt listener image
run: docker build -f mqtt/Dockerfile -t git.arinity.org/ctmesh:map-mqtt:latest .
- name: Build cli image
run: docker build -f cli/Dockerfile -t git.arinity.org/ctmesh:map-cli:latest .
- name: Push images
run: |
docker push git.arinity.org/ctmesh:map-web:latest
docker push git.arinity.org/ctmesh/map-mqtt:latest
docker push git.arinity.org/ctmesh:map-cli:latest

4
.gitignore vendored
View File

@ -1,4 +1,8 @@
.idea/
node_modules
*/prisma
*/proto
*/protos
*/dist
# Keep environment variables out of version control
.env

View File

@ -1,10 +0,0 @@
FROM node:lts
# add project files to /app
ADD ./ /app
WORKDIR /app
# install node dependencies
RUN npm install
EXPOSE 8080

12
cli/Dockerfile Normal file
View File

@ -0,0 +1,12 @@
FROM node:lts-alpine3.17
# add project files to /app
ADD ./cli /app
ADD ./common /app
ADD ./mqtt/utils /app/utils
WORKDIR /app
# install node dependencies
RUN npm install && npx prisma generate
ENTRYPOINT ["node", "index.js"]

18
cli/package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "mqtt",
"version": "1.0.0",
"main": "index.js",
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"@prisma/client": "^5.11.0",
"command-line-args": "^5.2.1",
"command-line-usage": "^7.0.1",
"mqtt": "^5.11.0",
"protobufjs": "^7.5.0"
},
"devDependencies": {
"prisma": "^5.10.2"
}
}

8
common/entrypoint.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
set -e
echo "Running migrations"
npx prisma migrate deploy
echo "Starting application"
node index.js "$@"

View File

@ -2,28 +2,26 @@ services:
# listens to mqtt packets and saves to database
meshtastic-mqtt:
container_name: meshtastic-mqtt
image: git.arinity.org/ctmesh/map:latest
image: git.arinity.org/ctmesh/map-mqtt:latest
depends_on:
database:
condition: service_healthy
command: /app/docker/mqtt.sh
command: "--mqtt-topic=msh/US/#"
environment:
DATABASE_URL: "mysql://root:password@database:3306/meshtastic-map?connection_limit=100"
MQTT_OPTS: "--mqtt-broker-url=" # add any custom mqtt.js options here
# runs the web map ui
meshtastic-map:
container_name: meshtastic-map
image: git.arinity.org/ctmesh/map:latest
image: git.arinity.org/ctmesh/map-web:latest
depends_on:
database:
condition: service_healthy
command: /app/docker/map.sh
command: "--port=8080"
ports:
- 8080:8080/tcp
environment:
DATABASE_URL: "mysql://root:password@database:3306/meshtastic-map?connection_limit=100"
MAP_OPTS: "" # add any custom index.js options here
# runs the database to store everything from mqtt
database:

View File

@ -1,7 +0,0 @@
#!/bin/sh
echo "Running migrations"
npx prisma migrate dev
echo "Starting map ui"
exec node src/index.js ${MAP_OPTS}

View File

@ -1,7 +0,0 @@
#!/bin/sh
echo "Running migrations"
npx prisma migrate dev
echo "Starting mqtt listener"
exec node src/mqtt.js ${MQTT_OPTS}

View File

@ -1,10 +0,0 @@
# Donate
Thank you for considering donating, this helps support my work on this project 😁
## How can I donate?
- Bitcoin: bc1qy22smke8n4c54evdxmp7lpy9p0e6m9tavtlg2q
- Ethereum: 0xc64CFbA5D0BF7664158c5671F64d446395b3bF3D
- Buy me a Coffee: [https://ko-fi.com/liamcottle](https://ko-fi.com/liamcottle)
- Sponsor on GitHub: [https://github.com/sponsors/liamcottle](https://github.com/sponsors/liamcottle)

View File

@ -1,39 +0,0 @@
[Unit]
Description=meshtastic-map-mqtt
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=liamcottle
WorkingDirectory=/home/liamcottle/meshtastic-map
ExecStart=/usr/bin/env node /home/liamcottle/meshtastic-map/src/mqtt.js \
--mqtt-broker-url mqtt://127.0.0.1 \
--mqtt-username username \
--mqtt-password password \
--mqtt-client-id meshtastic.example.com \
--mqtt-topic 'msh/#' \
--collect-positions \
--collect-text-messages \
--collect-waypoints \
--ignore-direct-messages \
--purge-interval-seconds 60 \
--purge-nodes-unheard-for-seconds 604800 \
--purge-device-metrics-after-seconds 604800 \
--purge-environment-metrics-after-seconds 604800 \
--purge-map-reports-after-seconds 604800 \
--purge-neighbour-infos-after-seconds 604800 \
--purge-power-metrics-after-seconds 604800 \
--purge-positions-after-seconds 604800 \
--purge-service-envelopes-after-seconds 604800 \
--purge-text-messages-after-seconds 604800 \
--purge-traceroutes-after-seconds 604800 \
--purge-waypoints-after-seconds 604800 \
--forget-outdated-node-positions-after-seconds 604800 \
--drop-packets-not-ok-to-mqtt \
--old-firmware-position-precision 16
[Install]
WantedBy=multi-user.target

View File

@ -1,15 +0,0 @@
[Unit]
Description=meshtastic-map
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=liamcottle
WorkingDirectory=/home/liamcottle/meshtastic-map
ExecStart=/usr/bin/env node /home/liamcottle/meshtastic-map/src/index.js
[Install]
WantedBy=multi-user.target

11
mqtt/Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM node:lts-alpine3.17
# add project files to /app
ADD ./mqtt /app
ADD ./common /app
WORKDIR /app
# install node dependencies
RUN npm install && npx prisma generate
ENTRYPOINT ["/app/entrypoint.sh"]

955
mqtt/package-lock.json generated Normal file
View File

@ -0,0 +1,955 @@
{
"name": "mqtt",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mqtt",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@prisma/client": "^5.11.0",
"command-line-args": "^5.2.1",
"command-line-usage": "^7.0.1",
"mqtt": "^5.11.0",
"protobufjs": "^7.5.0"
},
"devDependencies": {
"prisma": "^5.10.2"
}
},
"node_modules/@babel/runtime": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
"integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
"license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@prisma/client": {
"version": "5.22.0",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.22.0.tgz",
"integrity": "sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==",
"hasInstallScript": true,
"license": "Apache-2.0",
"engines": {
"node": ">=16.13"
},
"peerDependencies": {
"prisma": "*"
},
"peerDependenciesMeta": {
"prisma": {
"optional": true
}
}
},
"node_modules/@prisma/debug": {
"version": "5.22.0",
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.22.0.tgz",
"integrity": "sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==",
"devOptional": true,
"license": "Apache-2.0"
},
"node_modules/@prisma/engines": {
"version": "5.22.0",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.22.0.tgz",
"integrity": "sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==",
"devOptional": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "5.22.0",
"@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
"@prisma/fetch-engine": "5.22.0",
"@prisma/get-platform": "5.22.0"
}
},
"node_modules/@prisma/engines-version": {
"version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2.tgz",
"integrity": "sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==",
"devOptional": true,
"license": "Apache-2.0"
},
"node_modules/@prisma/fetch-engine": {
"version": "5.22.0",
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.22.0.tgz",
"integrity": "sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "5.22.0",
"@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
"@prisma/get-platform": "5.22.0"
}
},
"node_modules/@prisma/get-platform": {
"version": "5.22.0",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.22.0.tgz",
"integrity": "sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "5.22.0"
}
},
"node_modules/@protobufjs/aspromise": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
"integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/base64": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/codegen": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/eventemitter": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
"integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/fetch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
"integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
"license": "BSD-3-Clause",
"dependencies": {
"@protobufjs/aspromise": "^1.1.1",
"@protobufjs/inquire": "^1.1.0"
}
},
"node_modules/@protobufjs/float": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
"integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/inquire": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
"integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/path": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
"integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/pool": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
"integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/utf8": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
"license": "BSD-3-Clause"
},
"node_modules/@types/node": {
"version": "22.14.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz",
"integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/@types/readable-stream": {
"version": "4.0.18",
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.18.tgz",
"integrity": "sha512-21jK/1j+Wg+7jVw1xnSwy/2Q1VgVjWuFssbYGTREPUBeZ+rqVFl2udq0IkxzPC0ZhOzVceUbyIACFZKLqKEBlA==",
"license": "MIT",
"dependencies": {
"@types/node": "*",
"safe-buffer": "~5.1.1"
}
},
"node_modules/@types/ws": {
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"license": "MIT",
"dependencies": {
"event-target-shim": "^5.0.0"
},
"engines": {
"node": ">=6.5"
}
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/array-back": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz",
"integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/bl": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-6.1.0.tgz",
"integrity": "sha512-ClDyJGQkc8ZtzdAAbAwBmhMSpwN/sC9HA8jxdYm6nVUbCfZbe2mgza4qh7AuEYyEPB/c4Kznf9s66bnsKMQDjw==",
"license": "MIT",
"dependencies": {
"@types/readable-stream": "^4.0.0",
"buffer": "^6.0.3",
"inherits": "^2.0.4",
"readable-stream": "^4.2.0"
}
},
"node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"license": "MIT"
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/chalk-template": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz",
"integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==",
"license": "MIT",
"dependencies": {
"chalk": "^4.1.2"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/chalk-template?sponsor=1"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
"node_modules/command-line-args": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz",
"integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==",
"license": "MIT",
"dependencies": {
"array-back": "^3.1.0",
"find-replace": "^3.0.0",
"lodash.camelcase": "^4.3.0",
"typical": "^4.0.0"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/command-line-usage": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.3.tgz",
"integrity": "sha512-PqMLy5+YGwhMh1wS04mVG44oqDsgyLRSKJBdOo1bnYhMKBW65gZF1dRp2OZRhiTjgUHljy99qkO7bsctLaw35Q==",
"license": "MIT",
"dependencies": {
"array-back": "^6.2.2",
"chalk-template": "^0.4.0",
"table-layout": "^4.1.0",
"typical": "^7.1.1"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/command-line-usage/node_modules/array-back": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz",
"integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==",
"license": "MIT",
"engines": {
"node": ">=12.17"
}
},
"node_modules/command-line-usage/node_modules/typical": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz",
"integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==",
"license": "MIT",
"engines": {
"node": ">=12.17"
}
},
"node_modules/commist": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz",
"integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==",
"license": "MIT"
},
"node_modules/concat-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
"integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
"engines": [
"node >= 6.0"
],
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.0.2",
"typedarray": "^0.0.6"
}
},
"node_modules/concat-stream/node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/event-target-shim": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
"license": "MIT",
"engines": {
"node": ">=0.8.x"
}
},
"node_modules/fast-unique-numbers": {
"version": "8.0.13",
"resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz",
"integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.23.8",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.1.0"
}
},
"node_modules/find-replace": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz",
"integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==",
"license": "MIT",
"dependencies": {
"array-back": "^3.0.1"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/help-me": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz",
"integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==",
"license": "MIT"
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "BSD-3-Clause"
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/ip-address": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
"license": "MIT",
"dependencies": {
"jsbn": "1.1.0",
"sprintf-js": "^1.1.3"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
"integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/js-sdsl"
}
},
"node_modules/jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
"license": "MIT"
},
"node_modules/lodash.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
"license": "MIT"
},
"node_modules/long": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz",
"integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==",
"license": "Apache-2.0"
},
"node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/mqtt": {
"version": "5.11.0",
"resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.11.0.tgz",
"integrity": "sha512-VDqfADTNvohwcY02NgxPb7OojIeDrNQ1q62r/DcM+bnIWY8LBi3nMTvdEaFEp6Bu4ejBIpHjJVthUEgnvGLemA==",
"license": "MIT",
"dependencies": {
"@types/readable-stream": "^4.0.18",
"@types/ws": "^8.5.14",
"commist": "^3.2.0",
"concat-stream": "^2.0.0",
"debug": "^4.4.0",
"help-me": "^5.0.0",
"lru-cache": "^10.4.3",
"minimist": "^1.2.8",
"mqtt-packet": "^9.0.2",
"number-allocator": "^1.0.14",
"readable-stream": "^4.7.0",
"reinterval": "^1.1.0",
"rfdc": "^1.4.1",
"socks": "^2.8.3",
"split2": "^4.2.0",
"worker-timers": "^7.1.8",
"ws": "^8.18.0"
},
"bin": {
"mqtt": "build/bin/mqtt.js",
"mqtt_pub": "build/bin/pub.js",
"mqtt_sub": "build/bin/sub.js"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/mqtt-packet": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.2.tgz",
"integrity": "sha512-MvIY0B8/qjq7bKxdN1eD+nrljoeaai+qjLJgfRn3TiMuz0pamsIWY2bFODPZMSNmabsLANXsLl4EMoWvlaTZWA==",
"license": "MIT",
"dependencies": {
"bl": "^6.0.8",
"debug": "^4.3.4",
"process-nextick-args": "^2.0.1"
}
},
"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==",
"license": "MIT"
},
"node_modules/number-allocator": {
"version": "1.0.14",
"resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz",
"integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==",
"license": "MIT",
"dependencies": {
"debug": "^4.3.1",
"js-sdsl": "4.3.0"
}
},
"node_modules/prisma": {
"version": "5.22.0",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-5.22.0.tgz",
"integrity": "sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==",
"devOptional": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/engines": "5.22.0"
},
"bin": {
"prisma": "build/index.js"
},
"engines": {
"node": ">=16.13"
},
"optionalDependencies": {
"fsevents": "2.3.3"
}
},
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"license": "MIT",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"license": "MIT"
},
"node_modules/protobufjs": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.0.tgz",
"integrity": "sha512-Z2E/kOY1QjoMlCytmexzYfDm/w5fKAiRwpSzGtdnXW1zC88Z2yXazHHrOtwCzn+7wSxyE8PYM4rvVcMphF9sOA==",
"hasInstallScript": true,
"license": "BSD-3-Clause",
"dependencies": {
"@protobufjs/aspromise": "^1.1.2",
"@protobufjs/base64": "^1.1.2",
"@protobufjs/codegen": "^2.0.4",
"@protobufjs/eventemitter": "^1.1.0",
"@protobufjs/fetch": "^1.1.0",
"@protobufjs/float": "^1.0.2",
"@protobufjs/inquire": "^1.1.0",
"@protobufjs/path": "^1.1.2",
"@protobufjs/pool": "^1.1.0",
"@protobufjs/utf8": "^1.1.0",
"@types/node": ">=13.7.0",
"long": "^5.0.0"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/readable-stream": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
"integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
"license": "MIT",
"dependencies": {
"abort-controller": "^3.0.0",
"buffer": "^6.0.3",
"events": "^3.3.0",
"process": "^0.11.10",
"string_decoder": "^1.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
"license": "MIT"
},
"node_modules/reinterval": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
"integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==",
"license": "MIT"
},
"node_modules/rfdc": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
"license": "MIT"
},
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"license": "MIT",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks": {
"version": "2.8.4",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz",
"integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==",
"license": "MIT",
"dependencies": {
"ip-address": "^9.0.5",
"smart-buffer": "^4.2.0"
},
"engines": {
"node": ">= 10.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"license": "ISC",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/sprintf-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
"license": "BSD-3-Clause"
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/string_decoder/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"
}
],
"license": "MIT"
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/table-layout": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/table-layout/-/table-layout-4.1.1.tgz",
"integrity": "sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==",
"license": "MIT",
"dependencies": {
"array-back": "^6.2.2",
"wordwrapjs": "^5.1.0"
},
"engines": {
"node": ">=12.17"
}
},
"node_modules/table-layout/node_modules/array-back": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz",
"integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==",
"license": "MIT",
"engines": {
"node": ">=12.17"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"license": "MIT"
},
"node_modules/typical": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz",
"integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"license": "MIT"
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
"node_modules/wordwrapjs": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.0.tgz",
"integrity": "sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==",
"license": "MIT",
"engines": {
"node": ">=12.17"
}
},
"node_modules/worker-timers": {
"version": "7.1.8",
"resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.8.tgz",
"integrity": "sha512-R54psRKYVLuzff7c1OTFcq/4Hue5Vlz4bFtNEIarpSiCYhpifHU3aIQI29S84o1j87ePCYqbmEJPqwBTf+3sfw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.24.5",
"tslib": "^2.6.2",
"worker-timers-broker": "^6.1.8",
"worker-timers-worker": "^7.0.71"
}
},
"node_modules/worker-timers-broker": {
"version": "6.1.8",
"resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.8.tgz",
"integrity": "sha512-FUCJu9jlK3A8WqLTKXM9E6kAmI/dR1vAJ8dHYLMisLNB/n3GuaFIjJ7pn16ZcD1zCOf7P6H62lWIEBi+yz/zQQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.24.5",
"fast-unique-numbers": "^8.0.13",
"tslib": "^2.6.2",
"worker-timers-worker": "^7.0.71"
}
},
"node_modules/worker-timers-worker": {
"version": "7.0.71",
"resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.71.tgz",
"integrity": "sha512-ks/5YKwZsto1c2vmljroppOKCivB/ma97g9y77MAAz2TBBjPPgpoOiS1qYQKIgvGTr2QYPT3XhJWIB6Rj2MVPQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.24.5",
"tslib": "^2.6.2"
}
},
"node_modules/ws": {
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
"integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}

18
mqtt/package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "mqtt",
"version": "1.0.0",
"main": "index.js",
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"@prisma/client": "^5.11.0",
"command-line-args": "^5.2.1",
"command-line-usage": "^7.0.1",
"mqtt": "^5.11.0",
"protobufjs": "^7.5.0"
},
"devDependencies": {
"prisma": "^5.10.2"
}
}

5057
package-lock.json generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 270 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +0,0 @@
/*!
* chartjs-adapter-moment v1.0.1
* https://www.chartjs.org
* (c) 2022 chartjs-adapter-moment Contributors
* Released under the MIT license
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("moment"),require("chart.js")):"function"==typeof define&&define.amd?define(["moment","chart.js"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).moment,e.Chart)}(this,(function(e,t){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var f=n(e);const a={datetime:"MMM D, YYYY, h:mm:ss a",millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"};t._adapters._date.override("function"==typeof f.default?{_id:"moment",formats:function(){return a},parse:function(e,t){return"string"==typeof e&&"string"==typeof t?e=f.default(e,t):e instanceof f.default||(e=f.default(e)),e.isValid()?e.valueOf():null},format:function(e,t){return f.default(e).format(t)},add:function(e,t,n){return f.default(e).add(t,n).valueOf()},diff:function(e,t,n){return f.default(e).diff(f.default(t),n)},startOf:function(e,t,n){return e=f.default(e),"isoWeek"===t?(n=Math.trunc(Math.min(Math.max(0,n),6)),e.isoWeekday(n).startOf("day").valueOf()):e.startOf(t).valueOf()},endOf:function(e,t){return f.default(e).endOf(t).valueOf()}}:{})}));

View File

@ -1,691 +0,0 @@
function modulus(i, n) {
return ((i % n) + n) % n;
}
function definedProps(obj) {
return Object.fromEntries(
Object.entries(obj).filter(([k, v]) => v !== undefined)
);
}
/**
* Whether or not a string is in the format '<number>m'
* @param {string} value
* @returns Boolean
*/
function isInMeters(value) {
return (
value
.toString()
.trim()
.slice(value.toString().length - 1, value.toString().length) === 'm'
);
}
/**
* Whether or not a string is in the format '<number>%'
* @param {string} value
* @returns Boolean
*/
function isInPercent(value) {
return (
value
.toString()
.trim()
.slice(value.toString().length - 1, value.toString().length) === '%'
);
}
/**
* Whether or not a string is in the format '<number>px'
* @param {string} value
* @returns Boolean
*/
function isInPixels(value) {
return (
value
.toString()
.trim()
.slice(value.toString().length - 2, value.toString().length) === 'px'
);
}
function pixelsToMeters(pixels, map) {
let refPoint1 = map.getCenter();
let xy1 = map.latLngToLayerPoint(refPoint1);
let xy2 = {
x: xy1.x + Number(pixels),
y: xy1.y,
};
let refPoint2 = map.layerPointToLatLng(xy2);
let derivedMeters = map.distance(refPoint1, refPoint2);
return derivedMeters;
}
L.Polyline.include({
/**
* Adds arrowheads to an L.polyline
* @param {object} options The options for the arrowhead. See documentation for details
* @returns The L.polyline instance that they arrowheads are attached to
*/
arrowheads: function (options = {}) {
// Merge user input options with default options:
const defaults = {
yawn: 60,
size: '15%',
frequency: 'allvertices',
proportionalToTotal: false,
};
this.options.noClip = true;
let actualOptions = Object.assign({}, defaults, options);
this._arrowheadOptions = actualOptions;
this._hatsApplied = true;
return this;
},
buildVectorHats: function (options) {
// Reset variables from previous this._update()
if (this._arrowheads) {
this._arrowheads.remove();
}
if (this._ghosts) {
this._ghosts.remove();
}
// -------------------------------------------------------- //
// ------------ FILTER THE OPTIONS ----------------------- //
/*
* The next 3 lines folds the options of the parent polyline into the default options for all polylines
* The options for the arrowhead are then folded in as well
* All options defined in parent polyline will be inherited by the arrowhead, unless otherwise specified in the arrowhead(options) call
*/
let defaultOptionsOfParent = Object.getPrototypeOf(
Object.getPrototypeOf(this.options)
);
// merge default options of parent polyline (this.options's prototype's prototype) with options passed to parent polyline (this.options).
let parentOptions = Object.assign({}, defaultOptionsOfParent, this.options);
// now merge in the options the user has put in the arrowhead call
let hatOptions = Object.assign({}, parentOptions, options);
// ...with a few exceptions:
hatOptions.smoothFactor = 1;
hatOptions.fillOpacity = 1;
hatOptions.fill = options.fill ? true : false;
hatOptions.interactive = false;
// ------------ FILTER THE OPTIONS END -------------------- //
// --------------------------------------------------------- //
// --------------------------------------------------------- //
// ------ LOOP THROUGH EACH POLYLINE SEGMENT --------------- //
// ------ TO CALCULATE HAT SIZES AND CAPTURE IN ARRAY ------ //
let size = options.size.toString(); // stringify if its a number
let allhats = []; // empty array to receive hat polylines
const { frequency, offsets } = options;
if (offsets?.start || offsets?.end) {
this._buildGhosts({ start: offsets.start, end: offsets.end });
}
const lineToTrace = this._ghosts || this;
lineToTrace._parts.forEach((peice, index) => {
// Immutable variables for each peice
const latlngs = peice.map((point) => this._map.layerPointToLatLng(point));
const totalLength = (() => {
let total = 0;
for (var i = 0; i < peice.length - 1; i++) {
total += this._map.distance(latlngs[i], latlngs[i + 1]);
}
return total;
})();
// TBD by options if tree below
let derivedLatLngs;
let derivedBearings;
let spacing;
let noOfPoints;
// Determining latlng and bearing arrays based on frequency choice:
if (!isNaN(frequency)) {
spacing = 1 / frequency;
noOfPoints = frequency;
} else if (isInPercent(frequency)) {
console.error(
'Error: arrowhead frequency option cannot be given in percent. Try another unit.'
);
} else if (isInMeters(frequency)) {
spacing = frequency.slice(0, frequency.length - 1) / totalLength;
noOfPoints = 1 / spacing;
// round things out for more even spacing:
noOfPoints = Math.floor(noOfPoints);
spacing = 1 / noOfPoints;
} else if (isInPixels(frequency)) {
spacing = (() => {
let chosenFrequency = frequency.slice(0, frequency.length - 2);
let derivedMeters = pixelsToMeters(chosenFrequency, this._map);
return derivedMeters / totalLength;
})();
noOfPoints = 1 / spacing;
// round things out for more even spacing:
noOfPoints = Math.floor(noOfPoints);
spacing = 1 / noOfPoints;
}
if (options.frequency === 'allvertices') {
derivedBearings = (() => {
let bearings = [];
for (var i = 1; i < latlngs.length; i++) {
let bearing =
L.GeometryUtil.angle(
this._map,
latlngs[modulus(i - 1, latlngs.length)],
latlngs[i]
) + 180;
bearings.push(bearing);
}
return bearings;
})();
derivedLatLngs = latlngs;
derivedLatLngs.shift();
} else if (options.frequency === 'endonly' && latlngs.length >= 2) {
derivedLatLngs = [latlngs[latlngs.length - 1]];
derivedBearings = [
L.GeometryUtil.angle(
this._map,
latlngs[latlngs.length - 2],
latlngs[latlngs.length - 1]
) + 180,
];
} else {
derivedLatLngs = [];
let interpolatedPoints = [];
for (var i = 0; i < noOfPoints; i++) {
let interpolatedPoint = L.GeometryUtil.interpolateOnLine(
this._map,
latlngs,
spacing * (i + 1)
);
if (interpolatedPoint) {
interpolatedPoints.push(interpolatedPoint);
derivedLatLngs.push(interpolatedPoint.latLng);
}
}
derivedBearings = (() => {
let bearings = [];
for (var i = 0; i < interpolatedPoints.length; i++) {
let bearing = L.GeometryUtil.angle(
this._map,
latlngs[interpolatedPoints[i].predecessor + 1],
latlngs[interpolatedPoints[i].predecessor]
);
bearings.push(bearing);
}
return bearings;
})();
}
let hats = [];
// Function to build hats based on index and a given hatsize in meters
const pushHats = (size, localHatOptions = {}) => {
let yawn = localHatOptions.yawn ?? options.yawn;
let leftWingPoint = L.GeometryUtil.destination(
derivedLatLngs[i],
derivedBearings[i] - yawn / 2,
size
);
let rightWingPoint = L.GeometryUtil.destination(
derivedLatLngs[i],
derivedBearings[i] + yawn / 2,
size
);
let hatPoints = [
[leftWingPoint.lat, leftWingPoint.lng],
[derivedLatLngs[i].lat, derivedLatLngs[i].lng],
[rightWingPoint.lat, rightWingPoint.lng],
];
let hat = options.fill
? L.polygon(hatPoints, { ...hatOptions, ...localHatOptions })
: L.polyline(hatPoints, { ...hatOptions, ...localHatOptions });
hats.push(hat);
}; // pushHats()
// Function to build hats based on pixel input
const pushHatsFromPixels = (size, localHatOptions = {}) => {
let sizePixels = size.slice(0, size.length - 2);
let yawn = localHatOptions.yawn ?? options.yawn;
let derivedXY = this._map.latLngToLayerPoint(derivedLatLngs[i]);
let bearing = derivedBearings[i];
let thetaLeft = (180 - bearing - yawn / 2) * (Math.PI / 180),
thetaRight = (180 - bearing + yawn / 2) * (Math.PI / 180);
let dxLeft = sizePixels * Math.sin(thetaLeft),
dyLeft = sizePixels * Math.cos(thetaLeft),
dxRight = sizePixels * Math.sin(thetaRight),
dyRight = sizePixels * Math.cos(thetaRight);
let leftWingXY = {
x: derivedXY.x + dxLeft,
y: derivedXY.y + dyLeft,
};
let rightWingXY = {
x: derivedXY.x + dxRight,
y: derivedXY.y + dyRight,
};
let leftWingPoint = this._map.layerPointToLatLng(leftWingXY),
rightWingPoint = this._map.layerPointToLatLng(rightWingXY);
let hatPoints = [
[leftWingPoint.lat, leftWingPoint.lng],
[derivedLatLngs[i].lat, derivedLatLngs[i].lng],
[rightWingPoint.lat, rightWingPoint.lng],
];
let hat = options.fill
? L.polygon(hatPoints, { ...hatOptions, ...localHatOptions })
: L.polyline(hatPoints, { ...hatOptions, ...localHatOptions });
hats.push(hat);
}; // pushHatsFromPixels()
// ------- LOOP THROUGH POINTS IN EACH SEGMENT ---------- //
for (var i = 0; i < derivedLatLngs.length; i++) {
let { perArrowheadOptions, ...globalOptions } = options;
perArrowheadOptions = perArrowheadOptions ? perArrowheadOptions(i) : {};
perArrowheadOptions = Object.assign(
globalOptions,
definedProps(perArrowheadOptions)
);
size = perArrowheadOptions.size ?? size;
// ---- If size is chosen in meters -------------------------
if (isInMeters(size)) {
let hatSize = size.slice(0, size.length - 1);
pushHats(hatSize, perArrowheadOptions);
// ---- If size is chosen in percent ------------------------
} else if (isInPercent(size)) {
let sizePercent = size.slice(0, size.length - 1);
let hatSize = (() => {
if (
options.frequency === 'endonly' &&
options.proportionalToTotal
) {
return (totalLength * sizePercent) / 100;
} else {
let averageDistance = totalLength / (peice.length - 1);
return (averageDistance * sizePercent) / 100;
}
})(); // hatsize calculation
pushHats(hatSize, perArrowheadOptions);
// ---- If size is chosen in pixels --------------------------
} else if (isInPixels(size)) {
pushHatsFromPixels(options.size, perArrowheadOptions);
// ---- If size unit is not given -----------------------------
} else {
console.error(
'Error: Arrowhead size unit not defined. Check your arrowhead options.'
);
} // if else block for Size
} // for loop for each point witin a peice
allhats.push(...hats);
}); // forEach peice
// --------- LOOP THROUGH EACH POLYLINE END ---------------- //
// --------------------------------------------------------- //
let arrowheads = L.layerGroup(allhats);
this._arrowheads = arrowheads;
return this;
},
getArrowheads: function () {
if (this._arrowheads) {
return this._arrowheads;
} else {
return console.error(
`Error: You tried to call '.getArrowheads() on a shape that does not have a arrowhead. Use '.arrowheads()' to add a arrowheads before trying to call '.getArrowheads()'`
);
}
},
/**
* Builds ghost polylines that are clipped versions of the polylines based on the offsets
* If offsets are used, arrowheads are drawn from 'this._ghosts' rather than 'this'
*/
_buildGhosts: function ({ start, end }) {
if (start || end) {
let latlngs = this.getLatLngs();
latlngs = Array.isArray(latlngs[0]) ? latlngs : [latlngs];
const newLatLngs = latlngs.map((segment) => {
// Get total distance of original latlngs
const totalLength = (() => {
let total = 0;
for (var i = 0; i < segment.length - 1; i++) {
total += this._map.distance(segment[i], segment[i + 1]);
}
return total;
})();
// Modify latlngs to end at interpolated point
if (start) {
let endOffsetInMeters = (() => {
if (isInMeters(start)) {
return Number(start.slice(0, start.length - 1));
} else if (isInPixels(start)) {
let pixels = Number(start.slice(0, start.length - 2));
return pixelsToMeters(pixels, this._map);
}
})();
let newStart = L.GeometryUtil.interpolateOnLine(
this._map,
segment,
endOffsetInMeters / totalLength
);
segment = segment.slice(
newStart.predecessor === -1 ? 1 : newStart.predecessor + 1,
segment.length
);
segment.unshift(newStart.latLng);
}
if (end) {
let endOffsetInMeters = (() => {
if (isInMeters(end)) {
return Number(end.slice(0, end.length - 1));
} else if (isInPixels(end)) {
let pixels = Number(end.slice(0, end.length - 2));
return pixelsToMeters(pixels, this._map);
}
})();
let newEnd = L.GeometryUtil.interpolateOnLine(
this._map,
segment,
(totalLength - endOffsetInMeters) / totalLength
);
segment = segment.slice(0, newEnd.predecessor + 1);
segment.push(newEnd.latLng);
}
return segment;
});
this._ghosts = L.polyline(newLatLngs, {
...this.options,
color: 'rgba(0,0,0,0)',
stroke: 0,
smoothFactor: 0,
interactive: false,
});
this._ghosts.addTo(this._map);
}
},
deleteArrowheads: function () {
if (this._arrowheads) {
this._arrowheads.remove();
delete this._arrowheads;
delete this._arrowheadOptions;
this._hatsApplied = false;
}
if (this._ghosts) {
this._ghosts.remove();
}
},
_update: function () {
if (!this._map) {
return;
}
this._clipPoints();
this._simplifyPoints();
this._updatePath();
if (this._hatsApplied) {
this.buildVectorHats(this._arrowheadOptions);
this._map.addLayer(this._arrowheads);
}
},
remove: function () {
if (this._arrowheads) {
this._arrowheads.remove();
}
if (this._ghosts) {
this._ghosts.remove();
}
return this.removeFrom(this._map || this._mapToAdd);
},
});
L.LayerGroup.include({
removeLayer: function (layer) {
var id = layer in this._layers ? layer : this.getLayerId(layer);
if (this._map && this._layers[id]) {
if (this._layers[id]._arrowheads) {
this._layers[id]._arrowheads.remove();
}
this._map.removeLayer(this._layers[id]);
}
delete this._layers[id];
return this;
},
onRemove: function (map, layer) {
for (var layer in this._layers) {
if (this._layers[layer]) {
this._layers[layer].remove();
}
}
this.eachLayer(map.removeLayer, map);
},
});
L.Map.include({
removeLayer: function (layer) {
var id = L.Util.stamp(layer);
if (layer._arrowheads) {
layer._arrowheads.remove();
}
if (layer._ghosts) {
layer._ghosts.remove();
}
if (!this._layers[id]) {
return this;
}
if (this._loaded) {
layer.onRemove(this);
}
if (layer.getAttribution && this.attributionControl) {
this.attributionControl.removeAttribution(layer.getAttribution());
}
delete this._layers[id];
if (this._loaded) {
this.fire('layerremove', { layer: layer });
layer.fire('remove');
}
layer._map = layer._mapToAdd = null;
return this;
},
});
L.GeoJSON.include({
geometryToLayer: function (geojson, options) {
var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
coords = geometry ? geometry.coordinates : null,
layers = [],
pointToLayer = options && options.pointToLayer,
_coordsToLatLng =
(options && options.coordsToLatLng) || L.GeoJSON.coordsToLatLng,
latlng,
latlngs,
i,
len;
if (!coords && !geometry) {
return null;
}
switch (geometry.type) {
case 'Point':
latlng = _coordsToLatLng(coords);
return this._pointToLayer(pointToLayer, geojson, latlng, options);
case 'MultiPoint':
for (i = 0, len = coords.length; i < len; i++) {
latlng = _coordsToLatLng(coords[i]);
layers.push(
this._pointToLayer(pointToLayer, geojson, latlng, options)
);
}
return new L.FeatureGroup(layers);
case 'LineString':
case 'MultiLineString':
latlngs = L.GeoJSON.coordsToLatLngs(
coords,
geometry.type === 'LineString' ? 0 : 1,
_coordsToLatLng
);
var polyline = new L.Polyline(latlngs, options);
if (options.arrowheads) {
polyline.arrowheads(options.arrowheads);
}
return polyline;
case 'Polygon':
case 'MultiPolygon':
latlngs = L.GeoJSON.coordsToLatLngs(
coords,
geometry.type === 'Polygon' ? 1 : 2,
_coordsToLatLng
);
return new L.Polygon(latlngs, options);
case 'GeometryCollection':
for (i = 0, len = geometry.geometries.length; i < len; i++) {
var layer = this.geometryToLayer(
{
geometry: geometry.geometries[i],
type: 'Feature',
properties: geojson.properties,
},
options
);
if (layer) {
layers.push(layer);
}
}
return new L.FeatureGroup(layers);
default:
throw new Error('Invalid GeoJSON object.');
}
},
addData: function (geojson) {
var features = L.Util.isArray(geojson) ? geojson : geojson.features,
i,
len,
feature;
if (features) {
for (i = 0, len = features.length; i < len; i++) {
// only add this if geometry or geometries are set and not null
feature = features[i];
if (
feature.geometries ||
feature.geometry ||
feature.features ||
feature.coordinates
) {
this.addData(feature);
}
}
return this;
}
var options = this.options;
if (options.filter && !options.filter(geojson)) {
return this;
}
var layer = this.geometryToLayer(geojson, options);
if (!layer) {
return this;
}
layer.feature = L.GeoJSON.asFeature(geojson);
layer.defaultOptions = layer.options;
this.resetStyle(layer);
if (options.onEachFeature) {
options.onEachFeature(geojson, layer);
}
return this.addLayer(layer);
},
_pointToLayer: function (pointToLayerFn, geojson, latlng, options) {
return pointToLayerFn
? pointToLayerFn(geojson, latlng)
: new L.Marker(
latlng,
options && options.markersInheritOptions && options
);
},
});

View File

@ -1,807 +0,0 @@
// Packaging/modules magic dance.
(function (factory) {
var L;
if (typeof define === 'function' && define.amd) {
// AMD
define(['leaflet'], factory);
} else if (typeof module !== 'undefined') {
// Node/CommonJS
L = require('leaflet');
module.exports = factory(L);
} else {
// Browser globals
if (typeof window.L === 'undefined')
throw 'Leaflet must be loaded first';
factory(window.L);
}
}(function (L) {
"use strict";
L.Polyline._flat = L.LineUtil.isFlat || L.Polyline._flat || function (latlngs) {
// true if it's a flat array of latlngs; false if nested
return !L.Util.isArray(latlngs[0]) || (typeof latlngs[0][0] !== 'object' && typeof latlngs[0][0] !== 'undefined');
};
/**
* @fileOverview Leaflet Geometry utilities for distances and linear referencing.
* @name L.GeometryUtil
*/
L.GeometryUtil = L.extend(L.GeometryUtil || {}, {
/**
Shortcut function for planar distance between two {L.LatLng} at current zoom.
@tutorial distance-length
@param {L.Map} map Leaflet map to be used for this method
@param {L.LatLng} latlngA geographical point A
@param {L.LatLng} latlngB geographical point B
@returns {Number} planar distance
*/
distance: function (map, latlngA, latlngB) {
return map.latLngToLayerPoint(latlngA).distanceTo(map.latLngToLayerPoint(latlngB));
},
/**
Shortcut function for planar distance between a {L.LatLng} and a segment (A-B).
@param {L.Map} map Leaflet map to be used for this method
@param {L.LatLng} latlng - The position to search
@param {L.LatLng} latlngA geographical point A of the segment
@param {L.LatLng} latlngB geographical point B of the segment
@returns {Number} planar distance
*/
distanceSegment: function (map, latlng, latlngA, latlngB) {
var p = map.latLngToLayerPoint(latlng),
p1 = map.latLngToLayerPoint(latlngA),
p2 = map.latLngToLayerPoint(latlngB);
return L.LineUtil.pointToSegmentDistance(p, p1, p2);
},
/**
Shortcut function for converting distance to readable distance.
@param {Number} distance distance to be converted
@param {String} unit 'metric' or 'imperial'
@returns {String} in yard or miles
*/
readableDistance: function (distance, unit) {
var isMetric = (unit !== 'imperial'),
distanceStr;
if (isMetric) {
// show metres when distance is < 1km, then show km
if (distance > 1000) {
distanceStr = (distance / 1000).toFixed(2) + ' km';
}
else {
distanceStr = distance.toFixed(1) + ' m';
}
}
else {
distance *= 1.09361;
if (distance > 1760) {
distanceStr = (distance / 1760).toFixed(2) + ' miles';
}
else {
distanceStr = distance.toFixed(1) + ' yd';
}
}
return distanceStr;
},
/**
Returns true if the latlng belongs to segment A-B
@param {L.LatLng} latlng - The position to search
@param {L.LatLng} latlngA geographical point A of the segment
@param {L.LatLng} latlngB geographical point B of the segment
@param {?Number} [tolerance=0.2] tolerance to accept if latlng belongs really
@returns {boolean}
*/
belongsSegment: function(latlng, latlngA, latlngB, tolerance) {
tolerance = tolerance === undefined ? 0.2 : tolerance;
var hypotenuse = latlngA.distanceTo(latlngB),
delta = latlngA.distanceTo(latlng) + latlng.distanceTo(latlngB) - hypotenuse;
return delta/hypotenuse < tolerance;
},
/**
* Returns total length of line
* @tutorial distance-length
*
* @param {L.Polyline|Array<L.Point>|Array<L.LatLng>} coords Set of coordinates
* @returns {Number} Total length (pixels for Point, meters for LatLng)
*/
length: function (coords) {
var accumulated = L.GeometryUtil.accumulatedLengths(coords);
return accumulated.length > 0 ? accumulated[accumulated.length-1] : 0;
},
/**
* Returns a list of accumulated length along a line.
* @param {L.Polyline|Array<L.Point>|Array<L.LatLng>} coords Set of coordinates
* @returns {Array<Number>} Array of accumulated lengths (pixels for Point, meters for LatLng)
*/
accumulatedLengths: function (coords) {
if (typeof coords.getLatLngs == 'function') {
coords = coords.getLatLngs();
}
if (coords.length === 0)
return [];
var total = 0,
lengths = [0];
for (var i = 0, n = coords.length - 1; i< n; i++) {
total += coords[i].distanceTo(coords[i+1]);
lengths.push(total);
}
return lengths;
},
/**
Returns the closest point of a {L.LatLng} on the segment (A-B)
@tutorial closest
@param {L.Map} map Leaflet map to be used for this method
@param {L.LatLng} latlng - The position to search
@param {L.LatLng} latlngA geographical point A of the segment
@param {L.LatLng} latlngB geographical point B of the segment
@returns {L.LatLng} Closest geographical point
*/
closestOnSegment: function (map, latlng, latlngA, latlngB) {
var maxzoom = map.getMaxZoom();
if (maxzoom === Infinity)
maxzoom = map.getZoom();
var p = map.project(latlng, maxzoom),
p1 = map.project(latlngA, maxzoom),
p2 = map.project(latlngB, maxzoom),
closest = L.LineUtil.closestPointOnSegment(p, p1, p2);
return map.unproject(closest, maxzoom);
},
/**
Returns the closest point of a {L.LatLng} on a {L.Circle}
@tutorial closest
@param {L.LatLng} latlng - The position to search
@param {L.Circle} circle - A Circle defined by a center and a radius
@returns {L.LatLng} Closest geographical point on the circle circumference
*/
closestOnCircle: function (circle, latLng) {
const center = circle.getLatLng();
const circleRadius = circle.getRadius();
const radius = typeof circleRadius === 'number' ? circleRadius : circleRadius.radius;
const x = latLng.lng;
const y = latLng.lat;
const cx = center.lng;
const cy = center.lat;
// dx and dy is the vector from the circle's center to latLng
const dx = x - cx;
const dy = y - cy;
// distance between the point and the circle's center
const distance = Math.sqrt(dx * dx + dy * dy)
// Calculate the closest point on the circle by adding the normalized vector to the center
const tx = cx + (dx / distance) * radius;
const ty = cy + (dy / distance) * radius;
return new L.LatLng(ty, tx);
},
/**
Returns the closest latlng on layer.
Accept nested arrays
@tutorial closest
@param {L.Map} map Leaflet map to be used for this method
@param {Array<L.LatLng>|Array<Array<L.LatLng>>|L.PolyLine|L.Polygon} layer - Layer that contains the result
@param {L.LatLng} latlng - The position to search
@param {?boolean} [vertices=false] - Whether to restrict to path vertices.
@returns {L.LatLng} Closest geographical point or null if layer param is incorrect
*/
closest: function (map, layer, latlng, vertices) {
var latlngs,
mindist = Infinity,
result = null,
i, n, distance, subResult;
if (layer instanceof Array) {
// if layer is Array<Array<T>>
if (layer[0] instanceof Array && typeof layer[0][0] !== 'number') {
// if we have nested arrays, we calc the closest for each array
// recursive
for (i = 0; i < layer.length; i++) {
subResult = L.GeometryUtil.closest(map, layer[i], latlng, vertices);
if (subResult && subResult.distance < mindist) {
mindist = subResult.distance;
result = subResult;
}
}
return result;
} else if (layer[0] instanceof L.LatLng
|| typeof layer[0][0] === 'number'
|| typeof layer[0].lat === 'number') { // we could have a latlng as [x,y] with x & y numbers or {lat, lng}
layer = L.polyline(layer);
} else {
return result;
}
}
// if we don't have here a Polyline, that means layer is incorrect
// see https://github.com/makinacorpus/Leaflet.GeometryUtil/issues/23
if (! ( layer instanceof L.Polyline ) )
return result;
// deep copy of latlngs
latlngs = JSON.parse(JSON.stringify(layer.getLatLngs().slice(0)));
// add the last segment for L.Polygon
if (layer instanceof L.Polygon) {
// add the last segment for each child that is a nested array
var addLastSegment = function(latlngs) {
if (L.Polyline._flat(latlngs)) {
latlngs.push(latlngs[0]);
} else {
for (var i = 0; i < latlngs.length; i++) {
addLastSegment(latlngs[i]);
}
}
};
addLastSegment(latlngs);
}
// we have a multi polygon / multi polyline / polygon with holes
// use recursive to explore and return the good result
if ( ! L.Polyline._flat(latlngs) ) {
for (i = 0; i < latlngs.length; i++) {
// if we are at the lower level, and if we have a L.Polygon, we add the last segment
subResult = L.GeometryUtil.closest(map, latlngs[i], latlng, vertices);
if (subResult.distance < mindist) {
mindist = subResult.distance;
result = subResult;
}
}
return result;
} else {
// Lookup vertices
if (vertices) {
for(i = 0, n = latlngs.length; i < n; i++) {
var ll = latlngs[i];
distance = L.GeometryUtil.distance(map, latlng, ll);
if (distance < mindist) {
mindist = distance;
result = ll;
result.distance = distance;
}
}
return result;
}
// Keep the closest point of all segments
for (i = 0, n = latlngs.length; i < n-1; i++) {
var latlngA = latlngs[i],
latlngB = latlngs[i+1];
distance = L.GeometryUtil.distanceSegment(map, latlng, latlngA, latlngB);
if (distance <= mindist) {
mindist = distance;
result = L.GeometryUtil.closestOnSegment(map, latlng, latlngA, latlngB);
result.distance = distance;
}
}
return result;
}
},
/**
Returns the closest layer to latlng among a list of layers.
@tutorial closest
@param {L.Map} map Leaflet map to be used for this method
@param {Array<L.ILayer>} layers Set of layers
@param {L.LatLng} latlng - The position to search
@returns {object} ``{layer, latlng, distance}`` or ``null`` if list is empty;
*/
closestLayer: function (map, layers, latlng) {
var mindist = Infinity,
result = null,
ll = null,
distance = Infinity;
for (var i = 0, n = layers.length; i < n; i++) {
var layer = layers[i];
if (layer instanceof L.LayerGroup) {
// recursive
var subResult = L.GeometryUtil.closestLayer(map, layer.getLayers(), latlng);
if (subResult.distance < mindist) {
mindist = subResult.distance;
result = subResult;
}
} else {
if (layer instanceof L.Circle){
ll = this.closestOnCircle(layer, latlng);
distance = L.GeometryUtil.distance(map, latlng, ll);
} else
// Single dimension, snap on points, else snap on closest
if (typeof layer.getLatLng == 'function') {
ll = layer.getLatLng();
distance = L.GeometryUtil.distance(map, latlng, ll);
}
else {
ll = L.GeometryUtil.closest(map, layer, latlng);
if (ll) distance = ll.distance; // Can return null if layer has no points.
}
if (distance < mindist) {
mindist = distance;
result = {layer: layer, latlng: ll, distance: distance};
}
}
}
return result;
},
/**
Returns the n closest layers to latlng among a list of input layers.
@param {L.Map} map - Leaflet map to be used for this method
@param {Array<L.ILayer>} layers - Set of layers
@param {L.LatLng} latlng - The position to search
@param {?Number} [n=layers.length] - the expected number of output layers.
@returns {Array<object>} an array of objects ``{layer, latlng, distance}`` or ``null`` if the input is invalid (empty list or negative n)
*/
nClosestLayers: function (map, layers, latlng, n) {
n = typeof n === 'number' ? n : layers.length;
if (n < 1 || layers.length < 1) {
return null;
}
var results = [];
var distance, ll;
for (var i = 0, m = layers.length; i < m; i++) {
var layer = layers[i];
if (layer instanceof L.LayerGroup) {
// recursive
var subResult = L.GeometryUtil.closestLayer(map, layer.getLayers(), latlng);
results.push(subResult);
} else {
if (layer instanceof L.Circle){
ll = this.closestOnCircle(layer, latlng);
distance = L.GeometryUtil.distance(map, latlng, ll);
} else
// Single dimension, snap on points, else snap on closest
if (typeof layer.getLatLng == 'function') {
ll = layer.getLatLng();
distance = L.GeometryUtil.distance(map, latlng, ll);
}
else {
ll = L.GeometryUtil.closest(map, layer, latlng);
if (ll) distance = ll.distance; // Can return null if layer has no points.
}
results.push({layer: layer, latlng: ll, distance: distance});
}
}
results.sort(function(a, b) {
return a.distance - b.distance;
});
if (results.length > n) {
return results.slice(0, n);
} else {
return results;
}
},
/**
* Returns all layers within a radius of the given position, in an ascending order of distance.
@param {L.Map} map Leaflet map to be used for this method
@param {Array<ILayer>} layers - A list of layers.
@param {L.LatLng} latlng - The position to search
@param {?Number} [radius=Infinity] - Search radius in pixels
@return {object[]} an array of objects including layer within the radius, closest latlng, and distance
*/
layersWithin: function(map, layers, latlng, radius) {
radius = typeof radius == 'number' ? radius : Infinity;
var results = [];
var ll = null;
var distance = 0;
for (var i = 0, n = layers.length; i < n; i++) {
var layer = layers[i];
if (typeof layer.getLatLng == 'function') {
ll = layer.getLatLng();
distance = L.GeometryUtil.distance(map, latlng, ll);
}
else {
ll = L.GeometryUtil.closest(map, layer, latlng);
if (ll) distance = ll.distance; // Can return null if layer has no points.
}
if (ll && distance < radius) {
results.push({layer: layer, latlng: ll, distance: distance});
}
}
var sortedResults = results.sort(function(a, b) {
return a.distance - b.distance;
});
return sortedResults;
},
/**
Returns the closest position from specified {LatLng} among specified layers,
with a maximum tolerance in pixels, providing snapping behaviour.
@tutorial closest
@param {L.Map} map Leaflet map to be used for this method
@param {Array<ILayer>} layers - A list of layers to snap on.
@param {L.LatLng} latlng - The position to snap
@param {?Number} [tolerance=Infinity] - Maximum number of pixels.
@param {?boolean} [withVertices=true] - Snap to layers vertices or segment points (not only vertex)
@returns {object} with snapped {LatLng} and snapped {Layer} or null if tolerance exceeded.
*/
closestLayerSnap: function (map, layers, latlng, tolerance, withVertices) {
tolerance = typeof tolerance == 'number' ? tolerance : Infinity;
withVertices = typeof withVertices == 'boolean' ? withVertices : true;
var result = L.GeometryUtil.closestLayer(map, layers, latlng);
if (!result || result.distance > tolerance)
return null;
// If snapped layer is linear, try to snap on vertices (extremities and middle points)
if (withVertices && typeof result.layer.getLatLngs == 'function') {
var closest = L.GeometryUtil.closest(map, result.layer, result.latlng, true);
if (closest.distance < tolerance) {
result.latlng = closest;
result.distance = L.GeometryUtil.distance(map, closest, latlng);
}
}
return result;
},
/**
Returns the Point located on a segment at the specified ratio of the segment length.
@param {L.Point} pA coordinates of point A
@param {L.Point} pB coordinates of point B
@param {Number} the length ratio, expressed as a decimal between 0 and 1, inclusive.
@returns {L.Point} the interpolated point.
*/
interpolateOnPointSegment: function (pA, pB, ratio) {
return L.point(
(pA.x * (1 - ratio)) + (ratio * pB.x),
(pA.y * (1 - ratio)) + (ratio * pB.y)
);
},
/**
Returns the coordinate of the point located on a line at the specified ratio of the line length.
@param {L.Map} map Leaflet map to be used for this method
@param {Array<L.LatLng>|L.PolyLine} latlngs Set of geographical points
@param {Number} ratio the length ratio, expressed as a decimal between 0 and 1, inclusive
@returns {Object} an object with latLng ({LatLng}) and predecessor ({Number}), the index of the preceding vertex in the Polyline
(-1 if the interpolated point is the first vertex)
*/
interpolateOnLine: function (map, latLngs, ratio) {
latLngs = (latLngs instanceof L.Polyline) ? latLngs.getLatLngs() : latLngs;
var n = latLngs.length;
if (n < 2) {
return null;
}
// ensure the ratio is between 0 and 1;
ratio = Math.max(Math.min(ratio, 1), 0);
if (ratio === 0) {
return {
latLng: latLngs[0] instanceof L.LatLng ? latLngs[0] : L.latLng(latLngs[0]),
predecessor: -1
};
}
if (ratio == 1) {
return {
latLng: latLngs[latLngs.length -1] instanceof L.LatLng ? latLngs[latLngs.length -1] : L.latLng(latLngs[latLngs.length -1]),
predecessor: latLngs.length - 2
};
}
// project the LatLngs as Points,
// and compute total planar length of the line at max precision
var maxzoom = map.getMaxZoom();
if (maxzoom === Infinity)
maxzoom = map.getZoom();
var pts = [];
var lineLength = 0;
for(var i = 0; i < n; i++) {
pts[i] = map.project(latLngs[i], maxzoom);
if(i > 0)
lineLength += pts[i-1].distanceTo(pts[i]);
}
var ratioDist = lineLength * ratio;
// follow the line segments [ab], adding lengths,
// until we find the segment where the points should lie on
var cumulativeDistanceToA = 0, cumulativeDistanceToB = 0;
for (var i = 0; cumulativeDistanceToB < ratioDist; i++) {
var pointA = pts[i], pointB = pts[i+1];
cumulativeDistanceToA = cumulativeDistanceToB;
cumulativeDistanceToB += pointA.distanceTo(pointB);
}
if (pointA == undefined && pointB == undefined) { // Happens when line has no length
var pointA = pts[0], pointB = pts[1], i = 1;
}
// compute the ratio relative to the segment [ab]
var segmentRatio = ((cumulativeDistanceToB - cumulativeDistanceToA) !== 0) ? ((ratioDist - cumulativeDistanceToA) / (cumulativeDistanceToB - cumulativeDistanceToA)) : 0;
var interpolatedPoint = L.GeometryUtil.interpolateOnPointSegment(pointA, pointB, segmentRatio);
return {
latLng: map.unproject(interpolatedPoint, maxzoom),
predecessor: i-1
};
},
/**
Returns a float between 0 and 1 representing the location of the
closest point on polyline to the given latlng, as a fraction of total line length.
(opposite of L.GeometryUtil.interpolateOnLine())
@param {L.Map} map Leaflet map to be used for this method
@param {L.PolyLine} polyline Polyline on which the latlng will be search
@param {L.LatLng} latlng The position to search
@returns {Number} Float between 0 and 1
*/
locateOnLine: function (map, polyline, latlng) {
var latlngs = polyline.getLatLngs();
if (latlng.equals(latlngs[0]))
return 0.0;
if (latlng.equals(latlngs[latlngs.length-1]))
return 1.0;
var point = L.GeometryUtil.closest(map, polyline, latlng, false),
lengths = L.GeometryUtil.accumulatedLengths(latlngs),
total_length = lengths[lengths.length-1],
portion = 0,
found = false;
for (var i=0, n = latlngs.length-1; i < n; i++) {
var l1 = latlngs[i],
l2 = latlngs[i+1];
portion = lengths[i];
if (L.GeometryUtil.belongsSegment(point, l1, l2, 0.001)) {
portion += l1.distanceTo(point);
found = true;
break;
}
}
if (!found) {
throw "Could not interpolate " + latlng.toString() + " within " + polyline.toString();
}
return portion / total_length;
},
/**
Returns a clone with reversed coordinates.
@param {L.PolyLine} polyline polyline to reverse
@returns {L.PolyLine} polyline reversed
*/
reverse: function (polyline) {
return L.polyline(polyline.getLatLngs().slice(0).reverse());
},
/**
Returns a sub-part of the polyline, from start to end.
If start is superior to end, returns extraction from inverted line.
@param {L.Map} map Leaflet map to be used for this method
@param {L.PolyLine} polyline Polyline on which will be extracted the sub-part
@param {Number} start ratio, expressed as a decimal between 0 and 1, inclusive
@param {Number} end ratio, expressed as a decimal between 0 and 1, inclusive
@returns {Array<L.LatLng>} new polyline
*/
extract: function (map, polyline, start, end) {
if (start > end) {
return L.GeometryUtil.extract(map, L.GeometryUtil.reverse(polyline), 1.0-start, 1.0-end);
}
// Bound start and end to [0-1]
start = Math.max(Math.min(start, 1), 0);
end = Math.max(Math.min(end, 1), 0);
var latlngs = polyline.getLatLngs(),
startpoint = L.GeometryUtil.interpolateOnLine(map, polyline, start),
endpoint = L.GeometryUtil.interpolateOnLine(map, polyline, end);
// Return single point if start == end
if (start == end) {
var point = L.GeometryUtil.interpolateOnLine(map, polyline, end);
return [point.latLng];
}
// Array.slice() works indexes at 0
if (startpoint.predecessor == -1)
startpoint.predecessor = 0;
if (endpoint.predecessor == -1)
endpoint.predecessor = 0;
var result = latlngs.slice(startpoint.predecessor+1, endpoint.predecessor+1);
result.unshift(startpoint.latLng);
result.push(endpoint.latLng);
return result;
},
/**
Returns true if first polyline ends where other second starts.
@param {L.PolyLine} polyline First polyline
@param {L.PolyLine} other Second polyline
@returns {bool}
*/
isBefore: function (polyline, other) {
if (!other) return false;
var lla = polyline.getLatLngs(),
llb = other.getLatLngs();
return (lla[lla.length-1]).equals(llb[0]);
},
/**
Returns true if first polyline starts where second ends.
@param {L.PolyLine} polyline First polyline
@param {L.PolyLine} other Second polyline
@returns {bool}
*/
isAfter: function (polyline, other) {
if (!other) return false;
var lla = polyline.getLatLngs(),
llb = other.getLatLngs();
return (lla[0]).equals(llb[llb.length-1]);
},
/**
Returns true if first polyline starts where second ends or start.
@param {L.PolyLine} polyline First polyline
@param {L.PolyLine} other Second polyline
@returns {bool}
*/
startsAtExtremity: function (polyline, other) {
if (!other) return false;
var lla = polyline.getLatLngs(),
llb = other.getLatLngs(),
start = lla[0];
return start.equals(llb[0]) || start.equals(llb[llb.length-1]);
},
/**
Returns horizontal angle in degres between two points.
@param {L.Point} a Coordinates of point A
@param {L.Point} b Coordinates of point B
@returns {Number} horizontal angle
*/
computeAngle: function(a, b) {
return (Math.atan2(b.y - a.y, b.x - a.x) * 180 / Math.PI);
},
/**
Returns slope (Ax+B) between two points.
@param {L.Point} a Coordinates of point A
@param {L.Point} b Coordinates of point B
@returns {Object} with ``a`` and ``b`` properties.
*/
computeSlope: function(a, b) {
var s = (b.y - a.y) / (b.x - a.x),
o = a.y - (s * a.x);
return {'a': s, 'b': o};
},
/**
Returns LatLng of rotated point around specified LatLng center.
@param {L.LatLng} latlngPoint: point to rotate
@param {double} angleDeg: angle to rotate in degrees
@param {L.LatLng} latlngCenter: center of rotation
@returns {L.LatLng} rotated point
*/
rotatePoint: function(map, latlngPoint, angleDeg, latlngCenter) {
var maxzoom = map.getMaxZoom();
if (maxzoom === Infinity)
maxzoom = map.getZoom();
var angleRad = angleDeg*Math.PI/180,
pPoint = map.project(latlngPoint, maxzoom),
pCenter = map.project(latlngCenter, maxzoom),
x2 = Math.cos(angleRad)*(pPoint.x-pCenter.x) - Math.sin(angleRad)*(pPoint.y-pCenter.y) + pCenter.x,
y2 = Math.sin(angleRad)*(pPoint.x-pCenter.x) + Math.cos(angleRad)*(pPoint.y-pCenter.y) + pCenter.y;
return map.unproject(new L.Point(x2,y2), maxzoom);
},
/**
Returns the bearing in degrees clockwise from north (0 degrees)
from the first L.LatLng to the second, at the first LatLng
@param {L.LatLng} latlng1: origin point of the bearing
@param {L.LatLng} latlng2: destination point of the bearing
@returns {float} degrees clockwise from north.
*/
bearing: function(latlng1, latlng2) {
var rad = Math.PI / 180,
lat1 = latlng1.lat * rad,
lat2 = latlng2.lat * rad,
lon1 = latlng1.lng * rad,
lon2 = latlng2.lng * rad,
y = Math.sin(lon2 - lon1) * Math.cos(lat2),
x = Math.cos(lat1) * Math.sin(lat2) -
Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);
var bearing = ((Math.atan2(y, x) * 180 / Math.PI) + 360) % 360;
return bearing >= 180 ? bearing-360 : bearing;
},
/**
Returns the point that is a distance and heading away from
the given origin point.
@param {L.LatLng} latlng: origin point
@param {float} heading: heading in degrees, clockwise from 0 degrees north.
@param {float} distance: distance in meters
@returns {L.latLng} the destination point.
Many thanks to Chris Veness at http://www.movable-type.co.uk/scripts/latlong.html
for a great reference and examples.
*/
destination: function(latlng, heading, distance) {
heading = (heading + 360) % 360;
var rad = Math.PI / 180,
radInv = 180 / Math.PI,
R = L.CRS.Earth.R, // approximation of Earth's radius
lon1 = latlng.lng * rad,
lat1 = latlng.lat * rad,
rheading = heading * rad,
sinLat1 = Math.sin(lat1),
cosLat1 = Math.cos(lat1),
cosDistR = Math.cos(distance / R),
sinDistR = Math.sin(distance / R),
lat2 = Math.asin(sinLat1 * cosDistR + cosLat1 *
sinDistR * Math.cos(rheading)),
lon2 = lon1 + Math.atan2(Math.sin(rheading) * sinDistR *
cosLat1, cosDistR - sinLat1 * Math.sin(lat2));
lon2 = lon2 * radInv;
lon2 = lon2 > 180 ? lon2 - 360 : lon2 < -180 ? lon2 + 360 : lon2;
return L.latLng([lat2 * radInv, lon2]);
},
/**
Returns the the angle of the given segment and the Equator in degrees,
clockwise from 0 degrees north.
@param {L.Map} map: Leaflet map to be used for this method
@param {L.LatLng} latlngA: geographical point A of the segment
@param {L.LatLng} latlngB: geographical point B of the segment
@returns {Float} the angle in degrees.
*/
angle: function(map, latlngA, latlngB) {
var pointA = map.latLngToContainerPoint(latlngA),
pointB = map.latLngToContainerPoint(latlngB),
angleDeg = Math.atan2(pointB.y - pointA.y, pointB.x - pointA.x) * 180 / Math.PI + 90;
angleDeg += angleDeg < 0 ? 360 : 0;
return angleDeg;
},
/**
Returns a point snaps on the segment and heading away from the given origin point a distance.
@param {L.Map} map: Leaflet map to be used for this method
@param {L.LatLng} latlngA: geographical point A of the segment
@param {L.LatLng} latlngB: geographical point B of the segment
@param {float} distance: distance in meters
@returns {L.latLng} the destination point.
*/
destinationOnSegment: function(map, latlngA, latlngB, distance) {
var angleDeg = L.GeometryUtil.angle(map, latlngA, latlngB),
latlng = L.GeometryUtil.destination(latlngA, angleDeg, distance);
return L.GeometryUtil.closestOnSegment(map, latlng, latlngA, latlngB);
},
});
return L.GeometryUtil;
}));

View File

@ -1,13 +0,0 @@
.leaflet-control-layers-group-name {
font-weight: bold;
margin-bottom: .2em;
}
.leaflet-control-layers-group {
margin-bottom: .5em;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
padding-right: 10px;
}

View File

@ -1,374 +0,0 @@
/* global L */
// A layer control which provides for layer groupings.
// Author: Ishmael Smyrnow
L.Control.GroupedLayers = L.Control.extend({
options: {
collapsed: true,
position: 'topright',
autoZIndex: true,
exclusiveGroups: [],
groupCheckboxes: false
},
initialize: function (baseLayers, groupedOverlays, options) {
var i, j;
L.Util.setOptions(this, options);
this._layers = [];
this._lastZIndex = 0;
this._handlingClick = false;
this._groupList = [];
this._domGroups = [];
for (i in baseLayers) {
this._addLayer(baseLayers[i], i);
}
for (i in groupedOverlays) {
for (j in groupedOverlays[i]) {
this._addLayer(groupedOverlays[i][j], j, i, true);
}
}
},
onAdd: function (map) {
this._initLayout();
this._update();
map
.on('layeradd', this._onLayerChange, this)
.on('layerremove', this._onLayerChange, this);
return this._container;
},
onRemove: function (map) {
map
.off('layeradd', this._onLayerChange, this)
.off('layerremove', this._onLayerChange, this);
},
addBaseLayer: function (layer, name) {
this._addLayer(layer, name);
this._update();
return this;
},
addOverlay: function (layer, name, group) {
this._addLayer(layer, name, group, true);
this._update();
return this;
},
removeLayer: function (layer) {
var id = L.Util.stamp(layer);
var _layer = this._getLayer(id);
if (_layer) {
delete this._layers[this._layers.indexOf(_layer)];
}
this._update();
return this;
},
_getLayer: function (id) {
for (var i = 0; i < this._layers.length; i++) {
if (this._layers[i] && L.stamp(this._layers[i].layer) === id) {
return this._layers[i];
}
}
},
_initLayout: function () {
var className = 'leaflet-control-layers',
container = this._container = L.DomUtil.create('div', className);
// Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released
container.setAttribute('aria-haspopup', true);
if (L.Browser.touch) {
L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation);
} else {
L.DomEvent.disableClickPropagation(container);
L.DomEvent.on(container, 'wheel', L.DomEvent.stopPropagation);
}
var form = this._form = L.DomUtil.create('form', className + '-list');
if (this.options.collapsed) {
if (!L.Browser.android) {
L.DomEvent
.on(container, 'mouseover', this._expand, this)
.on(container, 'mouseout', this._collapse, this);
}
var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container);
link.href = '#';
link.title = 'Layers';
if (L.Browser.touch) {
L.DomEvent
.on(link, 'click', L.DomEvent.stop)
.on(link, 'click', this._expand, this);
} else {
L.DomEvent.on(link, 'focus', this._expand, this);
}
this._map.on('click', this._collapse, this);
// TODO keyboard accessibility
} else {
this._expand();
}
this._baseLayersList = L.DomUtil.create('div', className + '-base', form);
this._separator = L.DomUtil.create('div', className + '-separator', form);
this._overlaysList = L.DomUtil.create('div', className + '-overlays', form);
container.appendChild(form);
},
_addLayer: function (layer, name, group, overlay) {
var id = L.Util.stamp(layer);
var _layer = {
layer: layer,
name: name,
overlay: overlay
};
this._layers.push(_layer);
group = group || '';
var groupId = this._indexOf(this._groupList, group);
if (groupId === -1) {
groupId = this._groupList.push(group) - 1;
}
var exclusive = (this._indexOf(this.options.exclusiveGroups, group) !== -1);
_layer.group = {
name: group,
id: groupId,
exclusive: exclusive
};
if (this.options.autoZIndex && layer.setZIndex) {
this._lastZIndex++;
layer.setZIndex(this._lastZIndex);
}
},
_update: function () {
if (!this._container) {
return;
}
this._baseLayersList.innerHTML = '';
this._overlaysList.innerHTML = '';
this._domGroups.length = 0;
var baseLayersPresent = false,
overlaysPresent = false,
i, obj;
for (var i = 0; i < this._layers.length; i++) {
obj = this._layers[i];
this._addItem(obj);
overlaysPresent = overlaysPresent || obj.overlay;
baseLayersPresent = baseLayersPresent || !obj.overlay;
}
this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none';
},
_onLayerChange: function (e) {
var obj = this._getLayer(L.Util.stamp(e.layer)),
type;
if (!obj) {
return;
}
if (!this._handlingClick) {
this._update();
}
if (obj.overlay) {
type = e.type === 'layeradd' ? 'overlayadd' : 'overlayremove';
} else {
type = e.type === 'layeradd' ? 'baselayerchange' : null;
}
if (type) {
this._map.fire(type, obj);
}
},
// IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe)
_createRadioElement: function (name, checked) {
var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' + name + '"';
if (checked) {
radioHtml += ' checked="checked"';
}
radioHtml += '/>';
var radioFragment = document.createElement('div');
radioFragment.innerHTML = radioHtml;
return radioFragment.firstChild;
},
_addItem: function (obj) {
var label = document.createElement('label'),
input,
checked = this._map.hasLayer(obj.layer),
container,
groupRadioName;
if (obj.overlay) {
if (obj.group.exclusive) {
groupRadioName = 'leaflet-exclusive-group-layer-' + obj.group.id;
input = this._createRadioElement(groupRadioName, checked);
} else {
input = document.createElement('input');
input.type = 'checkbox';
input.className = 'leaflet-control-layers-selector';
input.defaultChecked = checked;
}
} else {
input = this._createRadioElement('leaflet-base-layers', checked);
}
input.layerId = L.Util.stamp(obj.layer);
input.groupID = obj.group.id;
L.DomEvent.on(input, 'click', this._onInputClick, this);
var name = document.createElement('span');
name.innerHTML = ' ' + obj.name;
label.appendChild(input);
label.appendChild(name);
if (obj.overlay) {
container = this._overlaysList;
var groupContainer = this._domGroups[obj.group.id];
// Create the group container if it doesn't exist
if (!groupContainer) {
groupContainer = document.createElement('div');
groupContainer.className = 'leaflet-control-layers-group';
groupContainer.id = 'leaflet-control-layers-group-' + obj.group.id;
var groupLabel = document.createElement('label');
groupLabel.className = 'leaflet-control-layers-group-label';
if (obj.group.name !== '' && !obj.group.exclusive) {
// ------ add a group checkbox with an _onInputClickGroup function
if (this.options.groupCheckboxes) {
var groupInput = document.createElement('input');
groupInput.type = 'checkbox';
groupInput.className = 'leaflet-control-layers-group-selector';
groupInput.groupID = obj.group.id;
groupInput.legend = this;
L.DomEvent.on(groupInput, 'click', this._onGroupInputClick, groupInput);
groupLabel.appendChild(groupInput);
}
}
var groupName = document.createElement('span');
groupName.className = 'leaflet-control-layers-group-name';
groupName.innerHTML = obj.group.name;
groupLabel.appendChild(groupName);
groupContainer.appendChild(groupLabel);
container.appendChild(groupContainer);
this._domGroups[obj.group.id] = groupContainer;
}
container = groupContainer;
} else {
container = this._baseLayersList;
}
container.appendChild(label);
return label;
},
_onGroupInputClick: function () {
var i, input, obj;
var this_legend = this.legend;
this_legend._handlingClick = true;
var inputs = this_legend._form.getElementsByTagName('input');
var inputsLen = inputs.length;
for (i = 0; i < inputsLen; i++) {
input = inputs[i];
if (input.groupID === this.groupID && input.className === 'leaflet-control-layers-selector') {
input.checked = this.checked;
obj = this_legend._getLayer(input.layerId);
if (input.checked && !this_legend._map.hasLayer(obj.layer)) {
this_legend._map.addLayer(obj.layer);
} else if (!input.checked && this_legend._map.hasLayer(obj.layer)) {
this_legend._map.removeLayer(obj.layer);
}
}
}
this_legend._handlingClick = false;
},
_onInputClick: function () {
var i, input, obj,
inputs = this._form.getElementsByTagName('input'),
inputsLen = inputs.length;
this._handlingClick = true;
for (i = 0; i < inputsLen; i++) {
input = inputs[i];
if (input.className === 'leaflet-control-layers-selector') {
obj = this._getLayer(input.layerId);
if (input.checked && !this._map.hasLayer(obj.layer)) {
this._map.addLayer(obj.layer);
} else if (!input.checked && this._map.hasLayer(obj.layer)) {
this._map.removeLayer(obj.layer);
}
}
}
this._handlingClick = false;
},
_expand: function () {
L.DomUtil.addClass(this._container, 'leaflet-control-layers-expanded');
// permits to have a scrollbar if overlays heighter than the map.
var acceptableHeight = this._map._size.y - (this._container.offsetTop * 4);
if (acceptableHeight < this._form.clientHeight) {
L.DomUtil.addClass(this._form, 'leaflet-control-layers-scrollbar');
this._form.style.height = acceptableHeight + 'px';
}
},
_collapse: function () {
this._container.className = this._container.className.replace(' leaflet-control-layers-expanded', '');
},
_indexOf: function (arr, obj) {
for (var i = 0, j = arr.length; i < j; i++) {
if (arr[i] === obj) {
return i;
}
}
return -1;
}
});
L.control.groupedLayers = function (baseLayers, groupedOverlays, options) {
return new L.Control.GroupedLayers(baseLayers, groupedOverlays, options);
};

View File

@ -1,60 +0,0 @@
.marker-cluster-small {
background-color: rgba(181, 226, 140, 0.6);
}
.marker-cluster-small div {
background-color: rgba(110, 204, 57, 0.6);
}
.marker-cluster-medium {
background-color: rgba(241, 211, 87, 0.6);
}
.marker-cluster-medium div {
background-color: rgba(240, 194, 12, 0.6);
}
.marker-cluster-large {
background-color: rgba(253, 156, 115, 0.6);
}
.marker-cluster-large div {
background-color: rgba(241, 128, 23, 0.6);
}
/* IE 6-8 fallback colors */
.leaflet-oldie .marker-cluster-small {
background-color: rgb(181, 226, 140);
}
.leaflet-oldie .marker-cluster-small div {
background-color: rgb(110, 204, 57);
}
.leaflet-oldie .marker-cluster-medium {
background-color: rgb(241, 211, 87);
}
.leaflet-oldie .marker-cluster-medium div {
background-color: rgb(240, 194, 12);
}
.leaflet-oldie .marker-cluster-large {
background-color: rgb(253, 156, 115);
}
.leaflet-oldie .marker-cluster-large div {
background-color: rgb(241, 128, 23);
}
.marker-cluster {
background-clip: padding-box;
border-radius: 20px;
}
.marker-cluster div {
width: 30px;
height: 30px;
margin-left: 5px;
margin-top: 5px;
text-align: center;
border-radius: 15px;
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
}
.marker-cluster span {
line-height: 30px;
}

Some files were not shown because too many files have changed in this diff Show More