diff --git a/.github/workflows/docker-buildx-dev.yml b/.github/workflows/docker-buildx-dev.yml
index f0ac78f2..1255cc43 100644
--- a/.github/workflows/docker-buildx-dev.yml
+++ b/.github/workflows/docker-buildx-dev.yml
@@ -57,7 +57,7 @@ jobs:
run: |
docker buildx build \
--platform linux/arm64 \
- -f docker/Dockerfile.shelly.bookworm \
+ -f docker/Dockerfile.dev_shelly.bookworm \
-t luligu/matterbridge:dev_shelly \
--push .
docker manifest inspect luligu/matterbridge:dev_shelly
@@ -73,3 +73,13 @@ jobs:
docker manifest inspect luligu/matterbridge:dev
timeout-minutes: 60
+ - name: Run Docker Buildx on test
+ run: |
+ docker buildx build \
+ --platform linux/amd64,linux/arm64,linux/arm/v7 \
+ -f docker/Dockerfile.latest \
+ -t luligu/matterbridge:test \
+ --push .
+ docker manifest inspect luligu/matterbridge:test
+ timeout-minutes: 60
+
diff --git a/.npmignore b/.npmignore
index 20e608a5..ff1b8820 100644
--- a/.npmignore
+++ b/.npmignore
@@ -201,4 +201,5 @@ test
migrationV8.txt
migrationV8-answered.txt
-TODO.md
\ No newline at end of file
+TODO.md
+CODEOWNERS
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 53ccc6b7..fcd3a324 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ If you like this project and find it useful, please consider giving it a star on
### Home Assistant Community Add-ons
The Home Assistant Community Add-ons and plugins are not verified to work with Matterbridge. I strongly advise against using them. If you do use them and encounter an issue (which is likely because some do not meet the Matterbridge guidelines), please do not open an issue in the Matterbridge repository.
+
If you want to run Matterbridge in Home Assistant please use the official add-on https://github.com/Luligu/matterbridge-home-assistant-addon.
### New Apple firmware v. 18.0
@@ -19,6 +20,18 @@ Tamer (https://github.com/tammeryousef1006) has created the Matterbridge Discord
Feel free to join!
+## [1.5.10] - 2024-10-01
+
+### Changed
+
+- [matterbridge]: Added '--omit=dev' to all install commands to save space and time on low powered devices.
+- [matterbridge]: Integrated the DeviceManager class and removed the old array.
+- [package]: Update dependencies.
+
+
+
+
+
## [1.5.9] - 2024-09-23
### Fixed
diff --git a/README-DEV.md b/README-DEV.md
index d32bc13a..b2285272 100644
--- a/README-DEV.md
+++ b/README-DEV.md
@@ -43,23 +43,27 @@ Matterbridge exports from:
- NodeStorage classes.
-# ****\*\*****
+# \***\*\*\*\*\***
-A plugin must never install or import from `matter-node.js` or `matter.js` directly, as this leads to a second instance of `matter.js`, causing instability and unpredictable errors such as "The only instance is Endpoint". Additionally, when Matterbridge updates the `matter.js` version, it should be consistent across all plugins.
+A plugin must never install or import from `matter-node.js` or `matter.js` directly (neither as a dependency, devDependency, nor peerDependency), as this leads to a second instance of `matter.js`, causing instability and unpredictable errors such as "The only instance is Endpoint".
-# ****\*\*****
+Additionally, when Matterbridge updates the `matter.js` version, it should be consistent across all plugins.
-A plugin must never install Matterbridge (neither as dependencies nor as devDependencies). Matterbridge must be linked to the plugin:
+# \***\*\*\*\*\***
+
+A plugin must never install Matterbridge (neither as a dependency, devDependency, nor peerDependency).
+
+Matterbridge must be linked to the plugin in development only.
```json
"scripts": {
'''
- "install": "node link-matterbridge-script.js",
+ "dev:link": "npm link matterbridge",
'''
}
```
-# ****\*\*****
+# \***\*\*\*\*\***
In the next releases I will remove the duplicated exports so please update your plugins.
diff --git a/README-PODMAN.md b/README-PODMAN.md
index bf527aa1..c2a7d5f4 100644
--- a/README-PODMAN.md
+++ b/README-PODMAN.md
@@ -41,6 +41,7 @@ sudo chown -R $USER:$USER ./Matterbridge ./.matterbridge
```
You may need to adapt the script to your setup:
+
- ./Matterbridge is the position outside of the container of your matterbridge plugin directory (inside your home directory).
- ./.matterbridge is the position outside of the container of your matterbridge storage directory (inside your home directory).
@@ -56,6 +57,7 @@ podman run --name matterbridge \
```
You may need to adapt the script to your setup:
+
- ~/Matterbridge is the position outside of the container of your matterbridge plugin directory.
- ~/.matterbridge is the position outside of the container of your matterbridge storage directory.
diff --git a/README-SERVICE.md b/README-SERVICE.md
index fb1ab189..d1e97df7 100644
--- a/README-SERVICE.md
+++ b/README-SERVICE.md
@@ -105,48 +105,86 @@ sudo journalctl -u matterbridge.service -f --output cat
### Delete the logs older then 3 days (all of them not only the ones of Matterbridge!)
+Check the space used
+
+```
+sudo journalctl --disk-usage
+```
+
+remove all log older then 3 days
+
```
+sudo journalctl --rotate
sudo journalctl --vacuum-time=3d
```
-If you want to make the setting permanent edit
+## Prevent the journal logs to grow
+
+If you want to make the setting permanent to prevent the journal logs to grow too much, run
+
```
sudo nano /etc/systemd/journald.conf
```
+
add
+
```
-SystemMaxUse=3d
+Compress=yes # Compress logs
+MaxRetentionSec=3days # Keep logs for a maximum of 3 days.
+MaxFileSec=1day # Rotate logs daily within the 3-day retention period.
+ForwardToSyslog=no # Disable forwarding to syslog to prevent duplicate logging.
+SystemMaxUse=100M # Limit persistent logs in /var/log/journal to 100 MB.
+RuntimeMaxUse=100M # Limit runtime logs in /run/log/journal to 100 MB.
```
+
save it and run
+
```
sudo systemctl restart systemd-journald
```
-### Verify that with your distro you can run sudo npm install -g matterbridge without the password
+## Verify that with your distro you can run sudo npm install -g matterbridge without the password
Run the following command to verify if you can install Matterbridge globally without being prompted for a password:
```
sudo npm install -g matterbridge
```
+
If you are not prompted for a password, no further action is required.
If that is not the case, open the sudoers file for editing using visudo
+
```
sudo visudo
```
+verify the presence of of a line
+
+```
+@includedir /etc/sudoers.d
+```
+
+exit and create a configuration file for sudoers
+
+```
+sudo nano /etc/sudoers.d/matterbridge
+```
+
add this line replacing USER with your user name (e.g. radxa ALL=(ALL) NOPASSWD: ALL)
```
ALL=(ALL) NOPASSWD: ALL
```
-or if you prefers to only give access to npm without password try (e.g. radxa ALL=(ALL) NOPASSWD: /usr/bin/npm)
+or if you prefers to only give access to npm without password try with (e.g. radxa ALL=(ALL) NOPASSWD: /usr/bin/npm)
```
ALL=(ALL) NOPASSWD: /usr/bin/npm
```
-save the file and restart the system.
+save the file and reload the settings with:
+```
+sudo visudo -c
+```
diff --git a/README.md b/README.md
index 94c0767a..fa617a3b 100644
--- a/README.md
+++ b/README.md
@@ -320,6 +320,52 @@ matterbridge -factoryreset
This will reset the internal storages. All commissioning informations will be lost. All plugins will be unregistered.
+# Frequently asked questions
+
+## How to enable HTTPS for the frontend
+
+### Provide your own certificates
+
+Place your own certificates in the `.matterbridge/cert` directory:
+
+- `cert.pem`
+- `key.pem`
+- `ca.pem` (optional)
+
+![image](https://github.com/user-attachments/assets/846785ca-6f5c-458b-b786-a6417a4da319)
+
+### Change the command line
+
+Add the **-ssl** parameter to the command line. If desired, you can also change the frontend port with **-frontend 443**.
+
+```sh
+matterbridge -ssl -frontend 443
+```
+
+### Restart
+
+If the certificate are correctly configured, you will be able to connect with https to the frontend.
+
+![image](https://github.com/user-attachments/assets/9c38776d-064f-4d91-9359-a2cd3319b1ff)
+
+## How to send the debug log files
+
+### Enable debug and log on file
+
+In the frontend, go to settings and enable debug mode as shown below:
+
+![Debug Matterbridge Settings](https://github.com/user-attachments/assets/83181dc2-969a-4b71-aff4-f1498fa1d665)
+
+![Debug Matter Settings](https://github.com/user-attachments/assets/617961a9-7cb0-46cf-9878-981f61738f8c)
+
+### Restart
+
+Wait a few minutes to allow the logs to to accumulate.
+
+Then, from the dots menu in the frontend, download the `matterbridge.log` and `matter.log` files.
+
+![image](https://github.com/user-attachments/assets/04ba65f6-594a-4ff8-9732-3df049f5a33e)
+
# Known general issues
## Session XYZ does not exist
diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev
index f65176e8..2e67f073 100644
--- a/docker/Dockerfile.dev
+++ b/docker/Dockerfile.dev
@@ -12,60 +12,60 @@ RUN apt-get update && \
FROM base AS builder
WORKDIR /app
-COPY ./package.json ./package-lock.json ./tsconfig.json ./
+COPY ./package.json ./package-lock.json ./tsconfig.json ./.npmignore ./
COPY ./src ./src
COPY ./frontend/build ./frontend/build
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack && npm link
+RUN npm ci && npm run build && npm link && npm shrinkwrap && npm pack
WORKDIR /matterbridge-zigbee2mqtt
RUN GIT_SSL_NO_VERIFY=true git clone -b dev https://github.com/Luligu/matterbridge-zigbee2mqtt.git .
COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
+RUN npm ci && npm run build && npm shrinkwrap && npm pack
WORKDIR /matterbridge-somfy-tahoma
RUN GIT_SSL_NO_VERIFY=true git clone -b dev https://github.com/Luligu/matterbridge-somfy-tahoma.git .
COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
+RUN npm ci && npm run build && npm shrinkwrap && npm pack
WORKDIR /matterbridge-shelly
RUN GIT_SSL_NO_VERIFY=true git clone -b dev https://github.com/Luligu/matterbridge-shelly.git .
-COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
+# COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
+RUN npm ci && npm link matterbridge && npm run build && npm shrinkwrap && npm pack
WORKDIR /matterbridge-example-accessory-platform
RUN GIT_SSL_NO_VERIFY=true git clone https://github.com/Luligu/matterbridge-example-accessory-platform.git .
COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
+RUN npm ci && npm run build && npm shrinkwrap && npm pack
WORKDIR /matterbridge-example-dynamic-platform
RUN GIT_SSL_NO_VERIFY=true git clone https://github.com/Luligu/matterbridge-example-dynamic-platform.git .
COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
+RUN npm ci && npm run build && npm shrinkwrap && npm pack
WORKDIR /matterbridge-eve-door
RUN GIT_SSL_NO_VERIFY=true git clone https://github.com/Luligu/matterbridge-eve-door.git .
COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
+RUN npm ci && npm run build && npm shrinkwrap && npm pack
WORKDIR /matterbridge-eve-motion
RUN GIT_SSL_NO_VERIFY=true git clone https://github.com/Luligu/matterbridge-eve-motion.git .
COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
+RUN npm ci && npm run build && npm shrinkwrap && npm pack
WORKDIR /matterbridge-eve-energy
RUN GIT_SSL_NO_VERIFY=true git clone https://github.com/Luligu/matterbridge-eve-energy.git .
COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
+RUN npm ci && npm run build && npm shrinkwrap && npm pack
WORKDIR /matterbridge-eve-room
RUN GIT_SSL_NO_VERIFY=true git clone https://github.com/Luligu/matterbridge-eve-room.git .
COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
+RUN npm ci && npm run build && npm shrinkwrap && npm pack
WORKDIR /matterbridge-eve-weather
RUN GIT_SSL_NO_VERIFY=true git clone https://github.com/Luligu/matterbridge-eve-weather.git .
COPY docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
+RUN npm ci && npm run build && npm shrinkwrap && npm pack
@@ -73,7 +73,7 @@ FROM node:22-bookworm-slim AS release
WORKDIR /app
COPY --from=builder /app/*.tgz .
-RUN npm install -g npm@latest && npm -g install *.tgz && rm *.tgz
+RUN npm install -g npm@latest && npm install -g --omit=dev *.tgz && rm *.tgz
COPY --from=builder /matterbridge-zigbee2mqtt/*.tgz .
COPY --from=builder /matterbridge-somfy-tahoma/*.tgz .
@@ -85,6 +85,6 @@ COPY --from=builder /matterbridge-eve-motion/*.tgz .
COPY --from=builder /matterbridge-eve-energy/*.tgz .
COPY --from=builder /matterbridge-eve-room/*.tgz .
COPY --from=builder /matterbridge-eve-weather/*.tgz .
-RUN npm install -g *.tgz && rm *.tgz && node -v && npm -v && npm list -g
+RUN npm install -g --omit=dev *.tgz && rm *.tgz && node -v && npm -v && npm list -g
CMD ["matterbridge", "-docker"]
diff --git a/docker/Dockerfile.shelly.alpine b/docker/Dockerfile.dev_shelly.alpine
similarity index 100%
rename from docker/Dockerfile.shelly.alpine
rename to docker/Dockerfile.dev_shelly.alpine
diff --git a/docker/Dockerfile.shelly.bookworm b/docker/Dockerfile.dev_shelly.bookworm
similarity index 72%
rename from docker/Dockerfile.shelly.bookworm
rename to docker/Dockerfile.dev_shelly.bookworm
index 6a199a1f..2c0e7d26 100644
--- a/docker/Dockerfile.shelly.bookworm
+++ b/docker/Dockerfile.dev_shelly.bookworm
@@ -10,21 +10,23 @@ RUN apt-get update && \
# Build Matterbridge
WORKDIR /matterbridge
-COPY ./package.json ./package-lock.json ./tsconfig.json ./
+COPY ./package.json ./package-lock.json ./tsconfig.json ./.npmignore ./
COPY ./src ./src
COPY ./frontend/build ./frontend/build
RUN npm ci && \
npm run build && \
- npm shrinkwrap --omit=dev && \
+ npm link && \
+ npm shrinkwrap && \
npm pack
# Build shelly plugin
WORKDIR /matterbridge-shelly
RUN GIT_SSL_NO_VERIFY=true git clone -b dev https://github.com/Luligu/matterbridge-shelly.git .
-COPY ./docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
+# COPY ./docker/link-matterbridge-docker-script.js ./link-matterbridge-script.js
RUN npm ci && \
+ npm link matterbridge && \
npm run build && \
- npm shrinkwrap --omit=dev && \
+ npm shrinkwrap && \
npm pack
@@ -32,10 +34,10 @@ FROM node:22-bookworm-slim AS release
WORKDIR /app
COPY --from=base /matterbridge/*.tgz .
-RUN npm install -g npm@latest && npm -g install *.tgz && rm *.tgz
+RUN npm install -g npm@latest && npm install -g --omit=dev *.tgz && rm *.tgz
COPY --from=base /matterbridge-shelly/*.tgz .
-RUN npm -g install *.tgz && rm *.tgz
+RUN npm install -g --omit=dev *.tgz && rm *.tgz
# Copy and execute the entrypoint script
COPY ./docker/shellyEntrypoint.sh ./
diff --git a/docker/Dockerfile.shelly.bullseye b/docker/Dockerfile.dev_shelly.bullseye
similarity index 100%
rename from docker/Dockerfile.shelly.bullseye
rename to docker/Dockerfile.dev_shelly.bullseye
diff --git a/docker/Dockerfile.latest b/docker/Dockerfile.latest
index 91e2f221..4a5c2878 100644
--- a/docker/Dockerfile.latest
+++ b/docker/Dockerfile.latest
@@ -1,33 +1,18 @@
-FROM node:22-bookworm-slim AS builder
-WORKDIR /app
-COPY ./package.json ./
-COPY ./package-lock.json ./
-COPY ./tsconfig.json ./
-COPY ./src ./src
-COPY ./frontend/build ./frontend/build
-RUN npm ci && npm run build && npm shrinkwrap --omit=dev && npm pack
-
-
-FROM node:22-bookworm-slim AS release
-WORKDIR /app
-COPY --from=builder /app/*.tgz .
+FROM node:22-bookworm-slim
RUN npm install -g npm@latest && \
- npm install -g *.tgz && \
- rm *.tgz && \
- npm install -g matterbridge-zigbee2mqtt && \
- npm install -g matterbridge-somfy-tahoma && \
- npm install -g matterbridge-shelly && \
- npm install -g matterbridge-example-accessory-platform && \
- npm install -g matterbridge-example-dynamic-platform && \
- npm install -g matterbridge-eve-door && \
- npm install -g matterbridge-eve-motion && \
- npm install -g matterbridge-eve-energy && \
- npm install -g matterbridge-eve-room && \
- npm install -g matterbridge-eve-weather && \
+ npm install -g --omit=dev matterbridge \
+ matterbridge-zigbee2mqtt \
+ matterbridge-somfy-tahoma \
+ matterbridge-shelly \
+ matterbridge-example-accessory-platform \
+ matterbridge-example-dynamic-platform \
+ matterbridge-eve-door \
+ matterbridge-eve-motion \
+ matterbridge-eve-energy \
+ matterbridge-eve-room \
+ matterbridge-eve-weather && \
node -v && \
npm -v && \
npm list -g
-
-WORKDIR /app
CMD ["matterbridge", "-docker"]
diff --git a/docker/Dockerfile.main b/docker/Dockerfile.main
index 65b5bcba..4524f702 100644
--- a/docker/Dockerfile.main
+++ b/docker/Dockerfile.main
@@ -21,16 +21,16 @@ COPY --from=builder /app/frontend/build ./frontend/build
RUN npm link
# Install Matterbridge plugins
-RUN npm install -g matterbridge-example-accessory-platform
-RUN npm install -g matterbridge-example-dynamic-platform
-RUN npm install -g matterbridge-zigbee2mqtt
-RUN npm install -g matterbridge-somfy-tahoma
-RUN npm install -g matterbridge-shelly
-RUN npm install -g matterbridge-eve-door
-RUN npm install -g matterbridge-eve-motion
-RUN npm install -g matterbridge-eve-energy
-RUN npm install -g matterbridge-eve-room
-RUN npm install -g matterbridge-eve-weather
+RUN npm install -g --omit=dev matterbridge-example-accessory-platform
+RUN npm install -g --omit=dev matterbridge-example-dynamic-platform
+RUN npm install -g --omit=dev matterbridge-zigbee2mqtt
+RUN npm install -g --omit=dev matterbridge-somfy-tahoma
+RUN npm install -g --omit=dev matterbridge-shelly
+RUN npm install -g --omit=dev matterbridge-eve-door
+RUN npm install -g --omit=dev matterbridge-eve-motion
+RUN npm install -g --omit=dev matterbridge-eve-energy
+RUN npm install -g --omit=dev matterbridge-eve-room
+RUN npm install -g --omit=dev matterbridge-eve-weather
WORKDIR /app
CMD ["matterbridge", "-docker"]
diff --git a/docker/Dockerfile.shelly b/docker/Dockerfile.shelly
index f4cf139b..fb29e49c 100644
--- a/docker/Dockerfile.shelly
+++ b/docker/Dockerfile.shelly
@@ -3,8 +3,8 @@ WORKDIR /app
COPY ./docker/shellyEntrypoint.sh ./
RUN chmod +x ./shellyEntrypoint.sh && \
npm install -g npm@latest && \
- npm install -g matterbridge && \
- npm install -g matterbridge-shelly && \
+ npm install -g --omit=dev matterbridge && \
+ npm install -g --omit=dev matterbridge-shelly && \
node -v && \
npm -v && \
npm list -g
diff --git a/package-lock.json b/package-lock.json
index 015cfc9e..3777d28a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "matterbridge",
- "version": "1.5.9",
+ "version": "1.5.10-dev.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "matterbridge",
- "version": "1.5.9",
+ "version": "1.5.10-dev.7",
"license": "Apache-2.0",
"dependencies": {
"@project-chip/matter-node.js": "0.10.6",
@@ -24,23 +24,23 @@
"matterbridge": "dist/cli.js"
},
"devDependencies": {
- "@eslint/js": "9.11.0",
+ "@eslint/js": "9.11.1",
"@types/archiver": "6.0.2",
"@types/eslint__js": "8.42.3",
- "@types/express": "4.17.21",
+ "@types/express": "5.0.0",
"@types/jest": "29.5.13",
- "@types/node": "22.5.5",
+ "@types/node": "22.7.4",
"@types/ws": "8.5.12",
- "eslint": "9.11.0",
+ "eslint": "9.11.1",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-jest": "28.8.3",
"eslint-plugin-prettier": "5.2.1",
"jest": "29.7.0",
"prettier": "3.3.3",
- "rimraf": "6.0.1",
+ "rimraf": "^6.0.1",
"ts-jest": "29.2.5",
"typescript": "5.6.2",
- "typescript-eslint": "8.6.0"
+ "typescript-eslint": "8.8.0"
},
"engines": {
"node": ">=18.0.0"
@@ -742,6 +742,16 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@eslint/core": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz",
+ "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
"node_modules/@eslint/eslintrc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz",
@@ -767,9 +777,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.11.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.0.tgz",
- "integrity": "sha512-LPkkenkDqyzTFauZLLAPhIb48fj6drrfMvRGSL9tS3AcZBSVTllemLSNyCvHNNL2t797S/6DJNSIwRwXgMO/eQ==",
+ "version": "9.11.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz",
+ "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1597,22 +1607,22 @@
"license": "MIT"
},
"node_modules/@types/express": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
- "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz",
+ "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/body-parser": "*",
- "@types/express-serve-static-core": "^4.17.33",
+ "@types/express-serve-static-core": "^5.0.0",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"node_modules/@types/express-serve-static-core": {
- "version": "4.19.5",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz",
- "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.0.tgz",
+ "integrity": "sha512-AbXMTZGt40T+KON9/Fdxx0B2WK5hsgxcfXJLr5bFpZ7b4JCex2WyQPTEKdXqfHiY5nKKBScZ7yCoO6Pvgxfvnw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1692,9 +1702,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "22.5.5",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz",
- "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==",
+ "version": "22.7.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz",
+ "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1783,17 +1793,17 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz",
- "integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz",
+ "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.6.0",
- "@typescript-eslint/type-utils": "8.6.0",
- "@typescript-eslint/utils": "8.6.0",
- "@typescript-eslint/visitor-keys": "8.6.0",
+ "@typescript-eslint/scope-manager": "8.8.0",
+ "@typescript-eslint/type-utils": "8.8.0",
+ "@typescript-eslint/utils": "8.8.0",
+ "@typescript-eslint/visitor-keys": "8.8.0",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@@ -1817,16 +1827,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz",
- "integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz",
+ "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.6.0",
- "@typescript-eslint/types": "8.6.0",
- "@typescript-eslint/typescript-estree": "8.6.0",
- "@typescript-eslint/visitor-keys": "8.6.0",
+ "@typescript-eslint/scope-manager": "8.8.0",
+ "@typescript-eslint/types": "8.8.0",
+ "@typescript-eslint/typescript-estree": "8.8.0",
+ "@typescript-eslint/visitor-keys": "8.8.0",
"debug": "^4.3.4"
},
"engines": {
@@ -1846,14 +1856,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz",
- "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz",
+ "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.6.0",
- "@typescript-eslint/visitor-keys": "8.6.0"
+ "@typescript-eslint/types": "8.8.0",
+ "@typescript-eslint/visitor-keys": "8.8.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1864,14 +1874,14 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz",
- "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz",
+ "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.6.0",
- "@typescript-eslint/utils": "8.6.0",
+ "@typescript-eslint/typescript-estree": "8.8.0",
+ "@typescript-eslint/utils": "8.8.0",
"debug": "^4.3.4",
"ts-api-utils": "^1.3.0"
},
@@ -1889,9 +1899,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz",
- "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz",
+ "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1903,14 +1913,14 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz",
- "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz",
+ "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "@typescript-eslint/types": "8.6.0",
- "@typescript-eslint/visitor-keys": "8.6.0",
+ "@typescript-eslint/types": "8.8.0",
+ "@typescript-eslint/visitor-keys": "8.8.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -1958,16 +1968,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz",
- "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz",
+ "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "8.6.0",
- "@typescript-eslint/types": "8.6.0",
- "@typescript-eslint/typescript-estree": "8.6.0"
+ "@typescript-eslint/scope-manager": "8.8.0",
+ "@typescript-eslint/types": "8.8.0",
+ "@typescript-eslint/typescript-estree": "8.8.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1981,13 +1991,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz",
- "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz",
+ "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.6.0",
+ "@typescript-eslint/types": "8.8.0",
"eslint-visitor-keys": "^3.4.3"
},
"engines": {
@@ -2267,9 +2277,9 @@
"license": "MIT"
},
"node_modules/b4a": {
- "version": "1.6.6",
- "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz",
- "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==",
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
+ "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==",
"license": "Apache-2.0"
},
"node_modules/babel-jest": {
@@ -2405,9 +2415,9 @@
"license": "MIT"
},
"node_modules/bare-events": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz",
- "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==",
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz",
+ "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==",
"license": "Apache-2.0",
"optional": true
},
@@ -2495,9 +2505,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.23.3",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
- "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
+ "version": "4.24.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
+ "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
"dev": true,
"funding": [
{
@@ -2515,8 +2525,8 @@
],
"license": "MIT",
"dependencies": {
- "caniuse-lite": "^1.0.30001646",
- "electron-to-chromium": "^1.5.4",
+ "caniuse-lite": "^1.0.30001663",
+ "electron-to-chromium": "^1.5.28",
"node-releases": "^2.0.18",
"update-browserslist-db": "^1.1.0"
},
@@ -2639,9 +2649,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001663",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz",
- "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==",
+ "version": "1.0.30001664",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz",
+ "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==",
"dev": true,
"funding": [
{
@@ -3068,9 +3078,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.5.27",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz",
- "integrity": "sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==",
+ "version": "1.5.30",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.30.tgz",
+ "integrity": "sha512-sXI35EBN4lYxzc/pIGorlymYNzDBOqkSlVRe6MkgBsW/hW1tpC/HDJ2fjG7XnjakzfLEuvdmux0Mjs6jHq4UOA==",
"dev": true,
"license": "ISC"
},
@@ -3163,21 +3173,24 @@
}
},
"node_modules/eslint": {
- "version": "9.11.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.0.tgz",
- "integrity": "sha512-yVS6XODx+tMFMDFcG4+Hlh+qG7RM6cCJXtQhCKLSsr3XkLvWggHjCqjfh0XsPPnt1c56oaT6PMgW9XWQQjdHXA==",
+ "version": "9.11.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz",
+ "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.11.0",
"@eslint/config-array": "^0.18.0",
+ "@eslint/core": "^0.6.0",
"@eslint/eslintrc": "^3.1.0",
- "@eslint/js": "9.11.0",
+ "@eslint/js": "9.11.1",
"@eslint/plugin-kit": "^0.2.0",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.3.0",
"@nodelib/fs.walk": "^1.2.8",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
"ajv": "^6.12.4",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@@ -3293,9 +3306,9 @@
}
},
"node_modules/eslint-scope": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz",
- "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz",
+ "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -3310,9 +3323,9 @@
}
},
"node_modules/eslint-visitor-keys": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
- "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz",
+ "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -3323,15 +3336,15 @@
}
},
"node_modules/espree": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz",
- "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==",
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz",
+ "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"acorn": "^8.12.0",
"acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.0.0"
+ "eslint-visitor-keys": "^4.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -4373,9 +4386,9 @@
}
},
"node_modules/jackspeak": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz",
- "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
+ "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
@@ -4385,9 +4398,6 @@
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
- },
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/jake": {
@@ -5665,9 +5675,9 @@
}
},
"node_modules/package-json-from-dist": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
- "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"license": "BlueOak-1.0.0"
},
"node_modules/parent-module": {
@@ -6950,15 +6960,15 @@
}
},
"node_modules/typescript-eslint": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.6.0.tgz",
- "integrity": "sha512-eEhhlxCEpCd4helh3AO1hk0UP2MvbRi9CtIAJTVPQjuSXOOO2jsEacNi4UdcJzZJbeuVg1gMhtZ8UYb+NFYPrA==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz",
+ "integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/eslint-plugin": "8.6.0",
- "@typescript-eslint/parser": "8.6.0",
- "@typescript-eslint/utils": "8.6.0"
+ "@typescript-eslint/eslint-plugin": "8.8.0",
+ "@typescript-eslint/parser": "8.8.0",
+ "@typescript-eslint/utils": "8.8.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6990,9 +7000,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
- "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
+ "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
"dev": true,
"funding": [
{
@@ -7010,8 +7020,8 @@
],
"license": "MIT",
"dependencies": {
- "escalade": "^3.1.2",
- "picocolors": "^1.0.1"
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.0"
},
"bin": {
"update-browserslist-db": "cli.js"
diff --git a/package.json b/package.json
index 76470d0b..6ed0cb05 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "matterbridge",
- "version": "1.5.9",
+ "version": "1.5.10",
"description": "Matterbridge plugin manager for Matter",
"author": "https://github.com/Luligu",
"license": "Apache-2.0",
@@ -91,7 +91,7 @@
"test:bridgemode": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand --verbose matterbridge.bridge.test.ts",
"test:childbridgemode": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand --verbose matterbridge.childbridge.test.ts",
"test:device": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand --verbose --coverage matterbridgeDevice.test.ts",
- "test:platform": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand --verbose matterbridgePlatform.test.ts matterbridgeAccessoryPlatform.test.ts matterbridgeDynamicPlatform.test.ts",
+ "test:platform": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand --verbose --coverage matterbridgePlatform.test.ts matterbridgeAccessoryPlatform.test.ts matterbridgeDynamicPlatform.test.ts",
"test:pluginManager": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand --verbose --coverage pluginManager.test.ts",
"test:deviceManager": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand --verbose --coverage deviceManager.test.ts",
"test:utils": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand --verbose utils.test.ts",
@@ -99,13 +99,14 @@
"lint:fix": "eslint --fix --max-warnings=0 .",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,md}\"",
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,md}\"",
- "clean": "rimraf tsconfig.tsbuildinfo ./dist",
+ "clean": "npm install --no-save rimraf && rimraf tsconfig.tsbuildinfo ./dist",
"cleanBuild": "npm run clean && npm run build",
- "deepClean": "rimraf tsconfig.tsbuildinfo package-lock.json npm-shrinkwrap.json ./dist ./node_modules",
- "deepCleanRebuild": "npm run deepClean && npm install && npm run build",
- "prepublishOnly": "npm run lint && npm run cleanBuild && npm shrinkwrap --omit=dev",
+ "deepClean": "npm install --no-save rimraf && rimraf tsconfig.tsbuildinfo package-lock.json npm-shrinkwrap.json ./dist ./node_modules",
+ "deepCleanBuild": "npm run deepClean && npm install && npm run build && npm link",
+ "prepublishOnly": "npm shrinkwrap",
+ "npmPack": "npm run deepCleanBuild && npm shrinkwrap && npm pack && npm run deepCleanBuild",
"checkDependencies": "npx npm-check-updates",
- "updateDependencies": "npx npm-check-updates -u && npm install & npm run cleanBuild",
+ "updateDependencies": "npx npm-check-updates -u && npm install && npm run cleanBuild",
"updateMatter:latest": "npm run deepClean && npm install @project-chip/matter-node.js@latest @project-chip/matter.js@latest && npm install && npm run build",
"updateMatter:dev": "npm run deepClean && npm install @project-chip/matter-node.js@dev @project-chip/matter.js@dev && npm install && npm run build",
"updateMatter:loc": "npm run deepClean && npm install ../matter.js/packages/matter-node.js ../matter.js/packages/matter.js && npm install && npm run build",
@@ -138,22 +139,22 @@
"ws": "8.18.0"
},
"devDependencies": {
- "@eslint/js": "9.11.0",
+ "@eslint/js": "9.11.1",
"@types/archiver": "6.0.2",
"@types/eslint__js": "8.42.3",
- "@types/express": "4.17.21",
+ "@types/express": "5.0.0",
"@types/jest": "29.5.13",
- "@types/node": "22.5.5",
+ "@types/node": "22.7.4",
"@types/ws": "8.5.12",
- "eslint": "9.11.0",
+ "eslint": "9.11.1",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-jest": "28.8.3",
"eslint-plugin-prettier": "5.2.1",
"jest": "29.7.0",
"prettier": "3.3.3",
- "rimraf": "6.0.1",
+ "rimraf": "^6.0.1",
"ts-jest": "29.2.5",
"typescript": "5.6.2",
- "typescript-eslint": "8.6.0"
+ "typescript-eslint": "8.8.0"
}
-}
\ No newline at end of file
+}
diff --git a/src/matterbridge.bridge.test.ts b/src/matterbridge.bridge.test.ts
index 325bd099..67040897 100644
--- a/src/matterbridge.bridge.test.ts
+++ b/src/matterbridge.bridge.test.ts
@@ -57,7 +57,7 @@ describe('Matterbridge loadInstance() and cleanup() -bridge mode', () => {
expect((matterbridge as any).nodeStorage).toBeDefined();
expect((matterbridge as any).nodeContext).toBeDefined();
expect((matterbridge as any).plugins).toBeDefined();
- expect((matterbridge as any).registeredDevices).toHaveLength(0);
+ expect((matterbridge as any).devices.size).toBe(0);
expect((matterbridge as any).httpServer).toBeDefined();
expect((matterbridge as any).httpsServer).toBeUndefined();
diff --git a/src/matterbridge.childbridge.test.ts b/src/matterbridge.childbridge.test.ts
index a69b746f..b2411280 100644
--- a/src/matterbridge.childbridge.test.ts
+++ b/src/matterbridge.childbridge.test.ts
@@ -57,7 +57,7 @@ describe('Matterbridge loadInstance() and cleanup() -childbridge mode', () => {
expect((matterbridge as any).nodeStorage).toBeDefined();
expect((matterbridge as any).nodeContext).toBeDefined();
expect((matterbridge as any).plugins).toBeDefined();
- expect((matterbridge as any).registeredDevices).toHaveLength(0);
+ expect((matterbridge as any).devices.size).toBe(0);
expect((matterbridge as any).httpServer).toBeDefined();
expect((matterbridge as any).httpsServer).toBeUndefined();
diff --git a/src/matterbridge.test.ts b/src/matterbridge.test.ts
index 4920f7f0..b2f75915 100644
--- a/src/matterbridge.test.ts
+++ b/src/matterbridge.test.ts
@@ -74,7 +74,7 @@ describe('Matterbridge loadInstance() and cleanup()', () => {
expect((matterbridge as any).nodeStorage).toBeUndefined();
expect((matterbridge as any).nodeContext).toBeUndefined();
expect((matterbridge as any).plugins).toBeUndefined();
- expect((matterbridge as any).registeredDevices).toHaveLength(0);
+ expect((matterbridge as any).devices).toBeUndefined();
expect((matterbridge as any).globalModulesDirectory).toBe('');
expect((matterbridge as any).matterbridgeLatestVersion).toBe('');
@@ -105,7 +105,7 @@ describe('Matterbridge loadInstance() and cleanup()', () => {
expect((matterbridge as any).nodeStorage).toBeDefined();
expect((matterbridge as any).nodeContext).toBeDefined();
expect((matterbridge as any).plugins).toBeDefined();
- expect((matterbridge as any).registeredDevices).toHaveLength(0);
+ expect((matterbridge as any).devices.size).toBe(0);
expect((matterbridge as any).httpServer).toBeUndefined();
expect((matterbridge as any).httpsServer).toBeUndefined();
@@ -136,7 +136,7 @@ describe('Matterbridge loadInstance() and cleanup()', () => {
expect((matterbridge as any).nodeStorage).toBeDefined();
expect((matterbridge as any).nodeContext).toBeDefined();
expect((matterbridge as any).plugins).toBeDefined();
- expect((matterbridge as any).registeredDevices).toHaveLength(0);
+ expect((matterbridge as any).devices.size).toBe(0);
expect((matterbridge as any).httpServer).toBeDefined();
expect((matterbridge as any).httpsServer).toBeUndefined();
diff --git a/src/matterbridge.ts b/src/matterbridge.ts
index 482a4ea8..89e8fb83 100644
--- a/src/matterbridge.ts
+++ b/src/matterbridge.ts
@@ -41,7 +41,7 @@ import { AnsiLogger, TimestampFormat, LogLevel, UNDERLINE, UNDERLINEOFF, YELLOW,
// Matterbridge
import { MatterbridgeDevice, SerializedMatterbridgeDevice } from './matterbridgeDevice.js';
import { logInterfaces, wait, waiter, createZip } from './utils/utils.js';
-import { BaseRegisteredPlugin, MatterbridgeInformation, RegisteredDevice, RegisteredPlugin, SanitizedExposedFabricInformation, SanitizedSessionInformation, SessionInformation, SystemInformation } from './matterbridgeTypes.js';
+import { BaseRegisteredPlugin, MatterbridgeInformation, RegisteredPlugin, SanitizedExposedFabricInformation, SanitizedSessionInformation, SessionInformation, SystemInformation } from './matterbridgeTypes.js';
import { PluginManager } from './pluginManager.js';
import { DeviceManager } from './deviceManager.js';
@@ -145,7 +145,6 @@ export class Matterbridge extends EventEmitter {
private matterLoggerFile = 'matter' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.log';
private plugins!: PluginManager;
private devices!: DeviceManager;
- private registeredDevices: RegisteredDevice[] = [];
private nodeStorage: NodeStorageManager | undefined;
private nodeContext: NodeStorage | undefined;
private matterStorageName = 'matterbridge' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.json';
@@ -265,6 +264,9 @@ export class Matterbridge extends EventEmitter {
// this.log.debug('Creating node storage context for matterbridge');
this.nodeContext = await this.nodeStorage.createStorage('matterbridge');
+ // Check if the storage is corrupted and remove it
+ // TODO: Check if the storage is corrupted and remove it
+
// Create matterbridge logger
this.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: TimestampFormat.TIME_MILLIS, logLevel: LogLevel.INFO });
@@ -376,7 +378,7 @@ export class Matterbridge extends EventEmitter {
// We don't do this when the add parameter is set because we shut down the process after adding the plugin
this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm.`);
try {
- await this.spawnCommand('npm', ['install', '-g', plugin.name]);
+ await this.spawnCommand('npm', ['install', '-g', '--omit=dev', plugin.name]);
this.log.info(`Plugin ${plg}${plugin.name}${nf} reinstalled.`);
plugin.error = false;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -514,28 +516,24 @@ export class Matterbridge extends EventEmitter {
if (getParameter('add')) {
this.log.debug(`Adding plugin ${getParameter('add')}`);
- // await this.executeCommandLine(getParameter('add') as string, 'add');
await this.plugins.add(getParameter('add') as string);
this.emit('shutdown');
return;
}
if (getParameter('remove')) {
this.log.debug(`Removing plugin ${getParameter('remove')}`);
- // await this.executeCommandLine(getParameter('remove') as string, 'remove');
await this.plugins.remove(getParameter('remove') as string);
this.emit('shutdown');
return;
}
if (getParameter('enable')) {
this.log.debug(`Enabling plugin ${getParameter('enable')}`);
- // await this.executeCommandLine(getParameter('enable') as string, 'enable');
await this.plugins.enable(getParameter('enable') as string);
this.emit('shutdown');
return;
}
if (getParameter('disable')) {
this.log.debug(`Disabling plugin ${getParameter('disable')}`);
- // await this.executeCommandLine(getParameter('disable') as string, 'disable');
await this.plugins.disable(getParameter('disable') as string);
this.emit('shutdown');
return;
@@ -558,7 +556,7 @@ export class Matterbridge extends EventEmitter {
this.nodeContext = undefined;
this.nodeStorage = undefined;
this.plugins.clear();
- this.registeredDevices = [];
+ this.devices.clear();
this.emit('shutdown');
return;
}
@@ -1254,13 +1252,14 @@ export class Matterbridge extends EventEmitter {
if (this.nodeStorage && this.nodeContext) {
this.log.info('Saving registered devices...');
const serializedRegisteredDevices: SerializedMatterbridgeDevice[] = [];
- this.registeredDevices.forEach((registeredDevice) => {
- const serializedMatterbridgeDevice = registeredDevice.device.serialize(registeredDevice.plugin);
+ this.devices.forEach(async (device) => {
+ const serializedMatterbridgeDevice = device.serialize();
// this.log.info(`- ${serializedMatterbridgeDevice.deviceName}${rs}\n`, serializedMatterbridgeDevice);
if (serializedMatterbridgeDevice) serializedRegisteredDevices.push(serializedMatterbridgeDevice);
});
await this.nodeContext.set('devices', serializedRegisteredDevices);
this.log.info(`Saved registered devices (${serializedRegisteredDevices?.length})`);
+
// Clear nodeContext and nodeStorage (they just need 1000ms to write the data to disk)
this.log.debug(`Closing node storage context for ${plg}Matterbridge${db}...`);
await this.nodeContext.close();
@@ -1280,7 +1279,8 @@ export class Matterbridge extends EventEmitter {
this.log.error('Error saving registered devices: nodeContext not found!');
}
this.plugins.clear();
- this.registeredDevices = [];
+ this.devices.clear();
+ // this.registeredDevices = [];
// this.log.info('Waiting for matter to deliver last messages...');
// this.cleanupTimeout2 = setTimeout(async () => {
@@ -1382,7 +1382,6 @@ export class Matterbridge extends EventEmitter {
plugin.aggregator?.addBridgedDevice(device);
}
}
- this.registeredDevices.push({ plugin: pluginName, device });
if (plugin.registeredDevices !== undefined) plugin.registeredDevices++;
if (plugin.addedDevices !== undefined) plugin.addedDevices++;
// Add the device to the DeviceManager
@@ -1419,12 +1418,6 @@ export class Matterbridge extends EventEmitter {
// device.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerShutDownEvent({});
// device.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerLeaveEvent({});
this.matterAggregator?.removeBridgedDevice(device);
- this.registeredDevices.forEach((registeredDevice, index) => {
- if (registeredDevice.device === device) {
- this.registeredDevices.splice(index, 1);
- return;
- }
- });
this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
if (plugin.registeredDevices !== undefined) plugin.registeredDevices--;
if (plugin.addedDevices !== undefined) plugin.addedDevices--;
@@ -1437,23 +1430,11 @@ export class Matterbridge extends EventEmitter {
this.log.error(`Error removing bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) for plugin ${plg}${pluginName}${er}: commissioning server not found`);
return;
}
- this.registeredDevices.forEach((registeredDevice, index) => {
- if (registeredDevice.device === device) {
- this.registeredDevices.splice(index, 1);
- return;
- }
- });
} else if (plugin.type === 'DynamicPlatform') {
if (!plugin.aggregator) {
this.log.error(`Error removing bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) for plugin ${plg}${pluginName}${er}: aggregator not found`);
return;
}
- this.registeredDevices.forEach((registeredDevice, index) => {
- if (registeredDevice.device === device) {
- this.registeredDevices.splice(index, 1);
- return;
- }
- });
if (device.number !== undefined) {
device.setBridgedDeviceReachability(false);
device.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerReachableChangedEvent({ reachableNewValue: false });
@@ -1483,19 +1464,15 @@ export class Matterbridge extends EventEmitter {
*/
async removeAllBridgedDevices(pluginName: string): Promise {
this.log.debug(`Removing all bridged devices for plugin ${plg}${pluginName}${db}`);
- const devicesToRemove: RegisteredDevice[] = [];
- for (const registeredDevice of this.registeredDevices) {
- if (registeredDevice.plugin === pluginName) {
- devicesToRemove.push(registeredDevice);
+ this.devices.forEach(async (device) => {
+ if (device.plugin === pluginName) {
+ await this.removeBridgedDevice(pluginName, device);
}
- }
- for (const registeredDevice of devicesToRemove) {
- this.removeBridgedDevice(pluginName, registeredDevice.device);
- }
+ });
}
private async startTest(): Promise {
- // Start the Matterbridge
+ // Start the Matterbridge test
}
/**
@@ -2581,7 +2558,7 @@ export class Matterbridge extends EventEmitter {
childProcess.on('close', (code, signal) => {
this.wssSendMessage('spawn', this.log.now(), 'Matterbridge:spawn', `child process closed with code ${code} and signal ${signal}`);
if (code === 0) {
- if (cmdLine.startsWith('npm install -g')) this.log.notice(`Package ${cmdLine.replace('npm install -g ', '').replace('--verbose', '')} installed correctly`);
+ if (cmdLine.startsWith('npm install -g')) this.log.notice(`Package ${cmdLine.replace('npm install -g ', '').replace('--verbose', '').replace('--omit=dev', '')} installed correctly`);
this.log.debug(`Child process "${cmdLine}" closed with code ${code} and signal ${signal}`);
resolve();
} else {
@@ -2887,18 +2864,18 @@ export class Matterbridge extends EventEmitter {
this.expressApp.get('/api/devices', (req, res) => {
this.log.debug('The frontend sent /api/devices');
const data: { pluginName: string; type: string; endpoint: EndpointNumber | undefined; name: string; serial: string; uniqueId: string; cluster: string }[] = [];
- this.registeredDevices.forEach((registeredDevice) => {
- let name = registeredDevice.device.getClusterServer(BasicInformationCluster)?.attributes.nodeLabel?.getLocal();
- if (!name) name = registeredDevice.device.getClusterServer(BridgedDeviceBasicInformationCluster)?.attributes.nodeLabel?.getLocal() ?? 'Unknown';
- let serial = registeredDevice.device.getClusterServer(BasicInformationCluster)?.attributes.serialNumber?.getLocal();
- if (!serial) serial = registeredDevice.device.getClusterServer(BridgedDeviceBasicInformationCluster)?.attributes.serialNumber?.getLocal() ?? 'Unknown';
- let uniqueId = registeredDevice.device.getClusterServer(BasicInformationCluster)?.attributes.uniqueId?.getLocal();
- if (!uniqueId) uniqueId = registeredDevice.device.getClusterServer(BridgedDeviceBasicInformationCluster)?.attributes.uniqueId?.getLocal() ?? 'Unknown';
- const cluster = this.getClusterTextFromDevice(registeredDevice.device);
+ this.devices.forEach(async (device) => {
+ let name = device.getClusterServer(BasicInformationCluster)?.attributes.nodeLabel?.getLocal();
+ if (!name) name = device.getClusterServer(BridgedDeviceBasicInformationCluster)?.attributes.nodeLabel?.getLocal() ?? 'Unknown';
+ let serial = device.getClusterServer(BasicInformationCluster)?.attributes.serialNumber?.getLocal();
+ if (!serial) serial = device.getClusterServer(BridgedDeviceBasicInformationCluster)?.attributes.serialNumber?.getLocal() ?? 'Unknown';
+ let uniqueId = device.getClusterServer(BasicInformationCluster)?.attributes.uniqueId?.getLocal();
+ if (!uniqueId) uniqueId = device.getClusterServer(BridgedDeviceBasicInformationCluster)?.attributes.uniqueId?.getLocal() ?? 'Unknown';
+ const cluster = this.getClusterTextFromDevice(device);
data.push({
- pluginName: registeredDevice.plugin,
- type: registeredDevice.device.name + ' (0x' + registeredDevice.device.deviceType.toString(16).padStart(4, '0') + ')',
- endpoint: registeredDevice.device.number,
+ pluginName: device.plugin ?? 'Unknown',
+ type: device.name + ' (0x' + device.deviceType.toString(16).padStart(4, '0') + ')',
+ endpoint: device.number,
name,
serial,
uniqueId,
@@ -2919,9 +2896,9 @@ export class Matterbridge extends EventEmitter {
return;
}
const data: { endpoint: string; clusterName: string; clusterId: string; attributeName: string; attributeId: string; attributeValue: string }[] = [];
- this.registeredDevices.forEach((registeredDevice) => {
- if (registeredDevice.plugin === selectedPluginName && registeredDevice.device.number === selectedDeviceEndpoint) {
- const clusterServers = registeredDevice.device.getAllClusterServers();
+ this.devices.forEach(async (device) => {
+ if (device.plugin === selectedPluginName && device.number === selectedDeviceEndpoint) {
+ const clusterServers = device.getAllClusterServers();
clusterServers.forEach((clusterServer) => {
Object.entries(clusterServer.attributes).forEach(([key, value]) => {
if (clusterServer.name === 'EveHistory') return;
@@ -2936,7 +2913,7 @@ export class Matterbridge extends EventEmitter {
// console.log(error);
}
data.push({
- endpoint: registeredDevice.device.number ? registeredDevice.device.number.toString() : '...',
+ endpoint: device.number ? device.number.toString() : '...',
clusterName: clusterServer.name,
clusterId: '0x' + clusterServer.id.toString(16).padStart(2, '0'),
attributeName: key,
@@ -2945,8 +2922,8 @@ export class Matterbridge extends EventEmitter {
});
});
});
- registeredDevice.device.getChildEndpoints().forEach((childEndpoint) => {
- const name = registeredDevice.device.getChildEndpointName(childEndpoint);
+ device.getChildEndpoints().forEach((childEndpoint) => {
+ const name = device.getChildEndpointName(childEndpoint);
const clusterServers = childEndpoint.getAllClusterServers();
clusterServers.forEach((clusterServer) => {
Object.entries(clusterServer.attributes).forEach(([key, value]) => {
@@ -3274,7 +3251,7 @@ export class Matterbridge extends EventEmitter {
if (command === 'update') {
this.log.info('Updating matterbridge...');
try {
- await this.spawnCommand('npm', ['install', '-g', 'matterbridge', '--verbose']);
+ await this.spawnCommand('npm', ['install', '-g', 'matterbridge', '--omit=dev', '--verbose']);
this.log.info('Matterbridge has been updated. Full restart required.');
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
@@ -3308,7 +3285,7 @@ export class Matterbridge extends EventEmitter {
param = param.replace(/\*/g, '\\');
this.log.info(`Installing plugin ${plg}${param}${nf}...`);
try {
- await this.spawnCommand('npm', ['install', '-g', param, '--verbose']);
+ await this.spawnCommand('npm', ['install', '-g', param, '--omit=dev', '--verbose']);
this.log.info(`Plugin ${plg}${param}${nf} installed. Full restart required.`);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
diff --git a/src/matterbridgeDevice.test.ts b/src/matterbridgeDevice.test.ts
index 391e79f7..d729fdf7 100644
--- a/src/matterbridgeDevice.test.ts
+++ b/src/matterbridgeDevice.test.ts
@@ -74,7 +74,7 @@ describe('Matterbridge device serialize/deserialize', () => {
expect(device.getDeviceTypes()).toHaveLength(1);
expect(() => device.verifyRequiredClusters()).not.toThrow();
expect(device.getAllClusterServers()).toHaveLength(7);
- const serialized = device.serialize('matterbridge-test');
+ const serialized = device.serialize();
expect(serialized).toBeDefined();
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const deserialized = MatterbridgeDevice.deserialize(serialized!);
@@ -95,7 +95,7 @@ describe('Matterbridge device serialize/deserialize', () => {
expect(device.getDeviceTypes()).toHaveLength(1);
expect(() => device.verifyRequiredClusters()).not.toThrow();
expect(device.getAllClusterServers()).toHaveLength(5);
- const serialized = device.serialize('matterbridge-test');
+ const serialized = device.serialize();
expect(serialized).toBeDefined();
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const deserialized = MatterbridgeDevice.deserialize(serialized!);
diff --git a/src/matterbridgeDevice.ts b/src/matterbridgeDevice.ts
index 418efbeb..e191654c 100644
--- a/src/matterbridgeDevice.ts
+++ b/src/matterbridgeDevice.ts
@@ -848,12 +848,12 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods {
}
});
+ it('should validate version', () => {
+ matterbridge.matterbridgeVersion = '1.5.4';
+ expect(platform.verifyMatterbridgeVersion('1.5.3')).toBe(true);
+ expect(platform.verifyMatterbridgeVersion('1.5.4')).toBe(true);
+ expect(platform.verifyMatterbridgeVersion('2.0.0')).toBe(false);
+ expect(platform.verifyMatterbridgeVersion('2.0.0-dev.1')).toBe(false);
+ });
+
+ it('should validate version beta', () => {
+ matterbridge.matterbridgeVersion = '1.5.4-dev.1';
+ expect(platform.verifyMatterbridgeVersion('1.5.3')).toBe(true);
+ expect(platform.verifyMatterbridgeVersion('1.5.4')).toBe(true);
+ expect(platform.verifyMatterbridgeVersion('2.0.0')).toBe(false);
+ });
+
test('onConfigure should log a debug message if not overridden', async () => {
await platform.onConfigure();
expect(platform.log.debug).toHaveBeenCalledWith("The plugin doesn't override onConfigure.");
});
+ test('onChangeLoggerLevel should log a debug message if not overridden', async () => {
+ await platform.onChangeLoggerLevel(LogLevel.DEBUG);
+ expect(platform.log.debug).toHaveBeenCalledWith("The plugin doesn't override onChangeLoggerLevel. Logger level set to: debug");
+ });
+
test('onShutdown should log a debug message if not overridden', async () => {
await platform.onShutdown('test reason');
expect(platform.log.debug).toHaveBeenCalledWith("The plugin doesn't override onShutdown.", 'test reason');
diff --git a/src/matterbridgeTypes.ts b/src/matterbridgeTypes.ts
index 277e02fd..8d617b59 100644
--- a/src/matterbridgeTypes.ts
+++ b/src/matterbridgeTypes.ts
@@ -4,7 +4,7 @@
* @file matterbridgeTypes.ts
* @author Luca Liguori
* @date 2024-07-12
- * @version 1.0.1
+ * @version 1.0.2
*
* Copyright 2023, 2024, 2025 Luca Liguori.
*
@@ -74,12 +74,6 @@ export interface BaseRegisteredPlugin {
schemaJson?: PlatformSchema;
}
-// Define an interface for storing the devices
-export interface RegisteredDevice {
- plugin: string;
- device: MatterbridgeDevice;
-}
-
// Define an interface for storing the system information
export interface SystemInformation {
interfaceName: string;
diff --git a/src/pluginManager.ts b/src/pluginManager.ts
index 5a4fd421..3404cf23 100644
--- a/src/pluginManager.ts
+++ b/src/pluginManager.ts
@@ -170,10 +170,6 @@ export class PluginManager {
this.log.error(`Plugin at ${packageJsonPath} has no types in package.json`);
return null;
}
- if (!packageJson.scripts.install || packageJson.scripts.install !== 'node link-matterbridge-script.js') {
- this.log.error(`Plugin at ${packageJsonPath} has not the correct install script in package.json`);
- return null;
- }
// Check for @project-chip packages in dependencies and devDependencies
const checkForProjectChipPackages = (dependencies: Record) => {
@@ -191,6 +187,12 @@ export class PluginManager {
this.log.error(`Please open an issue on the plugin repository to remove them.`);
return null;
}
+ const projectChipPeerDependencies = checkForProjectChipPackages(packageJson.peerDependencies || {});
+ if (projectChipPeerDependencies.length > 0) {
+ this.log.error(`Found @project-chip packages "${projectChipPeerDependencies.join(', ')}" in plugin peerDependencies.`);
+ this.log.error(`Please open an issue on the plugin repository to remove them.`);
+ return null;
+ }
// Check for matterbridge package in dependencies and devDependencies
const checkForMatterbridgePackage = (dependencies: Record) => {
@@ -208,6 +210,12 @@ export class PluginManager {
this.log.error(`Please open an issue on the plugin repository to remove them.`);
return null;
}
+ const matterbridgePeerDependencies = checkForMatterbridgePackage(packageJson.peerDependencies || {});
+ if (matterbridgePeerDependencies.length > 0) {
+ this.log.error(`Found matterbridge package in the plugin peerDependencies.`);
+ this.log.error(`Please open an issue on the plugin repository to remove them.`);
+ return null;
+ }
this.log.debug(`Resolved plugin path ${plg}${pluginPath}${db}: ${packageJsonPath}`);
return packageJsonPath;
@@ -257,6 +265,12 @@ export class PluginManager {
this.log.error(`Please open an issue on the plugin repository to remove them.`);
this.log.error(`In the next release this plugin will not be loaded cause it doesn't meet the requirements.`);
}
+ const projectChipPeerDependencies = checkForProjectChipPackages(packageJson.peerDependencies || {});
+ if (projectChipPeerDependencies.length > 0) {
+ this.log.error(`Found @project-chip packages "${projectChipPeerDependencies.join(', ')}" in plugin ${plg}${plugin.name}${er} peerDependencies.`);
+ this.log.error(`Please open an issue on the plugin repository to remove them.`);
+ this.log.error(`In the next release this plugin will not be loaded cause it doesn't meet the requirements.`);
+ }
// Check for matterbridge package in dependencies and devDependencies
const checkForMatterbridgePackage = (dependencies: Record) => {
@@ -274,6 +288,12 @@ export class PluginManager {
this.log.error(`Please open an issue on the plugin repository to remove them.`);
this.log.error(`In the next release this plugin will not be loaded cause it doesn't meet the requirements.`);
}
+ const matterbridgePeerDependencies = checkForMatterbridgePackage(packageJson.peerDependencies || {});
+ if (matterbridgePeerDependencies.length > 0) {
+ this.log.error(`Found matterbridge package in the plugin ${plg}${plugin.name}${er} peerDependencies.`);
+ this.log.error(`Please open an issue on the plugin repository to remove them.`);
+ this.log.error(`In the next release this plugin will not be loaded cause it doesn't meet the requirements.`);
+ }
// await this.saveToStorage(); // No need to save the plugin to storage
return packageJson;