Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10e7ff078a | ||
|
|
e677fff160 | ||
|
|
63db26611e | ||
|
|
5ec6577b5a | ||
|
|
0359742e70 | ||
|
|
b70f4074e5 | ||
|
|
a4c300407b | ||
|
|
758f64ced4 | ||
|
|
7ab803d4ca | ||
|
|
092697850d | ||
|
|
422e92dd89 | ||
|
|
a15c0fc91d | ||
|
|
358fa3ca9c | ||
|
|
10722fa217 | ||
|
|
7267fafb97 | ||
|
|
b5e95936dc | ||
|
|
047b38a41b | ||
|
|
a93fbb2ad3 | ||
|
|
0b927a3ef6 | ||
|
|
d35cf27de9 | ||
|
|
19348b4b60 | ||
|
|
ce1eed391d | ||
|
|
fe6fe92656 | ||
|
|
3aea938cfb | ||
|
|
c39428fa42 | ||
|
|
7caa5bfc8a | ||
|
|
5f69961a9f | ||
|
|
f44d998016 | ||
|
|
3ea65a4af8 | ||
|
|
2ad49c3167 | ||
|
|
ef2093a25e | ||
|
|
2737eabd8a |
@@ -1,3 +1,4 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
docs/
|
docs/
|
||||||
out/
|
out/
|
||||||
|
build.json
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ If you are running Linux with a graphical user interface (Wayland or X11), you s
|
|||||||
| Raspberry Pi 5 (arm64) | Raspberry Pi OS (64-bit), Wayland, X11 | [ELECROW Portable Monitor 10.1" (1280x800)](https://www.amazon.co.uk/dp/B0BHHQLKPY) | 🟨 |
|
| Raspberry Pi 5 (arm64) | Raspberry Pi OS (64-bit), Wayland, X11 | [ELECROW Portable Monitor 10.1" (1280x800)](https://www.amazon.co.uk/dp/B0BHHQLKPY) | 🟨 |
|
||||||
| Raspberry Pi 5 (arm64) | Raspberry Pi OS (64-bit), Wayland, X11 | Generic Non-Touch | 🟨 |
|
| Raspberry Pi 5 (arm64) | Raspberry Pi OS (64-bit), Wayland, X11 | Generic Non-Touch | 🟨 |
|
||||||
| Generic PC (x64) | Debian KDE (64-bit), Wayland, X11 | Generic Non-Touch | 🟧 |
|
| Generic PC (x64) | Debian KDE (64-bit), Wayland, X11 | Generic Non-Touch | 🟧 |
|
||||||
|
| Generic PC (x64) | Ubuntu XFCE (64-bit), X11 | Generic Non-Touch | 🟧 |
|
||||||
| Generic PC (x64) | Ubuntu GNOME (64-bit), X11 | Generic Non-Touch | 🟧 |
|
| Generic PC (x64) | Ubuntu GNOME (64-bit), X11 | Generic Non-Touch | 🟧 |
|
||||||
| Generic PC (x64) | Ubuntu GNOME (64-bit), Wayland | Generic Non-Touch | 🟥 |
|
| Generic PC (x64) | Ubuntu GNOME (64-bit), Wayland | Generic Non-Touch | 🟥 |
|
||||||
|
|
||||||
|
|||||||
@@ -17,13 +17,14 @@ Moreover, the device running the **kiosk application** also offers several **Hom
|
|||||||
- [x] Configurable browser zoom and theme support.
|
- [x] Configurable browser zoom and theme support.
|
||||||
- [x] Extended touch screen wake-up functionality.
|
- [x] Extended touch screen wake-up functionality.
|
||||||
- [x] Remote controllable via MQTT.
|
- [x] Remote controllable via MQTT.
|
||||||
- [x] Manage kiosk window status.
|
|
||||||
- [x] Toggle the on-screen keyboard.
|
- [x] Toggle the on-screen keyboard.
|
||||||
- [x] Touch display power and brightness.
|
- [x] Touch display power and brightness.
|
||||||
|
- [x] Manage kiosk window status and zoom.
|
||||||
|
- [x] Show network interfaces and addresses.
|
||||||
|
- [x] List all available system package upgrades.
|
||||||
- [x] Multi-webpage switching and url navigation.
|
- [x] Multi-webpage switching and url navigation.
|
||||||
- [x] Monitor temperature, processor and memory usage.
|
- [x] Monitor temperature, processor and memory usage.
|
||||||
- [x] Execute system reboot and shutdown commands.
|
- [x] Execute system reboot and shutdown commands.
|
||||||
- [x] Show available system package upgrades.
|
|
||||||
|
|
||||||
The kiosk application can be executed with command line arguments to load a **Home Assistant dashboard in fullscreen** mode.
|
The kiosk application can be executed with command line arguments to load a **Home Assistant dashboard in fullscreen** mode.
|
||||||
Additionally, a **MQTT endpoint** can be defined, allowing the application to provide controls and sensors for the Linux device and the connected Touch Display.
|
Additionally, a **MQTT endpoint** can be defined, allowing the application to provide controls and sensors for the Linux device and the connected Touch Display.
|
||||||
@@ -43,7 +44,7 @@ For a comprehensive guide on setting up MQTT with Home Assistant, please refer t
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
On the first run of the application, you may encounter a **setup procedure** and the Home Assistant **login screen**.
|
On the first run of the application, you may encounter a **setup procedure** and the Home Assistant **login screen**.
|
||||||
It's recommended to create a **dedicated user** (local access only) for your kiosk device.
|
It's recommended to create a dedicated Home Assistant user (local access only) for your kiosk device.
|
||||||
|
|
||||||
You might also need a physical keyboard or remote VNC access to input these credentials once.
|
You might also need a physical keyboard or remote VNC access to input these credentials once.
|
||||||
If your hardware is [supported](https://github.com/leukipp/touchkio/blob/main/HARDWARE.md) you may be able to activate the on-screen keyboard using the side [widget](https://github.com/leukipp/touchkio/issues/16).
|
If your hardware is [supported](https://github.com/leukipp/touchkio/blob/main/HARDWARE.md) you may be able to activate the on-screen keyboard using the side [widget](https://github.com/leukipp/touchkio/issues/16).
|
||||||
@@ -56,7 +57,6 @@ bash <(wget -qO- https://raw.githubusercontent.com/leukipp/touchkio/main/install
|
|||||||
```
|
```
|
||||||
Make sure that you run this with your **standard user** and not with root (sudo).
|
Make sure that you run this with your **standard user** and not with root (sudo).
|
||||||
If you are paranoid, or smart, or both, have a look into the [install.sh](https://github.com/leukipp/touchkio/blob/main/install.sh) script before executing external code on your machine.
|
If you are paranoid, or smart, or both, have a look into the [install.sh](https://github.com/leukipp/touchkio/blob/main/install.sh) script before executing external code on your machine.
|
||||||
This command can also be re-run to **update** an existing installation to the latest version.
|
|
||||||
|
|
||||||
The systemd **user service** is enabled by default and the kiosk application should start automatically the next time you boot.
|
The systemd **user service** is enabled by default and the kiosk application should start automatically the next time you boot.
|
||||||
If you need manual control use:
|
If you need manual control use:
|
||||||
@@ -89,6 +89,15 @@ yarn build
|
|||||||
|
|
||||||
</div></details>
|
</div></details>
|
||||||
|
|
||||||
|
#### Update
|
||||||
|
If you have already installed TouchKio and want to upgrade to the latest version, simply install the newer version over the existing one.
|
||||||
|
|
||||||
|
The [install.sh](https://github.com/leukipp/touchkio/blob/main/install.sh) script can also be run to update an existing installation to the **latest version**.
|
||||||
|
The setup procedure can be skipped to use the existing default arguments from the configuration file:
|
||||||
|
```bash
|
||||||
|
bash <(wget -qO- https://raw.githubusercontent.com/leukipp/touchkio/main/install.sh) update
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
Running `touchkio --setup` will prompt you to enter arguments that will be used when the application starts without any specified arguments.
|
Running `touchkio --setup` will prompt you to enter arguments that will be used when the application starts without any specified arguments.
|
||||||
These default arguments are stored in `~/.config/touchkio/Arguments.json`, where they can also be modified.
|
These default arguments are stored in `~/.config/touchkio/Arguments.json`, where they can also be modified.
|
||||||
@@ -143,7 +152,7 @@ touchkio --web-url=http://192.168.1.42:8123 --mqtt-url=mqtt://192.168.1.42:1883
|
|||||||
## User Interface
|
## User Interface
|
||||||
TouchKio provides a simple webview window designed specifically for Touch Displays. Electron apps are known to be resource intensive due to their architecture and the inclusion of a full web browser environment. If you just run the kiosk application without other heavy loads, everything should run smoothly.
|
TouchKio provides a simple webview window designed specifically for Touch Displays. Electron apps are known to be resource intensive due to their architecture and the inclusion of a full web browser environment. If you just run the kiosk application without other heavy loads, everything should run smoothly.
|
||||||
|
|
||||||
### Controls
|
### Touch Controls
|
||||||
Additional controls can be found along the right edge of the kiosk application. For more details, you may want to have a closer look here:
|
Additional controls can be found along the right edge of the kiosk application. For more details, you may want to have a closer look here:
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| ------------ | -------------------------------------------------------- |
|
| ------------ | -------------------------------------------------------- |
|
||||||
@@ -154,14 +163,14 @@ Additional controls can be found along the right edge of the kiosk application.
|
|||||||
|
|
||||||
### Keyboard Shortcuts
|
### Keyboard Shortcuts
|
||||||
The application also supports basic shortcuts to enhance navigation and usability for users who prefer or require non-touch input methods:
|
The application also supports basic shortcuts to enhance navigation and usability for users who prefer or require non-touch input methods:
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| --------------------------- | --------------------------- |
|
| --------------------------- | ---------------------------- |
|
||||||
| `Control+Left` | Navigate to previous page |
|
| `Control+Left` | Navigate to previous page |
|
||||||
| `Control+Right` | Navigate to next page |
|
| `Control+Right` | Navigate to next page |
|
||||||
| `Control+Num_Subtract` | Decrease the page zoom |
|
| `Control+Num_Subtract` | Decrease the page zoom |
|
||||||
| `Control+Num_Add` | Increase the page zoom |
|
| `Control+Num_Add` | Increase the page zoom |
|
||||||
| `Alt+Left`/`Mouse+Back` | Navigate back in history |
|
| `Alt+Left`/`Mouse+Back` | Navigate backward in history |
|
||||||
| `Alt+Right`/`Mouse+Forward` | Navigate forward in history |
|
| `Alt+Right`/`Mouse+Forward` | Navigate forward in history |
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
To create your own local build, you first need to install [Node.js](https://pimylifeup.com/raspberry-pi-nodejs) and [Yarn](https://classic.yarnpkg.com/lang/en/docs/install).
|
To create your own local build, you first need to install [Node.js](https://pimylifeup.com/raspberry-pi-nodejs) and [Yarn](https://classic.yarnpkg.com/lang/en/docs/install).
|
||||||
@@ -242,9 +251,10 @@ Implementing stronger **security measures** would complicate the setup process a
|
|||||||
When using the kiosk application without initializing the default arguments, you will need to provide them with every command.
|
When using the kiosk application without initializing the default arguments, you will need to provide them with every command.
|
||||||
This means that the password may be stored as plain text in various files, such as `touchkio.service`, `~/.bash_history`, etc.
|
This means that the password may be stored as plain text in various files, such as `touchkio.service`, `~/.bash_history`, etc.
|
||||||
|
|
||||||
To resolve the issue where the first **touch** on a **turned-off screen** triggers a **click event** (which could inadvertently activate Home Assistant actions), a workaround needed to be implemented.
|
To address the problem where the first **touch** on a **turned-off screen** may trigger a **click event** (which could inadvertently activate Home Assistant actions), a workaround needed to be implemented.
|
||||||
When the screen **turns off** the **focus** is removed from the kiosk window.
|
When the screen **turns on/off**, the timestamps of these events are recorded.
|
||||||
This way, the first click only turns the screen on and focuses the window, allowing subsequent clicks to work as expected.
|
If a touch event is detected and the **timestamp** of the **last screen-off** is more recent than the **last screen-on** timestamp, the touch event is discarded and the screen is turned on instead.
|
||||||
|
From that point onward, subsequent touch interactions will function normally as expected.
|
||||||
|
|
||||||
Additionally, to address the problem that scrolling only works with the **web browser scrollbar** on the right, the application is configured to **simulate a touch device** using `Emulation.setEmitTouchEventsForMouse`.
|
Additionally, to address the problem that scrolling only works with the **web browser scrollbar** on the right, the application is configured to **simulate a touch device** using `Emulation.setEmitTouchEventsForMouse`.
|
||||||
This adjustment provides a user experience similar to that of a proper mobile device.
|
This adjustment provides a user experience similar to that of a proper mobile device.
|
||||||
@@ -252,7 +262,7 @@ This adjustment provides a user experience similar to that of a proper mobile de
|
|||||||
</div></details>
|
</div></details>
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
Please have a look into the [hardware](https://github.com/leukipp/touchkio/blob/main/HARDWARE.md) documentation if you ran into any issues.
|
Please review the [hardware](https://github.com/leukipp/touchkio/blob/main/HARDWARE.md) documentation first if you encounter any problems.
|
||||||
|
|
||||||
**Minimal features** are designed to run on any system without issues:
|
**Minimal features** are designed to run on any system without issues:
|
||||||
- A webview kiosk window launched in fullscreen mode and loading the specified `--web-url` website should not cause any problems.
|
- A webview kiosk window launched in fullscreen mode and loading the specified `--web-url` website should not cause any problems.
|
||||||
@@ -260,7 +270,7 @@ Please have a look into the [hardware](https://github.com/leukipp/touchkio/blob/
|
|||||||
**Extended features** become available when the `--mqtt-*` arguments are provided and the hardware is supported:
|
**Extended features** become available when the `--mqtt-*` arguments are provided and the hardware is supported:
|
||||||
- If your hardware is not fully compatible there should be no crashes, but you may miss some sensors.
|
- If your hardware is not fully compatible there should be no crashes, but you may miss some sensors.
|
||||||
- On some Debian based systems (e.g. Ubuntu GNOME), the display status control may only be available when using X11.
|
- On some Debian based systems (e.g. Ubuntu GNOME), the display status control may only be available when using X11.
|
||||||
- The following commands are currently implemented to modify the display status.
|
- The following commands are currently implemented to modify the display status. Make sure that one of these works for your display when you run it directly on the terminal, otherwise the MQTT switch will not work either.
|
||||||
- `wlopm --[on]/[off] *` (Raspberry Pi OS, Wayland)
|
- `wlopm --[on]/[off] *` (Raspberry Pi OS, Wayland)
|
||||||
- `kscreen-doctor --dpms [on]/[off]` (Debian KDE, Wayland)
|
- `kscreen-doctor --dpms [on]/[off]` (Debian KDE, Wayland)
|
||||||
- `xset dpms force [on]/[off]` (Generic, X11)
|
- `xset dpms force [on]/[off]` (Generic, X11)
|
||||||
@@ -268,17 +278,27 @@ Please have a look into the [hardware](https://github.com/leukipp/touchkio/blob/
|
|||||||
**Known Issues** that are by-design or for which there isn't a solution so far:
|
**Known Issues** that are by-design or for which there isn't a solution so far:
|
||||||
- You can use Raspberry Pi's build-in [screen blanking](https://www.raspberrypi.com/documentation/computers/configuration.html#screen-blanking-3) functionality, however, if the screen is turned on through Home Assistant after being automatically turned off, it will remain on indefinitely.
|
- You can use Raspberry Pi's build-in [screen blanking](https://www.raspberrypi.com/documentation/computers/configuration.html#screen-blanking-3) functionality, however, if the screen is turned on through Home Assistant after being automatically turned off, it will remain on indefinitely.
|
||||||
- It's recommended to either use the built-in screen blanking feature or implement a Home Assistant automation (e.g. presence detection) to manage the screen status.
|
- It's recommended to either use the built-in screen blanking feature or implement a Home Assistant automation (e.g. presence detection) to manage the screen status.
|
||||||
- When using a Raspberry Pi, the on-screen keyboard doesn't automatically pop-out when entering a text field inside the webview.
|
- When using a Raspberry Pi, the on-screen keyboard doesn't [automatically pop-out](https://github.com/leukipp/touchkio/issues/4) when entering a text field inside the webview.
|
||||||
- As a current [workaround](https://github.com/leukipp/touchkio/issues/4) you can use the side [widget](https://github.com/leukipp/touchkio/issues/16) to toggle the keyboard visibility.
|
- As a current workaround you can use the side [widget](https://github.com/leukipp/touchkio/issues/16) to toggle the keyboard visibility.
|
||||||
- Certain commands from the MQTT integration may require elevated privileges to work correctly.
|
- Certain commands from the MQTT integration may require elevated privileges to work correctly.
|
||||||
- Ensure that your local user has the [necessary permissions](https://github.com/leukipp/touchkio/issues/39) to run `sudo` without being prompted for a password.
|
- Ensure that your local user has the [necessary permissions](https://github.com/leukipp/touchkio/issues/39) to run `sudo` without being prompted for a password.
|
||||||
- On the terminal you may see some *ERROR:gbm_wrapper.cc* messages.
|
- On the terminal you may see some *ERROR:gbm_wrapper.cc* messages.
|
||||||
- This appears to be a [known issue](https://github.com/electron/electron/issues/42322) that currently lacks a fix, but the webview still works.
|
- This appears to be a [known issue](https://github.com/electron/electron/issues/42322) that currently lacks a fix, but the webview still works.
|
||||||
|
|
||||||
|
For debugging, stop the service and launch `touchkio` directly on the terminal to monitor the log output in real-time.
|
||||||
|
This output is also written into `~/.config/touchkio/logs/main.log` for review.
|
||||||
|
|
||||||
|
If you encounter any problems, please [create an issue](https://github.com/leukipp/touchkio/issues) and include the output of `touchkio --version`, additional information's about your system (such as operating system, hardware specs, etc.) and any relevant log files.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
Thanks to Sebastian ([@pdsccode](https://github.com/pdsccode)) for his contributions on issues and [community](https://community.home-assistant.io/t/kiosk-mode-for-raspberry-pi-with-touch-display/821196) discussions.
|
|
||||||
|
|
||||||
[Inspired by](https://www.jeffgeerling.com/blog/2024/home-assistant-and-carplay-pi-touch-display-2) the one and only Raspberry Pi Master, Jeff Geerling ([@geerlingguy](https://github.com/geerlingguy)).
|
[Inspired by](https://www.jeffgeerling.com/blog/2024/home-assistant-and-carplay-pi-touch-display-2) the one and only Raspberry Pi Master, Jeff Geerling ([@geerlingguy](https://github.com/geerlingguy)).
|
||||||
|
|
||||||
|
Thanks to Sebastian ([@pdsccode](https://github.com/pdsccode)) for his contributions on issues and [community](https://community.home-assistant.io/t/kiosk-mode-for-raspberry-pi-with-touch-display/821196) discussions.
|
||||||
|
|
||||||
|
If you are looking for hardware or a well-designed mounting solution for the Raspberry Pi Display, check out the [blog post](https://www.thestockpot.net/videos/home-assistant-wall-display) from Dillan Stock ([@TheStockPot-AU](https://www.youtube.com/channel/UCmlzNHg8QiWVutUyFOV2UdQ)).
|
||||||
|
|
||||||
|
[](https://www.youtube.com/watch?v=uTxURzmrVtA)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
[MIT](https://github.com/leukipp/touchkio/blob/main/LICENSE)
|
[MIT](https://github.com/leukipp/touchkio/blob/main/LICENSE)
|
||||||
|
|||||||
+35
-2
@@ -1,4 +1,22 @@
|
|||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
const jszip = require("jszip");
|
||||||
|
const crypto = require("crypto");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const date = new Date().toISOString();
|
||||||
|
|
||||||
|
const generateBuildFile = (platform, arch, maker) => {
|
||||||
|
const package = fs.readFileSync(path.join(__dirname, "package.json"), "utf8");
|
||||||
|
const hash = crypto.createHash("sha256").update(package);
|
||||||
|
const data = {
|
||||||
|
id: hash.digest("hex").slice(-6),
|
||||||
|
platform: platform,
|
||||||
|
arch: arch,
|
||||||
|
maker: maker,
|
||||||
|
date: date,
|
||||||
|
};
|
||||||
|
return JSON.stringify(data, null, 2);
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
packagerConfig: {
|
packagerConfig: {
|
||||||
@@ -33,10 +51,25 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
hooks: {
|
hooks: {
|
||||||
|
postPackage: async (config, results) => {
|
||||||
|
for (const outputPath of results.outputPaths) {
|
||||||
|
const [name, platform, arch] = path.basename(outputPath).split("-");
|
||||||
|
const buildFile = path.join(outputPath, "resources", "app", "build.json");
|
||||||
|
fs.writeFileSync(buildFile, generateBuildFile(platform, arch, "deb"), { encoding: "utf8" });
|
||||||
|
}
|
||||||
|
},
|
||||||
postMake: async (config, results) => {
|
postMake: async (config, results) => {
|
||||||
for (const result of results) {
|
for (const result of results) {
|
||||||
const artifacts = [];
|
const artifacts = [];
|
||||||
result.artifacts.forEach((artifact) => {
|
for (const artifact of result.artifacts) {
|
||||||
|
if (artifact.includes(".zip")) {
|
||||||
|
const [name, platform, arch] = path.basename(artifact).split("-");
|
||||||
|
const buildFile = path.join(`${name}-${platform}-${arch}`, "resources", "app", "build.json");
|
||||||
|
const options = { type: "nodebuffer", compression: "DEFLATE", compressionOptions: { level: 9 } };
|
||||||
|
const zip = await jszip.loadAsync(fs.readFileSync(artifact));
|
||||||
|
zip.file(buildFile, generateBuildFile(platform, arch, "zip"));
|
||||||
|
fs.writeFileSync(artifact, await zip.generateAsync(options));
|
||||||
|
}
|
||||||
if (artifact.includes("amd64")) {
|
if (artifact.includes("amd64")) {
|
||||||
const renamed = artifact.replace("amd64", "x64");
|
const renamed = artifact.replace("amd64", "x64");
|
||||||
fs.renameSync(artifact, renamed);
|
fs.renameSync(artifact, renamed);
|
||||||
@@ -44,7 +77,7 @@ module.exports = {
|
|||||||
} else {
|
} else {
|
||||||
artifacts.push(artifact);
|
artifacts.push(artifact);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
result.artifacts = artifacts;
|
result.artifacts = artifacts;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 78 KiB |
@@ -5,9 +5,13 @@ const readline = require("readline/promises");
|
|||||||
const integration = require("./js/integration");
|
const integration = require("./js/integration");
|
||||||
const hardware = require("./js/hardware");
|
const hardware = require("./js/hardware");
|
||||||
const webview = require("./js/webview");
|
const webview = require("./js/webview");
|
||||||
|
const log = require("electron-log");
|
||||||
const { app } = require("electron");
|
const { app } = require("electron");
|
||||||
|
const Events = require("events");
|
||||||
|
|
||||||
|
global.APP = global.APP || {};
|
||||||
global.ARGS = global.ARGS || {};
|
global.ARGS = global.ARGS || {};
|
||||||
|
global.EVENTS = global.EVENTS || new Events();
|
||||||
|
|
||||||
if (!process.env.DISPLAY) {
|
if (!process.env.DISPLAY) {
|
||||||
console.error(`\n$DISPLAY variable not set to run the GUI application, are you connected via SSH?\n`);
|
console.error(`\n$DISPLAY variable not set to run the GUI application, are you connected via SSH?\n`);
|
||||||
@@ -23,20 +27,90 @@ if (!process.env.DISPLAY) {
|
|||||||
* initialization tasks.
|
* initialization tasks.
|
||||||
*/
|
*/
|
||||||
app.whenReady().then(async () => {
|
app.whenReady().then(async () => {
|
||||||
const lock = app.requestSingleInstanceLock();
|
if (!(await initApp()) || !(await initArgs()) || !(await initLog())) {
|
||||||
if (!lock) {
|
return;
|
||||||
console.error("TouchKio is already running");
|
}
|
||||||
|
|
||||||
|
// Show used arguments
|
||||||
|
const args = Object.assign({}, ARGS);
|
||||||
|
if ("mqtt_password" in args) {
|
||||||
|
args.mqtt_password = "*".repeat((args.mqtt_password || "").length);
|
||||||
|
}
|
||||||
|
console.log(`Arguments: ${JSON.stringify(args, null, 2)}`);
|
||||||
|
|
||||||
|
// Chained init functions
|
||||||
|
const chained = [webview.init, hardware.init, integration.init];
|
||||||
|
for (const init of chained) {
|
||||||
|
if (!(await init())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the global app object.
|
||||||
|
*
|
||||||
|
* @returns {bool} Returns true if the initialization was successful.
|
||||||
|
*/
|
||||||
|
const initApp = async () => {
|
||||||
|
const packageJsonPath = path.join(app.getAppPath(), "package.json");
|
||||||
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
||||||
|
|
||||||
|
const buildJsonPath = path.join(app.getAppPath(), "build.json");
|
||||||
|
const buildFileExists = fs.existsSync(buildJsonPath);
|
||||||
|
|
||||||
|
// Set required app infos
|
||||||
|
APP.name = app.getName();
|
||||||
|
APP.title = packageJson.title;
|
||||||
|
APP.version = app.getVersion();
|
||||||
|
APP.path = app.getAppPath();
|
||||||
|
APP.config = app.getPath("userData");
|
||||||
|
APP.log = path.join(app.getPath("logs"), "main.log");
|
||||||
|
|
||||||
|
// Set additional update infos
|
||||||
|
APP.homepage = `https://github.com/${packageJson.author}/${packageJson.name}`;
|
||||||
|
APP.releases = {
|
||||||
|
url: `https://api.github.com/repos/${packageJson.author}/${packageJson.name}/releases`,
|
||||||
|
latest: null,
|
||||||
|
};
|
||||||
|
APP.scripts = {
|
||||||
|
install: `https://raw.githubusercontent.com/${packageJson.author}/${packageJson.name}/main/install.sh`,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set additional build infos
|
||||||
|
APP.build = {};
|
||||||
|
if (buildFileExists) {
|
||||||
|
APP.build = JSON.parse(fs.readFileSync(buildJsonPath, "utf8"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request single app instance lock
|
||||||
|
if (!app.requestSingleInstanceLock()) {
|
||||||
|
console.error(`${APP.title} is already running`);
|
||||||
return app.quit();
|
return app.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the global args object.
|
||||||
|
*
|
||||||
|
* @returns {bool} Returns true if the initialization was successful.
|
||||||
|
*/
|
||||||
|
const initArgs = async () => {
|
||||||
let args = parseArgs(process);
|
let args = parseArgs(process);
|
||||||
let argsProvided = !!Object.keys(args).length;
|
let argsProvided = !!Object.keys(args).length;
|
||||||
|
|
||||||
let argsFilePath = path.join(app.getPath("userData"), "Arguments.json");
|
let argsFilePath = path.join(APP.config, "Arguments.json");
|
||||||
let argsFileExists = fs.existsSync(argsFilePath);
|
let argsFileExists = fs.existsSync(argsFilePath);
|
||||||
|
|
||||||
// Show version and release info
|
// Show version and release info
|
||||||
if ("help" in args || "version" in args) {
|
if ("help" in args || "version" in args) {
|
||||||
console.log(`${app.getName()}-v${app.getVersion()}, https://github.com/leukipp/touchkio`);
|
let build = "";
|
||||||
|
if (APP.build.id) {
|
||||||
|
build = ` (${APP.build.id}), built on ${APP.build.date} (${APP.build.platform}-${APP.build.arch}-${APP.build.maker})`;
|
||||||
|
}
|
||||||
|
console.log(`${APP.name}-v${APP.version}${build}\n${APP.homepage}`);
|
||||||
return app.quit();
|
return app.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,24 +125,44 @@ app.whenReady().then(async () => {
|
|||||||
args = readArgs(argsFilePath);
|
args = readArgs(argsFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check arguments object
|
||||||
|
if (!Object.keys(args).length) {
|
||||||
|
console.error(`No arguments provided`);
|
||||||
|
return app.quit();
|
||||||
|
}
|
||||||
|
|
||||||
// Split url arguments
|
// Split url arguments
|
||||||
args.web_url = args.web_url || [];
|
args.web_url = args.web_url || [];
|
||||||
if (!Array.isArray(args.web_url)) {
|
if (!Array.isArray(args.web_url)) {
|
||||||
args.web_url = args.web_url.split(",").map((url) => url.trim());
|
args.web_url = args.web_url.split(",").map((url) => url.trim());
|
||||||
}
|
}
|
||||||
global.ARGS = args;
|
ARGS = args;
|
||||||
|
|
||||||
// Show used arguments
|
return true;
|
||||||
console.log(`Arguments: ${JSON.stringify(global.ARGS, null, 2)}\n`);
|
};
|
||||||
|
|
||||||
// Chained init functions
|
/**
|
||||||
const chained = [webview.init, hardware.init, integration.init];
|
* Initializes the global log object.
|
||||||
for (const init of chained) {
|
*
|
||||||
if (!(await init())) {
|
* @returns {bool} Returns true if the initialization was successful.
|
||||||
break;
|
*/
|
||||||
|
const initLog = async () => {
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(APP.log)) {
|
||||||
|
fs.unlinkSync(APP.log);
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to delete log file:", error.message);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// Overwrite console log settings
|
||||||
|
log.transports.file.resolvePathFn = () => {
|
||||||
|
return APP.log;
|
||||||
|
};
|
||||||
|
Object.assign(console, log.functions);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses command-line arguments from the given process object.
|
* Parses command-line arguments from the given process object.
|
||||||
@@ -155,34 +249,41 @@ const promptArgs = async (proc) => {
|
|||||||
// Prompt questions and wait for the answers
|
// Prompt questions and wait for the answers
|
||||||
let args = {};
|
let args = {};
|
||||||
let ignore = [];
|
let ignore = [];
|
||||||
for (const { key, question, fallback } of prompts) {
|
try {
|
||||||
if (key === "mqtt") {
|
for (const { key, question, fallback } of prompts) {
|
||||||
const prompt = `${question} (${fallback}): `;
|
if (key === "mqtt") {
|
||||||
const answer = await read.question(prompt);
|
const prompt = `${question} (${fallback}): `;
|
||||||
const value = (answer.trim() || fallback.match(/[YN]/)[0]).toLowerCase();
|
const answer = await read.question(prompt);
|
||||||
if (!["y", "yes"].includes(value)) {
|
const value = (answer.trim() || fallback.match(/[YN]/)[0]).toLowerCase();
|
||||||
ignore = ignore.concat(["mqtt_url", "mqtt_user", "mqtt_password", "mqtt_discovery"]);
|
if (!["y", "yes"].includes(value)) {
|
||||||
}
|
ignore = ignore.concat(["mqtt_url", "mqtt_user", "mqtt_password", "mqtt_discovery"]);
|
||||||
} else if (key === "check") {
|
}
|
||||||
const json = JSON.stringify(args, null, 2);
|
} else if (key === "check") {
|
||||||
const prompt = `${question}\n${json}\n(${fallback}): `;
|
const json = JSON.stringify(args, null, 2);
|
||||||
const answer = await read.question(prompt);
|
const prompt = `${question}\n${json}\n(${fallback}): `;
|
||||||
const value = (answer.trim() || fallback.match(/[YN]/)[0]).toLowerCase();
|
const answer = await read.question(prompt);
|
||||||
if (!["y", "yes"].includes(value)) {
|
const value = (answer.trim() || fallback.match(/[YN]/)[0]).toLowerCase();
|
||||||
args = {};
|
if (!["y", "yes"].includes(value)) {
|
||||||
}
|
args = {};
|
||||||
} else if (!ignore.includes(key)) {
|
}
|
||||||
const prompt = `${question} (${fallback}): `;
|
} else if (!ignore.includes(key)) {
|
||||||
const answer = await read.question(prompt);
|
const prompt = `${question} (${fallback}): `;
|
||||||
const value = answer.trim() || fallback;
|
const answer = await read.question(prompt);
|
||||||
if (key === "web_url") {
|
const value = answer.trim() || fallback;
|
||||||
args[key] = value.split(",").map((v) => v.trim());
|
if (key === "web_url") {
|
||||||
} else {
|
args[key] = value.split(",").map((v) => v.trim());
|
||||||
args[key] = value;
|
} else {
|
||||||
|
args[key] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`\n${error.message}`);
|
||||||
|
args = {};
|
||||||
|
app.quit();
|
||||||
|
} finally {
|
||||||
|
read.close();
|
||||||
}
|
}
|
||||||
read.close();
|
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
};
|
};
|
||||||
@@ -194,11 +295,15 @@ const promptArgs = async (proc) => {
|
|||||||
* @param {Object} args - The arguments object.
|
* @param {Object} args - The arguments object.
|
||||||
*/
|
*/
|
||||||
const writeArgs = (path, args) => {
|
const writeArgs = (path, args) => {
|
||||||
const argc = Object.assign({}, args);
|
try {
|
||||||
if ("mqtt_password" in argc) {
|
const argc = Object.assign({}, args);
|
||||||
argc.mqtt_password = encrypt(argc.mqtt_password);
|
if ("mqtt_password" in argc) {
|
||||||
|
argc.mqtt_password = encrypt(argc.mqtt_password);
|
||||||
|
}
|
||||||
|
fs.writeFileSync(path, JSON.stringify(argc, null, 2));
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to write ${path}:`, error.message);
|
||||||
}
|
}
|
||||||
fs.writeFileSync(path, JSON.stringify(argc, null, 2));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -208,11 +313,16 @@ const writeArgs = (path, args) => {
|
|||||||
* @returns {Object} The arguments object.
|
* @returns {Object} The arguments object.
|
||||||
*/
|
*/
|
||||||
const readArgs = (path) => {
|
const readArgs = (path) => {
|
||||||
const args = JSON.parse(fs.readFileSync(path));
|
try {
|
||||||
if ("mqtt_password" in args) {
|
const args = JSON.parse(fs.readFileSync(path, "utf8"));
|
||||||
args.mqtt_password = decrypt(args.mqtt_password);
|
if ("mqtt_password" in args) {
|
||||||
|
args.mqtt_password = decrypt(args.mqtt_password);
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to parse ${path}:`, error.message);
|
||||||
}
|
}
|
||||||
return args;
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -223,7 +333,7 @@ const readArgs = (path) => {
|
|||||||
*/
|
*/
|
||||||
const encrypt = (value) => {
|
const encrypt = (value) => {
|
||||||
const iv = crypto.randomBytes(16);
|
const iv = crypto.randomBytes(16);
|
||||||
const key = crypto.scryptSync(hardware.getMachineId(), app.getName(), 32);
|
const key = crypto.scryptSync(hardware.getMachineId(), APP.name, 32);
|
||||||
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
|
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
|
||||||
let encrypted = cipher.update(value, "utf8", "hex");
|
let encrypted = cipher.update(value, "utf8", "hex");
|
||||||
encrypted += cipher.final("hex");
|
encrypted += cipher.final("hex");
|
||||||
@@ -239,7 +349,7 @@ const encrypt = (value) => {
|
|||||||
const decrypt = (value) => {
|
const decrypt = (value) => {
|
||||||
const p = Buffer.from(value, "base64").toString("utf8").split(":");
|
const p = Buffer.from(value, "base64").toString("utf8").split(":");
|
||||||
const iv = Buffer.from(p.shift(), "hex");
|
const iv = Buffer.from(p.shift(), "hex");
|
||||||
const key = crypto.scryptSync(hardware.getMachineId(), app.getName(), 32);
|
const key = crypto.scryptSync(hardware.getMachineId(), APP.name, 32);
|
||||||
const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
|
const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
|
||||||
const buffer = Buffer.from(p.join(":"), "hex");
|
const buffer = Buffer.from(p.join(":"), "hex");
|
||||||
let decrypted = decipher.update(buffer, "binary", "utf8");
|
let decrypted = decipher.update(buffer, "binary", "utf8");
|
||||||
|
|||||||
+43
-41
@@ -1,5 +1,13 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Read arguments
|
||||||
|
ARG_UPDATE=false
|
||||||
|
for arg in "$@"; do
|
||||||
|
if [ "$arg" = "update" ]; then
|
||||||
|
ARG_UPDATE=true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# Determine system architecture
|
# Determine system architecture
|
||||||
echo -e "Determining system architecture..."
|
echo -e "Determining system architecture..."
|
||||||
|
|
||||||
@@ -12,57 +20,39 @@ case "$(uname -m)" in
|
|||||||
ARCH="x64"
|
ARCH="x64"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Architecture $(uname -m) running $BITS-bit operating system is not supported."
|
{ echo "Architecture $(uname -m) running $BITS-bit operating system is not supported."; exit 1; }
|
||||||
exit 1
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [ "$BITS" -ne 64 ]; then
|
[ "$BITS" -eq 64 ] || { echo "Architecture $ARCH running $BITS-bit operating system is not supported."; exit 1; }
|
||||||
echo "Architecture $ARCH running $BITS-bit operating system is not supported."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Architecture $ARCH running $BITS-bit operating system is supported."
|
echo "Architecture $ARCH running $BITS-bit operating system is supported."
|
||||||
|
|
||||||
# Download the latest .deb package
|
# Download the latest .deb package
|
||||||
echo -e "\nDownloading the latest release..."
|
echo -e "\nDownloading the latest release..."
|
||||||
|
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
DEB_URL=$(wget -qO- https://api.github.com/repos/leukipp/touchkio/releases/latest | \
|
DEB_URL=$(wget -qO- https://api.github.com/repos/leukipp/touchkio/releases/latest | \
|
||||||
grep -o "\"browser_download_url\": \"[^\"]*_${ARCH}\.deb\"" | \
|
grep -o "\"browser_download_url\": \"[^\"]*_${ARCH}\.deb\"" | \
|
||||||
sed 's/"browser_download_url": "//;s/"//g')
|
sed 's/"browser_download_url": "//;s/"//g')
|
||||||
|
|
||||||
TMP_DIR=$(mktemp -d)
|
|
||||||
DEB_PATH="${TMP_DIR}/$(basename "$DEB_URL")"
|
DEB_PATH="${TMP_DIR}/$(basename "$DEB_URL")"
|
||||||
chmod 755 "$TMP_DIR"
|
chmod 755 "$TMP_DIR"
|
||||||
|
|
||||||
if [ -z "$DEB_URL" ]; then
|
[ -z "$DEB_URL" ] && { echo "Download url for .deb file not found."; exit 1; }
|
||||||
echo "Download url for .deb file not found."
|
wget --show-progress -q -O "$DEB_PATH" "$DEB_URL" || { echo "Failed to download the .deb file."; exit 1; }
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! wget --show-progress -q -O "$DEB_PATH" "$DEB_URL"; then
|
|
||||||
echo "Failed to download the .deb file."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install the latest .deb package
|
# Install the latest .deb package
|
||||||
echo -e "\nInstalling the latest release..."
|
echo -e "\nInstalling the latest release..."
|
||||||
|
|
||||||
if ! command -v apt &> /dev/null; then
|
command -v apt &> /dev/null || { echo "Package manager apt was not found."; exit 1; }
|
||||||
echo "Package manager apt was not found."
|
sudo apt install -y "$DEB_PATH" || { echo "Installation of .deb file failed."; exit 1; }
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! sudo apt install "$DEB_PATH"; then
|
|
||||||
echo "Installation of .deb file failed."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create the systemd user service
|
# Create the systemd user service
|
||||||
echo -e "\nCreating systemd user service..."
|
echo -e "\nCreating systemd user service..."
|
||||||
|
|
||||||
SERVICE_FILE="$HOME/.config/systemd/user/touchkio.service"
|
SERVICE_NAME="touchkio.service"
|
||||||
mkdir -p "$(dirname "$SERVICE_FILE")" || { echo "Failed to create directory for $SERVICE_FILE"; exit 1; }
|
SERVICE_FILE="$HOME/.config/systemd/user/$SERVICE_NAME"
|
||||||
|
mkdir -p "$(dirname "$SERVICE_FILE")" || { echo "Failed to create directory for $SERVICE_FILE."; exit 1; }
|
||||||
|
|
||||||
SERVICE_CONTENT="[Unit]
|
SERVICE_CONTENT="[Unit]
|
||||||
Description=TouchKio
|
Description=TouchKio
|
||||||
After=graphical.target
|
After=graphical.target
|
||||||
@@ -76,20 +66,28 @@ RestartSec=5s
|
|||||||
[Install]
|
[Install]
|
||||||
WantedBy=default.target"
|
WantedBy=default.target"
|
||||||
|
|
||||||
|
if $ARG_UPDATE; then
|
||||||
|
if systemctl --user --quiet is-active "${SERVICE_NAME}"; then
|
||||||
|
systemctl --user restart "${SERVICE_NAME}"
|
||||||
|
echo "Existing $SERVICE_NAME restarted."
|
||||||
|
else
|
||||||
|
echo "Existing $SERVICE_NAME not running, start touchkio manually."
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
SERVICE_CREATE=true
|
SERVICE_CREATE=true
|
||||||
if [ -f "$SERVICE_FILE" ]; then
|
if [ -f "$SERVICE_FILE" ]; then
|
||||||
read -p "Service $SERVICE_FILE exists, overwrite? (y/N) " overwrite
|
read -p "Service $SERVICE_FILE exists, overwrite? (y/N) " overwrite
|
||||||
if [[ ! ${overwrite:-n} == [Yy]* ]]; then
|
[[ ${overwrite:-n} == [Yy]* ]] || SERVICE_CREATE=false
|
||||||
SERVICE_CREATE=false
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$SERVICE_CREATE" = true ]; then
|
if $SERVICE_CREATE; then
|
||||||
echo "$SERVICE_CONTENT" > "$SERVICE_FILE" || { echo "Failed to write to $SERVICE_FILE"; exit 1; }
|
echo "$SERVICE_CONTENT" > "$SERVICE_FILE" || { echo "Failed to write to $SERVICE_FILE."; exit 1; }
|
||||||
systemctl --user enable "$(basename "$SERVICE_FILE")" || { echo "Failed to enable service $SERVICE_FILE"; exit 1; }
|
systemctl --user enable "$(basename "$SERVICE_FILE")" || { echo "Failed to enable service $SERVICE_FILE."; exit 1; }
|
||||||
echo "Service $SERVICE_FILE enabled"
|
echo "Service $SERVICE_FILE enabled."
|
||||||
else
|
else
|
||||||
echo "Service $SERVICE_FILE not created"
|
echo "Service $SERVICE_FILE not created."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Export display variables
|
# Export display variables
|
||||||
@@ -97,20 +95,22 @@ echo -e "\nExporting display variables..."
|
|||||||
|
|
||||||
if [ -z "$DISPLAY" ]; then
|
if [ -z "$DISPLAY" ]; then
|
||||||
export DISPLAY=":0"
|
export DISPLAY=":0"
|
||||||
echo "DISPLAY was not set, defaulting to \"$DISPLAY\""
|
echo "DISPLAY was not set, defaulting to \"$DISPLAY\"."
|
||||||
else
|
else
|
||||||
echo "DISPLAY is set to \"$DISPLAY\""
|
echo "DISPLAY is set to \"$DISPLAY\"."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$WAYLAND_DISPLAY" ]; then
|
if [ -z "$WAYLAND_DISPLAY" ]; then
|
||||||
export WAYLAND_DISPLAY="wayland-0"
|
export WAYLAND_DISPLAY="wayland-0"
|
||||||
echo "WAYLAND_DISPLAY was not set, defaulting to \"$WAYLAND_DISPLAY\""
|
echo "WAYLAND_DISPLAY was not set, defaulting to \"$WAYLAND_DISPLAY\"."
|
||||||
else
|
else
|
||||||
echo "WAYLAND_DISPLAY is set to \"$WAYLAND_DISPLAY\""
|
echo "WAYLAND_DISPLAY is set to \"$WAYLAND_DISPLAY\"."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Start the setup mode
|
# Start the setup mode
|
||||||
echo ""
|
echo ""
|
||||||
read -p "Start touchkio setup? (Y/n) " setup
|
read -p "Start touchkio setup? (Y/n) " setup
|
||||||
|
|
||||||
if [[ ${setup:-y} == [Yy]* ]]; then
|
if [[ ${setup:-y} == [Yy]* ]]; then
|
||||||
echo "/usr/bin/touchkio --setup"
|
echo "/usr/bin/touchkio --setup"
|
||||||
/usr/bin/touchkio --setup
|
/usr/bin/touchkio --setup
|
||||||
@@ -118,3 +118,5 @@ else
|
|||||||
echo "/usr/bin/touchkio"
|
echo "/usr/bin/touchkio"
|
||||||
/usr/bin/touchkio
|
/usr/bin/touchkio
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|||||||
+164
-69
@@ -3,13 +3,11 @@ const fs = require("fs");
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const fsp = require("fs/promises");
|
const fsp = require("fs/promises");
|
||||||
const cpr = require("child_process");
|
const cpr = require("child_process");
|
||||||
const Events = require("events");
|
|
||||||
|
|
||||||
global.HARDWARE = global.HARDWARE || {
|
global.HARDWARE = global.HARDWARE || {
|
||||||
initialized: false,
|
initialized: false,
|
||||||
events: new Events(),
|
|
||||||
session: {},
|
|
||||||
support: {},
|
support: {},
|
||||||
|
session: {},
|
||||||
battery: {
|
battery: {
|
||||||
level: {
|
level: {
|
||||||
path: null,
|
path: null,
|
||||||
@@ -39,11 +37,7 @@ global.HARDWARE = global.HARDWARE || {
|
|||||||
*/
|
*/
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
if (!compatibleSystem()) {
|
if (!compatibleSystem()) {
|
||||||
console.warn("Operating system is not supported\n");
|
console.error("Operating system is not supported");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!sessionRights()) {
|
|
||||||
console.warn(`User "${sessionUser()}" is missing password-less sudo rights\n`);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,32 +54,35 @@ const init = async () => {
|
|||||||
HARDWARE.initialized = true;
|
HARDWARE.initialized = true;
|
||||||
|
|
||||||
// Show supported features
|
// Show supported features
|
||||||
|
process.stdout.write("\n");
|
||||||
console.log(`Supported: ${JSON.stringify(HARDWARE.support, null, 2)}`);
|
console.log(`Supported: ${JSON.stringify(HARDWARE.support, null, 2)}`);
|
||||||
|
|
||||||
// Show session infos
|
// Show session infos
|
||||||
console.log("\nUser:", HARDWARE.session.user);
|
process.stdout.write("\n");
|
||||||
|
console.log("User:", HARDWARE.session.user);
|
||||||
console.log("Session:", HARDWARE.session.type);
|
console.log("Session:", HARDWARE.session.type);
|
||||||
console.log("Desktop:", HARDWARE.session.desktop);
|
console.log("Desktop:", HARDWARE.session.desktop);
|
||||||
|
|
||||||
// Show device infos
|
// Show device infos
|
||||||
console.log("\nModel:", getModel());
|
process.stdout.write("\n");
|
||||||
|
console.log("Model:", getModel());
|
||||||
console.log("Vendor:", getVendor());
|
console.log("Vendor:", getVendor());
|
||||||
console.log("Serial Number:", getSerialNumber());
|
console.log("Serial Number:", getSerialNumber());
|
||||||
|
console.log("Network Addresses:", getNetworkAddresses());
|
||||||
console.log("Host Name:", getHostName());
|
console.log("Host Name:", getHostName());
|
||||||
|
|
||||||
// Show system infos
|
// Show system infos
|
||||||
console.log("\nUp Time:", getUpTime());
|
process.stdout.write("\n");
|
||||||
|
console.log("Up Time:", getUpTime());
|
||||||
console.log("Memory Size:", getMemorySize());
|
console.log("Memory Size:", getMemorySize());
|
||||||
console.log("Memory Usage:", getMemoryUsage());
|
console.log("Memory Usage:", getMemoryUsage());
|
||||||
console.log("Processor Usage:", getProcessorUsage());
|
console.log("Processor Usage:", getProcessorUsage());
|
||||||
console.log("Processor Temperature:", getProcessorTemperature());
|
console.log("Processor Temperature:", getProcessorTemperature());
|
||||||
|
|
||||||
// Show hardware infos
|
// Show hardware infos
|
||||||
|
process.stdout.write("\n");
|
||||||
const unsupported = "unsupported";
|
const unsupported = "unsupported";
|
||||||
console.log(
|
console.log(`Battery Level [${HARDWARE.battery.level.path || unsupported}]:`, `${getBatteryLevel() || unsupported}`);
|
||||||
`\nBattery Level [${HARDWARE.battery.level.path || unsupported}]:`,
|
|
||||||
`${getBatteryLevel() || unsupported}`,
|
|
||||||
);
|
|
||||||
console.log(
|
console.log(
|
||||||
`Display Status [${HARDWARE.display.status.path || unsupported}]:`,
|
`Display Status [${HARDWARE.display.status.path || unsupported}]:`,
|
||||||
`${getDisplayStatus() || unsupported} (${HARDWARE.display.status.command || unsupported})`,
|
`${getDisplayStatus() || unsupported} (${HARDWARE.display.status.command || unsupported})`,
|
||||||
@@ -96,10 +93,11 @@ const init = async () => {
|
|||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
`Keyboard Visibility [${HARDWARE.support.keyboardVisibility ? "squeekboard" : unsupported}]:`,
|
`Keyboard Visibility [${HARDWARE.support.keyboardVisibility ? "squeekboard" : unsupported}]:`,
|
||||||
`${getKeyboardVisibility() || unsupported}\n`,
|
`${getKeyboardVisibility() || unsupported}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check for keyboard visibility
|
// Check for keyboard visibility
|
||||||
|
process.stdout.write("\n");
|
||||||
setKeyboardVisibility("OFF", (reply, error) => {
|
setKeyboardVisibility("OFF", (reply, error) => {
|
||||||
if (!reply || error) {
|
if (!reply || error) {
|
||||||
return;
|
return;
|
||||||
@@ -109,12 +107,14 @@ const init = async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HARDWARE.keyboard.visibility = property.Visible === "true";
|
HARDWARE.keyboard.visibility = property.Visible === "true";
|
||||||
HARDWARE.events.emit("updateKeyboard");
|
EVENTS.emit("updateKeyboard");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check for display changes
|
// Check for display changes
|
||||||
interval(update, 1000);
|
setDisplayStatus("ON", () => {
|
||||||
|
interval(update, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -133,7 +133,7 @@ const update = async () => {
|
|||||||
if (status !== HARDWARE.display.status.value) {
|
if (status !== HARDWARE.display.status.value) {
|
||||||
console.log("Update Display Status:", getDisplayStatus());
|
console.log("Update Display Status:", getDisplayStatus());
|
||||||
HARDWARE.display.status.value = status;
|
HARDWARE.display.status.value = status;
|
||||||
HARDWARE.events.emit("updateDisplay");
|
EVENTS.emit("updateDisplay");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ const update = async () => {
|
|||||||
if (brightness !== HARDWARE.display.brightness.value) {
|
if (brightness !== HARDWARE.display.brightness.value) {
|
||||||
console.log("Update Display Brightness:", getDisplayBrightness());
|
console.log("Update Display Brightness:", getDisplayBrightness());
|
||||||
HARDWARE.display.brightness.value = brightness;
|
HARDWARE.display.brightness.value = brightness;
|
||||||
HARDWARE.events.emit("updateDisplay");
|
EVENTS.emit("updateDisplay");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -161,19 +161,6 @@ const compatibleSystem = () => {
|
|||||||
return paths.every((path) => fs.existsSync(path));
|
return paths.every((path) => fs.existsSync(path));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies user rights to run sudo commands without a password.
|
|
||||||
*
|
|
||||||
* @returns {bool} Returns true if password-less sudo rights exists.
|
|
||||||
*/
|
|
||||||
const sessionRights = () => {
|
|
||||||
if (!commandExists("sudo")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const result = execSyncCommand("sudo", ["-n", "true"]);
|
|
||||||
return result !== null && !result.includes("password is required");
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the session user name using `os.userInfo()`.
|
* Gets the session user name using `os.userInfo()`.
|
||||||
*
|
*
|
||||||
@@ -214,7 +201,7 @@ const sessionDesktop = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks supported features based on global properties.
|
* Checks supported features based on hardware and software.
|
||||||
*
|
*
|
||||||
* @returns {Object} Returns support object with boolean values.
|
* @returns {Object} Returns support object with boolean values.
|
||||||
*/
|
*/
|
||||||
@@ -223,11 +210,16 @@ const checkSupport = () => {
|
|||||||
const status = HARDWARE.display.status;
|
const status = HARDWARE.display.status;
|
||||||
const brightness = HARDWARE.display.brightness;
|
const brightness = HARDWARE.display.brightness;
|
||||||
const keyboard = processRuns("squeekboard");
|
const keyboard = processRuns("squeekboard");
|
||||||
|
const service = serviceRuns(APP.name);
|
||||||
|
const sudo = sudoRights();
|
||||||
|
const deb = APP.build.maker === "deb";
|
||||||
return {
|
return {
|
||||||
batteryLevel: battery.path !== null,
|
batteryLevel: !!battery.path,
|
||||||
displayStatus: status.path !== null && status.command !== null,
|
displayStatus: !!status.path && !!status.command,
|
||||||
displayBrightness: brightness.path !== null && brightness.max !== null,
|
displayBrightness: sudo && !!brightness.path && !!brightness.max,
|
||||||
keyboardVisibility: keyboard === true,
|
keyboardVisibility: keyboard,
|
||||||
|
sudoRights: sudo,
|
||||||
|
appUpdate: sudo && service && deb,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -240,7 +232,7 @@ const getModel = () => {
|
|||||||
const paths = ["/sys/firmware/devicetree/base/model", "/sys/class/dmi/id/product_name"];
|
const paths = ["/sys/firmware/devicetree/base/model", "/sys/class/dmi/id/product_name"];
|
||||||
for (const path of paths) {
|
for (const path of paths) {
|
||||||
if (fs.existsSync(path)) {
|
if (fs.existsSync(path)) {
|
||||||
return execSyncCommand("sudo", ["cat", path]) || "Generic";
|
return execSyncCommand("cat", [path]) || "Generic";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "Generic";
|
return "Generic";
|
||||||
@@ -255,7 +247,7 @@ const getVendor = () => {
|
|||||||
const paths = ["/sys/class/dmi/id/board_vendor"];
|
const paths = ["/sys/class/dmi/id/board_vendor"];
|
||||||
for (const path of paths) {
|
for (const path of paths) {
|
||||||
if (fs.existsSync(path)) {
|
if (fs.existsSync(path)) {
|
||||||
return execSyncCommand("sudo", ["cat", path]) || "Generic";
|
return execSyncCommand("cat", [path]) || "Generic";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const model = getModel();
|
const model = getModel();
|
||||||
@@ -266,22 +258,22 @@ const getVendor = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the serial number using `/sys/firmware/devicetree/base/serial-number` or `/sys/class/dmi/id/product_serial`.
|
* Gets the serial number using `/sys/firmware/devicetree/base/serial-number`.
|
||||||
*
|
*
|
||||||
* @returns {string} The serial number of the device or '123456' if not found.
|
* @returns {string} The serial number or machine id parts of the device or '123456' if not found.
|
||||||
*/
|
*/
|
||||||
const getSerialNumber = () => {
|
const getSerialNumber = () => {
|
||||||
const paths = ["/sys/firmware/devicetree/base/serial-number", "/sys/class/dmi/id/product_serial"];
|
const paths = ["/sys/firmware/devicetree/base/serial-number"];
|
||||||
for (const path of paths) {
|
for (const path of paths) {
|
||||||
if (fs.existsSync(path)) {
|
if (fs.existsSync(path)) {
|
||||||
return execSyncCommand("sudo", ["cat", path]) || "123456";
|
return execSyncCommand("cat", [path]) || "123456";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "123456";
|
return getMachineId().slice(-6);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the host machine id using `/etc/machine-id`.
|
* Gets the machine id using `/etc/machine-id`.
|
||||||
*
|
*
|
||||||
* @returns {string} The machine id of the system or '123456' if not found.
|
* @returns {string} The machine id of the system or '123456' if not found.
|
||||||
*/
|
*/
|
||||||
@@ -289,12 +281,38 @@ const getMachineId = () => {
|
|||||||
const paths = ["/etc/machine-id"];
|
const paths = ["/etc/machine-id"];
|
||||||
for (const path of paths) {
|
for (const path of paths) {
|
||||||
if (fs.existsSync(path)) {
|
if (fs.existsSync(path)) {
|
||||||
return execSyncCommand("sudo", ["cat", path]) || "123456";
|
return execSyncCommand("cat", [path]) || "123456";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "123456";
|
return "123456";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the network interfaces addresses using `os.networkInterfaces()`.
|
||||||
|
*
|
||||||
|
* @returns {Object} The network addresses of all interfaces.
|
||||||
|
*/
|
||||||
|
const getNetworkAddresses = () => {
|
||||||
|
const addresses = {};
|
||||||
|
for (const [key, interfaces] of Object.entries(os.networkInterfaces())) {
|
||||||
|
for (const interface of interfaces) {
|
||||||
|
if (interface.internal || !interface.family || !interface.address) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const name = key.charAt(0).toUpperCase() + key.slice(1);
|
||||||
|
if (!addresses[name]) {
|
||||||
|
addresses[name] = {};
|
||||||
|
}
|
||||||
|
const family = interface.family;
|
||||||
|
if (!addresses[name][family]) {
|
||||||
|
addresses[name][family] = [];
|
||||||
|
}
|
||||||
|
addresses[name][family].push(interface.address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return addresses;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the host name of the current system using `os.hostname()`.
|
* Gets the host name of the current system using `os.hostname()`.
|
||||||
*
|
*
|
||||||
@@ -354,7 +372,7 @@ const getProcessorTemperature = () => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const type = fs.readFileSync(typeFile, "utf8").trim();
|
const type = fs.readFileSync(typeFile, "utf8").trim();
|
||||||
if (["cpu-thermal", "x86_pkg_temp", "k10temp", "acpitz"].includes(type)) {
|
if (["cpu-thermal", "x86_pkg_temp", "k10temp", "acpitz", "cpu"].includes(type)) {
|
||||||
return parseFloat(fs.readFileSync(tempFile, "utf8").trim()) / 1000;
|
return parseFloat(fs.readFileSync(tempFile, "utf8").trim()) / 1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,22 +469,22 @@ const getDisplayStatus = () => {
|
|||||||
case "wlopm":
|
case "wlopm":
|
||||||
const wlopm = execSyncCommand("wlopm", []);
|
const wlopm = execSyncCommand("wlopm", []);
|
||||||
if (wlopm !== null) {
|
if (wlopm !== null) {
|
||||||
const out = wlopm.split("\n")[0].split(" ");
|
const output = wlopm.split("\n")[0].split(" ");
|
||||||
return out.pop().toUpperCase();
|
return output.pop().toUpperCase();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "kscreen-doctor":
|
case "kscreen-doctor":
|
||||||
const kdoc = execSyncCommand("kscreen-doctor", ["--dpms", "show"]);
|
const kdoc = execSyncCommand("kscreen-doctor", ["--dpms", "show"]);
|
||||||
if (kdoc !== null) {
|
if (kdoc !== null) {
|
||||||
const out = kdoc.split("\n")[0].split(" ");
|
const output = kdoc.split("\n")[0].split(" ");
|
||||||
return out.pop().toUpperCase();
|
return output.pop().toUpperCase();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "xset":
|
case "xset":
|
||||||
const xset = execSyncCommand("xset", ["-q"]);
|
const xset = execSyncCommand("xset", ["-q"]);
|
||||||
if (xset !== null) {
|
if (xset !== null) {
|
||||||
const on = /Monitor is On/.test(xset);
|
const output = /Monitor is On/.test(xset);
|
||||||
return on ? "ON" : "OFF";
|
return output ? "ON" : "OFF";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -641,6 +659,10 @@ const checkPackageUpgrades = () => {
|
|||||||
* @param {Function} callback - A callback function that receives the output or error.
|
* @param {Function} callback - A callback function that receives the output or error.
|
||||||
*/
|
*/
|
||||||
const shutdownSystem = (callback = null) => {
|
const shutdownSystem = (callback = null) => {
|
||||||
|
if (!HARDWARE.support.sudoRights) {
|
||||||
|
if (typeof callback === "function") callback(null, "Not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
execAsyncCommand("sudo", ["shutdown", "-h", "now"], callback);
|
execAsyncCommand("sudo", ["shutdown", "-h", "now"], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -653,9 +675,39 @@ const shutdownSystem = (callback = null) => {
|
|||||||
* @param {Function} callback - A callback function that receives the output or error.
|
* @param {Function} callback - A callback function that receives the output or error.
|
||||||
*/
|
*/
|
||||||
const rebootSystem = (callback = null) => {
|
const rebootSystem = (callback = null) => {
|
||||||
|
if (!HARDWARE.support.sudoRights) {
|
||||||
|
if (typeof callback === "function") callback(null, "Not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
execAsyncCommand("sudo", ["reboot"], callback);
|
execAsyncCommand("sudo", ["reboot"], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if sudo commands can run without a password.
|
||||||
|
*
|
||||||
|
* @returns {bool} Returns true if password-less sudo rights exists.
|
||||||
|
*/
|
||||||
|
const sudoRights = () => {
|
||||||
|
try {
|
||||||
|
const output = cpr.execSync(`sudo -n true`, { encoding: "utf8" });
|
||||||
|
return output !== null && !output.includes("password is required");
|
||||||
|
} catch {}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a service is running using `systemctl`.
|
||||||
|
*
|
||||||
|
* @param {string} name - The service name to check.
|
||||||
|
* @returns {bool} Returns true if the service runs.
|
||||||
|
*/
|
||||||
|
const serviceRuns = (name) => {
|
||||||
|
try {
|
||||||
|
return !!cpr.execSync(`systemctl --user is-active ${name}`, { encoding: "utf8" });
|
||||||
|
} catch {}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a process is running using `pidof`.
|
* Checks if a process is running using `pidof`.
|
||||||
*
|
*
|
||||||
@@ -732,14 +784,61 @@ const execAsyncCommand = (cmd, args = [], callback = null) => {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Execute Async:", error.message);
|
console.error("Execute Async:", error.message);
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") callback(null, error.message);
|
||||||
callback(null, error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return proc;
|
return proc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a script command asynchronously.
|
||||||
|
*
|
||||||
|
* @param {string} cmd - The script to execute.
|
||||||
|
* @param {Array<string>} args - The arguments for the command.
|
||||||
|
* @param {Function} callback - A callback function that receives the progress or error.
|
||||||
|
* @returns {Object} The spawned process object.
|
||||||
|
*/
|
||||||
|
const execScriptCommand = (cmd, args = [], callback = null) => {
|
||||||
|
let progress = 1;
|
||||||
|
let proc = cpr.spawn(cmd, args);
|
||||||
|
if (typeof callback === "function") callback(progress, null);
|
||||||
|
proc.stdout.on("data", (data) => {
|
||||||
|
if (data) {
|
||||||
|
const output = data.toString().trim();
|
||||||
|
const lines = output.replace(/\n+/g, "\n").replace(/^\n+|\n+$|\0/g, "");
|
||||||
|
for (const line of lines.split("\n").filter(Boolean)) {
|
||||||
|
console.log(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
proc.stderr.on("data", (data) => {
|
||||||
|
if (data) {
|
||||||
|
const output = data.toString().trim();
|
||||||
|
const lines = output.replace(/\n+/g, "\n").replace(/^\n+|\n+$|\0/g, "");
|
||||||
|
for (const line of lines.split("\n").filter(Boolean)) {
|
||||||
|
const matches = line.match(/(\d{1,3})%/g);
|
||||||
|
if (matches) {
|
||||||
|
const match = Math.max(...matches.map((p) => parseInt(p)));
|
||||||
|
const percent = Math.floor(match / 10) * 10;
|
||||||
|
if (percent > 10 && percent > progress) {
|
||||||
|
progress = percent;
|
||||||
|
if (typeof callback === "function") callback(progress - 10, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
proc.on("close", (code) => {
|
||||||
|
if (code !== 0) {
|
||||||
|
console.log(`Script exited with error code ${code}.`);
|
||||||
|
if (typeof callback === "function") callback(null, code);
|
||||||
|
} else {
|
||||||
|
console.log("Script exited successfully.");
|
||||||
|
if (typeof callback === "function") callback(100, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a D-Bus method call synchronously using `dbus-send`.
|
* Executes a D-Bus method call synchronously using `dbus-send`.
|
||||||
*
|
*
|
||||||
@@ -755,14 +854,10 @@ const dbusCall = (path, method, values, callback = null) => {
|
|||||||
const args = ["--print-reply", "--type=method_call", `--dest=${dest}`];
|
const args = ["--print-reply", "--type=method_call", `--dest=${dest}`];
|
||||||
try {
|
try {
|
||||||
const output = cpr.execSync([cmd, ...args].join(" ").trim(), { encoding: "utf8" });
|
const output = cpr.execSync([cmd, ...args].join(" ").trim(), { encoding: "utf8" });
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") callback(output.trim().replace(/\0/g, ""), null);
|
||||||
callback(output.trim().replace(/\0/g, "").split("\n").slice(1).join("\n").trim(), null);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Call D-Bus:", error.message);
|
console.error("Call D-Bus:", error.message);
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") callback(null, error.message);
|
||||||
callback(null, error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -796,17 +891,13 @@ const dbusMonitor = (path, callback) => {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Monitor D-Bus:", error.message);
|
console.error("Monitor D-Bus:", error.message);
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") callback(null, error.message);
|
||||||
callback(null, error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
proc.stderr.on("data", (data) => {
|
proc.stderr.on("data", (data) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
console.error("Monitor D-Bus:", data.toString());
|
console.error("Monitor D-Bus:", data.toString());
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") callback(null, data.toString());
|
||||||
callback(null, data.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return proc;
|
return proc;
|
||||||
@@ -839,6 +930,7 @@ module.exports = {
|
|||||||
getVendor,
|
getVendor,
|
||||||
getSerialNumber,
|
getSerialNumber,
|
||||||
getMachineId,
|
getMachineId,
|
||||||
|
getNetworkAddresses,
|
||||||
getHostName,
|
getHostName,
|
||||||
getUpTime,
|
getUpTime,
|
||||||
getMemorySize,
|
getMemorySize,
|
||||||
@@ -855,4 +947,7 @@ module.exports = {
|
|||||||
checkPackageUpgrades,
|
checkPackageUpgrades,
|
||||||
shutdownSystem,
|
shutdownSystem,
|
||||||
rebootSystem,
|
rebootSystem,
|
||||||
|
execSyncCommand,
|
||||||
|
execAsyncCommand,
|
||||||
|
execScriptCommand,
|
||||||
};
|
};
|
||||||
|
|||||||
+228
-100
@@ -1,11 +1,9 @@
|
|||||||
const mqtt = require("mqtt");
|
const mqtt = require("mqtt");
|
||||||
const hardware = require("./hardware");
|
const hardware = require("./hardware");
|
||||||
const { app } = require("electron");
|
const { app } = require("electron");
|
||||||
const Events = require("events");
|
|
||||||
|
|
||||||
global.INTEGRATION = global.INTEGRATION || {
|
global.INTEGRATION = global.INTEGRATION || {
|
||||||
initialized: false,
|
initialized: false,
|
||||||
events: new Events(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,28 +37,32 @@ const init = async () => {
|
|||||||
// Init globals
|
// Init globals
|
||||||
INTEGRATION.discovery = discovery;
|
INTEGRATION.discovery = discovery;
|
||||||
INTEGRATION.node = `rpi_${deviceId}`;
|
INTEGRATION.node = `rpi_${deviceId}`;
|
||||||
INTEGRATION.root = `${app.getName()}/${INTEGRATION.node}`;
|
INTEGRATION.root = `${APP.name}/${INTEGRATION.node}`;
|
||||||
INTEGRATION.device = {
|
INTEGRATION.device = {
|
||||||
name: `TouchKio ${deviceName}`,
|
name: `${APP.title} ${deviceName}`,
|
||||||
model: model,
|
model: model,
|
||||||
manufacturer: vendor,
|
manufacturer: vendor,
|
||||||
serial_number: serialNumber,
|
serial_number: serialNumber,
|
||||||
identifiers: [INTEGRATION.node],
|
identifiers: [INTEGRATION.node],
|
||||||
sw_version: `${app.getName()}-v${app.getVersion()}`,
|
sw_version: `${APP.name}-v${APP.version}`,
|
||||||
|
configuration_url: APP.homepage,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Connection settings
|
// Connection settings
|
||||||
const options = user === null || password === null ? null : { username: user, password: password };
|
const masked = password === null ? null : "*".repeat(password.length);
|
||||||
const masked = password === null ? "null" : "*".repeat(password.length);
|
const options = user === null || password === null ? {} : { username: user, password: password };
|
||||||
|
options.rejectUnauthorized = !("ignore_certificate_errors" in ARGS);
|
||||||
console.log("MQTT Connecting:", `${user}:${masked}@${url.toString()}`);
|
console.log("MQTT Connecting:", `${user}:${masked}@${url.toString()}`);
|
||||||
INTEGRATION.client = mqtt.connect(url.toString(), options);
|
INTEGRATION.client = mqtt.connect(url.toString(), options);
|
||||||
|
|
||||||
// Client connected
|
// Client connected
|
||||||
INTEGRATION.client
|
INTEGRATION.client
|
||||||
.once("connect", () => {
|
.once("connect", () => {
|
||||||
console.log(`MQTT Connected: ${url.toString()}\n`);
|
console.log(`MQTT Connected: ${url.toString()}`);
|
||||||
|
process.stdout.write("\n");
|
||||||
|
|
||||||
// Init client controls
|
// Init client controls
|
||||||
|
initApp();
|
||||||
initShutdown();
|
initShutdown();
|
||||||
initReboot();
|
initReboot();
|
||||||
initRefresh();
|
initRefresh();
|
||||||
@@ -75,6 +77,7 @@ const init = async () => {
|
|||||||
initModel();
|
initModel();
|
||||||
initSerialNumber();
|
initSerialNumber();
|
||||||
initHostName();
|
initHostName();
|
||||||
|
initNetworkAddress();
|
||||||
initUpTime();
|
initUpTime();
|
||||||
initMemorySize();
|
initMemorySize();
|
||||||
initMemoryUsage();
|
initMemoryUsage();
|
||||||
@@ -93,8 +96,8 @@ const init = async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Update sensor states from events
|
// Update sensor states from events
|
||||||
HARDWARE.events.on("updateDisplay", updateDisplay);
|
EVENTS.on("updateDisplay", updateDisplay);
|
||||||
HARDWARE.events.on("updateKeyboard", updateKeyboard);
|
EVENTS.on("updateKeyboard", updateKeyboard);
|
||||||
|
|
||||||
// Update time sensors periodically (30s)
|
// Update time sensors periodically (30s)
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
@@ -107,8 +110,9 @@ const init = async () => {
|
|||||||
update();
|
update();
|
||||||
}, 60 * 1000);
|
}, 60 * 1000);
|
||||||
|
|
||||||
// Update package sensors periodically (60min)
|
// Update upgrade sensors periodically (1h)
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
|
updateApp();
|
||||||
updatePackageUpgrades();
|
updatePackageUpgrades();
|
||||||
}, 3600 * 1000);
|
}, 3600 * 1000);
|
||||||
|
|
||||||
@@ -128,6 +132,7 @@ const update = async () => {
|
|||||||
updatePageNumber();
|
updatePageNumber();
|
||||||
updatePageZoom();
|
updatePageZoom();
|
||||||
updatePageUrl();
|
updatePageUrl();
|
||||||
|
updateNetworkAddress();
|
||||||
updateUpTime();
|
updateUpTime();
|
||||||
updateLastActive();
|
updateLastActive();
|
||||||
updateMemoryUsage();
|
updateMemoryUsage();
|
||||||
@@ -136,6 +141,22 @@ const update = async () => {
|
|||||||
updateBatteryLevel();
|
updateBatteryLevel();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the auto-discovery config via the mqtt connection.
|
||||||
|
*
|
||||||
|
* @param {string} type - The entity type name.
|
||||||
|
* @param {Object} config - The configuration object.
|
||||||
|
* @returns {Object} Instance of the mqtt client.
|
||||||
|
*/
|
||||||
|
const removeConfig = (type, config) => {
|
||||||
|
if (type === null || config === null) {
|
||||||
|
return INTEGRATION.client;
|
||||||
|
}
|
||||||
|
const path = config.unique_id.replace(`${INTEGRATION.node}_`, "");
|
||||||
|
const root = `${INTEGRATION.discovery}/${type}/${INTEGRATION.node}/${path}/config`;
|
||||||
|
return INTEGRATION.client.publish(root, null, { qos: 1, retain: true });
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publishes the auto-discovery config via the mqtt connection.
|
* Publishes the auto-discovery config via the mqtt connection.
|
||||||
*
|
*
|
||||||
@@ -182,6 +203,63 @@ const publishState = (path, state) => {
|
|||||||
return INTEGRATION.client.publish(root, `${state}`, { qos: 1, retain: true });
|
return INTEGRATION.client.publish(root, `${state}`, { qos: 1, retain: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the app update entity and handles the execute logic.
|
||||||
|
*/
|
||||||
|
const initApp = () => {
|
||||||
|
const root = `${INTEGRATION.root}/app`;
|
||||||
|
const config = {
|
||||||
|
name: "App",
|
||||||
|
unique_id: `${INTEGRATION.node}_app`,
|
||||||
|
command_topic: `${root}/install`,
|
||||||
|
state_topic: `${root}/version/state`,
|
||||||
|
payload_install: "update",
|
||||||
|
device: INTEGRATION.device,
|
||||||
|
};
|
||||||
|
if (!HARDWARE.support.appUpdate) {
|
||||||
|
removeConfig("update", config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
publishConfig("update", config)
|
||||||
|
.on("message", (topic, message) => {
|
||||||
|
if (topic === config.command_topic) {
|
||||||
|
console.log("Update App...");
|
||||||
|
hardware.setDisplayStatus("ON", () => {
|
||||||
|
const args = ["-c", `bash <(wget -qO- ${APP.scripts.install}) update`];
|
||||||
|
hardware.execScriptCommand("bash", args, (progress, error) => {
|
||||||
|
if (progress) {
|
||||||
|
console.log(`Progress: ${progress}%`);
|
||||||
|
}
|
||||||
|
updateApp(progress);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.subscribe(config.command_topic);
|
||||||
|
updateApp();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the app update entity via the mqtt connection.
|
||||||
|
*/
|
||||||
|
const updateApp = async (progress = 0) => {
|
||||||
|
const latest = APP.releases.latest;
|
||||||
|
if (!HARDWARE.support.appUpdate || !latest || !latest.summary) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const summary = latest.summary.length > 250 ? latest.summary.slice(0, 250) + "..." : latest.summary;
|
||||||
|
const version = {
|
||||||
|
title: latest.title,
|
||||||
|
latest_version: latest.version,
|
||||||
|
installed_version: APP.version,
|
||||||
|
release_summary: summary,
|
||||||
|
release_url: latest.url,
|
||||||
|
update_percentage: progress || null,
|
||||||
|
in_progress: progress && progress > 0 && progress < 100,
|
||||||
|
};
|
||||||
|
publishState("app/version", JSON.stringify(version));
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the shutdown button and handles the execute logic.
|
* Initializes the shutdown button and handles the execute logic.
|
||||||
*/
|
*/
|
||||||
@@ -194,12 +272,17 @@ const initShutdown = () => {
|
|||||||
icon: "mdi:power",
|
icon: "mdi:power",
|
||||||
device: INTEGRATION.device,
|
device: INTEGRATION.device,
|
||||||
};
|
};
|
||||||
|
if (!HARDWARE.support.sudoRights) {
|
||||||
|
removeConfig("button", config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
publishConfig("button", config)
|
publishConfig("button", config)
|
||||||
.on("message", (topic, message) => {
|
.on("message", (topic, message) => {
|
||||||
if (topic === config.command_topic) {
|
if (topic === config.command_topic) {
|
||||||
console.log("Shutdown system...");
|
console.log("Shutdown system...");
|
||||||
hardware.setDisplayStatus("ON");
|
hardware.setDisplayStatus("ON", () => {
|
||||||
hardware.shutdownSystem();
|
hardware.shutdownSystem();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.subscribe(config.command_topic);
|
.subscribe(config.command_topic);
|
||||||
@@ -217,12 +300,17 @@ const initReboot = () => {
|
|||||||
icon: "mdi:restart",
|
icon: "mdi:restart",
|
||||||
device: INTEGRATION.device,
|
device: INTEGRATION.device,
|
||||||
};
|
};
|
||||||
|
if (!HARDWARE.support.sudoRights) {
|
||||||
|
removeConfig("button", config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
publishConfig("button", config)
|
publishConfig("button", config)
|
||||||
.on("message", (topic, message) => {
|
.on("message", (topic, message) => {
|
||||||
if (topic === config.command_topic) {
|
if (topic === config.command_topic) {
|
||||||
console.log("Rebooting system...");
|
console.log("Rebooting system...");
|
||||||
hardware.setDisplayStatus("ON");
|
hardware.setDisplayStatus("ON", () => {
|
||||||
hardware.rebootSystem();
|
hardware.rebootSystem();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.subscribe(config.command_topic);
|
.subscribe(config.command_topic);
|
||||||
@@ -244,8 +332,9 @@ const initRefresh = () => {
|
|||||||
.on("message", (topic, message) => {
|
.on("message", (topic, message) => {
|
||||||
if (topic === config.command_topic) {
|
if (topic === config.command_topic) {
|
||||||
console.log("Refreshing webview...");
|
console.log("Refreshing webview...");
|
||||||
hardware.setDisplayStatus("ON");
|
hardware.setDisplayStatus("ON", () => {
|
||||||
WEBVIEW.events.emit("reloadView");
|
EVENTS.emit("reloadView");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.subscribe(config.command_topic);
|
.subscribe(config.command_topic);
|
||||||
@@ -271,31 +360,32 @@ const initKiosk = () => {
|
|||||||
if (topic === config.command_topic) {
|
if (topic === config.command_topic) {
|
||||||
const status = message.toString();
|
const status = message.toString();
|
||||||
console.log("Set Kiosk Status:", status);
|
console.log("Set Kiosk Status:", status);
|
||||||
hardware.setDisplayStatus("ON");
|
hardware.setDisplayStatus("ON", () => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "Framed":
|
case "Framed":
|
||||||
WEBVIEW.window.restore();
|
WEBVIEW.window.restore();
|
||||||
WEBVIEW.window.unmaximize();
|
WEBVIEW.window.unmaximize();
|
||||||
WEBVIEW.window.setFullScreen(false);
|
WEBVIEW.window.setFullScreen(false);
|
||||||
break;
|
break;
|
||||||
case "Fullscreen":
|
case "Fullscreen":
|
||||||
WEBVIEW.window.restore();
|
WEBVIEW.window.restore();
|
||||||
WEBVIEW.window.unmaximize();
|
WEBVIEW.window.unmaximize();
|
||||||
WEBVIEW.window.setFullScreen(true);
|
WEBVIEW.window.setFullScreen(true);
|
||||||
break;
|
break;
|
||||||
case "Maximized":
|
case "Maximized":
|
||||||
WEBVIEW.window.restore();
|
WEBVIEW.window.restore();
|
||||||
WEBVIEW.window.setFullScreen(false);
|
WEBVIEW.window.setFullScreen(false);
|
||||||
WEBVIEW.window.maximize();
|
WEBVIEW.window.maximize();
|
||||||
break;
|
break;
|
||||||
case "Minimized":
|
case "Minimized":
|
||||||
WEBVIEW.window.restore();
|
WEBVIEW.window.restore();
|
||||||
WEBVIEW.window.setFullScreen(false);
|
WEBVIEW.window.setFullScreen(false);
|
||||||
WEBVIEW.window.minimize();
|
WEBVIEW.window.minimize();
|
||||||
break;
|
break;
|
||||||
case "Terminated":
|
case "Terminated":
|
||||||
app.quit();
|
app.quit();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.subscribe(config.command_topic);
|
.subscribe(config.command_topic);
|
||||||
@@ -305,8 +395,8 @@ const initKiosk = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the kiosk status via the mqtt connection.
|
* Updates the kiosk status via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateKiosk = () => {
|
const updateKiosk = async () => {
|
||||||
const kiosk = WEBVIEW.status;
|
const kiosk = WEBVIEW.tracker.status;
|
||||||
publishState("kiosk", kiosk);
|
publishState("kiosk", kiosk);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -314,9 +404,6 @@ const updateKiosk = () => {
|
|||||||
* Initializes the display status, brightness and handles the execute logic.
|
* Initializes the display status, brightness and handles the execute logic.
|
||||||
*/
|
*/
|
||||||
const initDisplay = () => {
|
const initDisplay = () => {
|
||||||
if (!HARDWARE.support.displayStatus) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const root = `${INTEGRATION.root}/display`;
|
const root = `${INTEGRATION.root}/display`;
|
||||||
const config = {
|
const config = {
|
||||||
name: "Display",
|
name: "Display",
|
||||||
@@ -332,26 +419,30 @@ const initDisplay = () => {
|
|||||||
brightness_scale: 100,
|
brightness_scale: 100,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
if (!HARDWARE.support.displayStatus) {
|
||||||
|
removeConfig("light", config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
publishConfig("light", config)
|
publishConfig("light", config)
|
||||||
.on("message", (topic, message) => {
|
.on("message", (topic, message) => {
|
||||||
if (topic === config.command_topic) {
|
if (topic === config.command_topic) {
|
||||||
const status = message.toString();
|
const status = message.toString();
|
||||||
console.log("Set Display Status:", status);
|
console.log("Set Display Status:", status);
|
||||||
hardware.setDisplayStatus(status, (reply, error) => {
|
hardware.setDisplayStatus(status, (reply, error) => {
|
||||||
if (error) {
|
if (!error) {
|
||||||
console.warn("Failed:", error);
|
|
||||||
} else {
|
|
||||||
hardware.update();
|
hardware.update();
|
||||||
|
} else {
|
||||||
|
console.warn("Failed:", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (topic === config.brightness_command_topic) {
|
} else if (topic === config.brightness_command_topic) {
|
||||||
const brightness = parseInt(message, 10);
|
const brightness = parseInt(message, 10);
|
||||||
console.log("Set Display Brightness:", brightness);
|
console.log("Set Display Brightness:", brightness);
|
||||||
hardware.setDisplayBrightness(brightness, (reply, error) => {
|
hardware.setDisplayBrightness(brightness, (reply, error) => {
|
||||||
if (error) {
|
if (!error) {
|
||||||
console.warn("Failed:", error);
|
|
||||||
} else {
|
|
||||||
hardware.update();
|
hardware.update();
|
||||||
|
} else {
|
||||||
|
console.warn("Failed:", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -364,7 +455,7 @@ const initDisplay = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the display status, brightness via the mqtt connection.
|
* Updates the display status, brightness via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateDisplay = () => {
|
const updateDisplay = async () => {
|
||||||
const status = hardware.getDisplayStatus();
|
const status = hardware.getDisplayStatus();
|
||||||
const brightness = hardware.getDisplayBrightness();
|
const brightness = hardware.getDisplayBrightness();
|
||||||
publishState("display/power", status);
|
publishState("display/power", status);
|
||||||
@@ -375,9 +466,6 @@ const updateDisplay = () => {
|
|||||||
* Initializes the keyboard visibility and handles the execute logic.
|
* Initializes the keyboard visibility and handles the execute logic.
|
||||||
*/
|
*/
|
||||||
const initKeyboard = () => {
|
const initKeyboard = () => {
|
||||||
if (!HARDWARE.support.keyboardVisibility) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const root = `${INTEGRATION.root}/keyboard`;
|
const root = `${INTEGRATION.root}/keyboard`;
|
||||||
const config = {
|
const config = {
|
||||||
name: "Keyboard",
|
name: "Keyboard",
|
||||||
@@ -387,24 +475,30 @@ const initKeyboard = () => {
|
|||||||
icon: "mdi:keyboard-close-outline",
|
icon: "mdi:keyboard-close-outline",
|
||||||
device: INTEGRATION.device,
|
device: INTEGRATION.device,
|
||||||
};
|
};
|
||||||
|
if (!HARDWARE.support.keyboardVisibility) {
|
||||||
|
removeConfig("switch", config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
publishConfig("switch", config)
|
publishConfig("switch", config)
|
||||||
.on("message", (topic, message) => {
|
.on("message", (topic, message) => {
|
||||||
if (topic === config.command_topic) {
|
if (topic === config.command_topic) {
|
||||||
const status = message.toString();
|
const status = message.toString();
|
||||||
console.log("Set Keyboard Visibility:", status);
|
console.log("Set Keyboard Visibility:", status);
|
||||||
hardware.setKeyboardVisibility(status);
|
hardware.setDisplayStatus("ON", () => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "OFF":
|
case "OFF":
|
||||||
WEBVIEW.window.restore();
|
WEBVIEW.window.restore();
|
||||||
WEBVIEW.window.unmaximize();
|
WEBVIEW.window.unmaximize();
|
||||||
WEBVIEW.window.setFullScreen(true);
|
WEBVIEW.window.setFullScreen(true);
|
||||||
break;
|
break;
|
||||||
case "ON":
|
case "ON":
|
||||||
WEBVIEW.window.restore();
|
WEBVIEW.window.restore();
|
||||||
WEBVIEW.window.setFullScreen(false);
|
WEBVIEW.window.setFullScreen(false);
|
||||||
WEBVIEW.window.maximize();
|
WEBVIEW.window.maximize();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
hardware.setKeyboardVisibility(status);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.subscribe(config.command_topic);
|
.subscribe(config.command_topic);
|
||||||
@@ -414,7 +508,7 @@ const initKeyboard = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the keyboard visibility via the mqtt connection.
|
* Updates the keyboard visibility via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateKeyboard = () => {
|
const updateKeyboard = async () => {
|
||||||
const visibility = hardware.getKeyboardVisibility();
|
const visibility = hardware.getKeyboardVisibility();
|
||||||
publishState("keyboard", visibility);
|
publishState("keyboard", visibility);
|
||||||
};
|
};
|
||||||
@@ -423,9 +517,6 @@ const updateKeyboard = () => {
|
|||||||
* Initializes the page number and handles the execute logic.
|
* Initializes the page number and handles the execute logic.
|
||||||
*/
|
*/
|
||||||
const initPageNumber = () => {
|
const initPageNumber = () => {
|
||||||
if (WEBVIEW.viewUrls.length < 3) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const root = `${INTEGRATION.root}/page_number`;
|
const root = `${INTEGRATION.root}/page_number`;
|
||||||
const config = {
|
const config = {
|
||||||
name: "Page Number",
|
name: "Page Number",
|
||||||
@@ -440,13 +531,17 @@ const initPageNumber = () => {
|
|||||||
icon: "mdi:page-next",
|
icon: "mdi:page-next",
|
||||||
device: INTEGRATION.device,
|
device: INTEGRATION.device,
|
||||||
};
|
};
|
||||||
|
if (WEBVIEW.viewUrls.length <= 2) {
|
||||||
|
removeConfig("number", config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
publishConfig("number", config)
|
publishConfig("number", config)
|
||||||
.on("message", (topic, message) => {
|
.on("message", (topic, message) => {
|
||||||
if (topic === config.command_topic) {
|
if (topic === config.command_topic) {
|
||||||
const number = parseInt(message, 10);
|
const number = parseInt(message, 10);
|
||||||
console.log("Set Page Number:", number);
|
console.log("Set Page Number:", number);
|
||||||
WEBVIEW.viewActive = number || 1;
|
WEBVIEW.viewActive = number || 1;
|
||||||
WEBVIEW.events.emit("updateView");
|
EVENTS.emit("updateView");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.subscribe(config.command_topic);
|
.subscribe(config.command_topic);
|
||||||
@@ -456,8 +551,8 @@ const initPageNumber = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the page number via the mqtt connection.
|
* Updates the page number via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updatePageNumber = () => {
|
const updatePageNumber = async () => {
|
||||||
const pageNumber = WEBVIEW.viewActive || 1;
|
const pageNumber = WEBVIEW.viewUrls.length <= 2 ? null : WEBVIEW.viewActive || 1;
|
||||||
publishState("page_number", pageNumber);
|
publishState("page_number", pageNumber);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -485,7 +580,7 @@ const initPageZoom = () => {
|
|||||||
const zoom = parseInt(message, 10);
|
const zoom = parseInt(message, 10);
|
||||||
console.log("Set Page Zoom:", zoom);
|
console.log("Set Page Zoom:", zoom);
|
||||||
WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.setZoomFactor(zoom / 100.0);
|
WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.setZoomFactor(zoom / 100.0);
|
||||||
WEBVIEW.events.emit("updateView");
|
EVENTS.emit("updateView");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.subscribe(config.command_topic);
|
.subscribe(config.command_topic);
|
||||||
@@ -495,7 +590,7 @@ const initPageZoom = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the page zoom via the mqtt connection.
|
* Updates the page zoom via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updatePageZoom = () => {
|
const updatePageZoom = async () => {
|
||||||
const pageZoom = Math.round(WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.getZoomFactor() * 100.0);
|
const pageZoom = Math.round(WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.getZoomFactor() * 100.0);
|
||||||
publishState("page_zoom", pageZoom);
|
publishState("page_zoom", pageZoom);
|
||||||
};
|
};
|
||||||
@@ -530,7 +625,7 @@ const initPageUrl = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the page url via the mqtt connection.
|
* Updates the page url via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updatePageUrl = () => {
|
const updatePageUrl = async () => {
|
||||||
const defaultUrl = WEBVIEW.viewUrls[WEBVIEW.viewActive || 1];
|
const defaultUrl = WEBVIEW.viewUrls[WEBVIEW.viewActive || 1];
|
||||||
const currentUrl = WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.getURL();
|
const currentUrl = WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.getURL();
|
||||||
const pageUrl = !currentUrl || currentUrl.startsWith("data:") ? defaultUrl : currentUrl;
|
const pageUrl = !currentUrl || currentUrl.startsWith("data:") ? defaultUrl : currentUrl;
|
||||||
@@ -546,6 +641,7 @@ const initModel = () => {
|
|||||||
name: "Model",
|
name: "Model",
|
||||||
unique_id: `${INTEGRATION.node}_model`,
|
unique_id: `${INTEGRATION.node}_model`,
|
||||||
state_topic: `${root}/state`,
|
state_topic: `${root}/state`,
|
||||||
|
json_attributes_topic: `${root}/attributes`,
|
||||||
value_template: "{{ value }}",
|
value_template: "{{ value }}",
|
||||||
icon: "mdi:raspberry-pi",
|
icon: "mdi:raspberry-pi",
|
||||||
device: INTEGRATION.device,
|
device: INTEGRATION.device,
|
||||||
@@ -557,9 +653,10 @@ const initModel = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the model sensor via the mqtt connection.
|
* Updates the model sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateModel = () => {
|
const updateModel = async () => {
|
||||||
const model = hardware.getModel();
|
const model = hardware.getModel();
|
||||||
publishState("model", model);
|
publishState("model", model);
|
||||||
|
publishAttributes("model", HARDWARE.support);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -582,11 +679,41 @@ const initSerialNumber = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the serial number sensor via the mqtt connection.
|
* Updates the serial number sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateSerialNumber = () => {
|
const updateSerialNumber = async () => {
|
||||||
const serialNumber = hardware.getSerialNumber();
|
const serialNumber = hardware.getSerialNumber();
|
||||||
publishState("serial_number", serialNumber);
|
publishState("serial_number", serialNumber);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the network address sensor.
|
||||||
|
*/
|
||||||
|
const initNetworkAddress = () => {
|
||||||
|
const root = `${INTEGRATION.root}/network_address`;
|
||||||
|
const config = {
|
||||||
|
name: "Network Address",
|
||||||
|
unique_id: `${INTEGRATION.node}_network_address`,
|
||||||
|
state_topic: `${root}/state`,
|
||||||
|
json_attributes_topic: `${root}/attributes`,
|
||||||
|
value_template: "{{ value }}",
|
||||||
|
icon: "mdi:ip-network",
|
||||||
|
device: INTEGRATION.device,
|
||||||
|
};
|
||||||
|
publishConfig("sensor", config);
|
||||||
|
updateNetworkAddress();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the network address sensor via the mqtt connection.
|
||||||
|
*/
|
||||||
|
const updateNetworkAddress = async () => {
|
||||||
|
const networkAddresses = hardware.getNetworkAddresses();
|
||||||
|
const [name] = Object.keys(networkAddresses);
|
||||||
|
const [family] = name ? Object.keys(networkAddresses[name]) : [];
|
||||||
|
const networkAddress = networkAddresses[name]?.[family]?.[0] || null;
|
||||||
|
publishState("network_address", networkAddress);
|
||||||
|
publishAttributes("network_address", networkAddresses);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the host name sensor.
|
* Initializes the host name sensor.
|
||||||
*/
|
*/
|
||||||
@@ -607,7 +734,7 @@ const initHostName = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the host name sensor via the mqtt connection.
|
* Updates the host name sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateHostName = () => {
|
const updateHostName = async () => {
|
||||||
const hostName = hardware.getHostName();
|
const hostName = hardware.getHostName();
|
||||||
publishState("host_name", hostName);
|
publishState("host_name", hostName);
|
||||||
};
|
};
|
||||||
@@ -633,7 +760,7 @@ const initUpTime = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the up time sensor via the mqtt connection.
|
* Updates the up time sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateUpTime = () => {
|
const updateUpTime = async () => {
|
||||||
const upTime = hardware.getUpTime();
|
const upTime = hardware.getUpTime();
|
||||||
publishState("up_time", upTime);
|
publishState("up_time", upTime);
|
||||||
};
|
};
|
||||||
@@ -659,7 +786,7 @@ const initMemorySize = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the memory size sensor via the mqtt connection.
|
* Updates the memory size sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateMemorySize = () => {
|
const updateMemorySize = async () => {
|
||||||
const memorySize = hardware.getMemorySize();
|
const memorySize = hardware.getMemorySize();
|
||||||
publishState("memory_size", memorySize);
|
publishState("memory_size", memorySize);
|
||||||
};
|
};
|
||||||
@@ -685,7 +812,7 @@ const initMemoryUsage = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the memory usage sensor via the mqtt connection.
|
* Updates the memory usage sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateMemoryUsage = () => {
|
const updateMemoryUsage = async () => {
|
||||||
const memoryUsage = hardware.getMemoryUsage();
|
const memoryUsage = hardware.getMemoryUsage();
|
||||||
publishState("memory_usage", memoryUsage);
|
publishState("memory_usage", memoryUsage);
|
||||||
};
|
};
|
||||||
@@ -711,7 +838,7 @@ const initProcessorUsage = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the processor usage sensor via the mqtt connection.
|
* Updates the processor usage sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateProcessorUsage = () => {
|
const updateProcessorUsage = async () => {
|
||||||
const processorUsage = hardware.getProcessorUsage();
|
const processorUsage = hardware.getProcessorUsage();
|
||||||
publishState("processor_usage", processorUsage);
|
publishState("processor_usage", processorUsage);
|
||||||
};
|
};
|
||||||
@@ -737,7 +864,7 @@ const initProcessorTemperature = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the processor temperature sensor via the mqtt connection.
|
* Updates the processor temperature sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateProcessorTemperature = () => {
|
const updateProcessorTemperature = async () => {
|
||||||
const processorTemperature = hardware.getProcessorTemperature();
|
const processorTemperature = hardware.getProcessorTemperature();
|
||||||
publishState("processor_temperature", processorTemperature);
|
publishState("processor_temperature", processorTemperature);
|
||||||
};
|
};
|
||||||
@@ -746,9 +873,6 @@ const updateProcessorTemperature = () => {
|
|||||||
* Initializes the battery level sensor.
|
* Initializes the battery level sensor.
|
||||||
*/
|
*/
|
||||||
const initBatteryLevel = () => {
|
const initBatteryLevel = () => {
|
||||||
if (!HARDWARE.support.batteryLevel) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const root = `${INTEGRATION.root}/battery_level`;
|
const root = `${INTEGRATION.root}/battery_level`;
|
||||||
const config = {
|
const config = {
|
||||||
name: "Battery Level",
|
name: "Battery Level",
|
||||||
@@ -759,6 +883,10 @@ const initBatteryLevel = () => {
|
|||||||
icon: "mdi:battery-medium",
|
icon: "mdi:battery-medium",
|
||||||
device: INTEGRATION.device,
|
device: INTEGRATION.device,
|
||||||
};
|
};
|
||||||
|
if (!HARDWARE.support.batteryLevel) {
|
||||||
|
removeConfig("sensor", config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
publishConfig("sensor", config);
|
publishConfig("sensor", config);
|
||||||
updateBatteryLevel();
|
updateBatteryLevel();
|
||||||
};
|
};
|
||||||
@@ -766,7 +894,7 @@ const initBatteryLevel = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the battery level sensor via the mqtt connection.
|
* Updates the battery level sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateBatteryLevel = () => {
|
const updateBatteryLevel = async () => {
|
||||||
const batteryLevel = hardware.getBatteryLevel();
|
const batteryLevel = hardware.getBatteryLevel();
|
||||||
publishState("battery_level", batteryLevel);
|
publishState("battery_level", batteryLevel);
|
||||||
};
|
};
|
||||||
@@ -792,14 +920,14 @@ const initPackageUpgrades = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the package upgrades sensor via the mqtt connection.
|
* Updates the package upgrades sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updatePackageUpgrades = () => {
|
const updatePackageUpgrades = async () => {
|
||||||
const packages = hardware.checkPackageUpgrades();
|
const packages = hardware.checkPackageUpgrades();
|
||||||
const attributes = {
|
const upgrades = {
|
||||||
total: packages.length,
|
total: packages.length,
|
||||||
packages: packages.map((pkg) => pkg.replace(/\s*\[.*?\]\s*/g, "").trim()),
|
packages: packages.map((pkg) => pkg.replace(/\s*\[.*?\]\s*/g, "").trim()),
|
||||||
};
|
};
|
||||||
publishAttributes("package_upgrades", attributes);
|
publishState("package_upgrades", upgrades.total);
|
||||||
publishState("package_upgrades", attributes.total);
|
publishAttributes("package_upgrades", upgrades);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -822,7 +950,7 @@ const initHeartbeat = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the heartbeat sensor via the mqtt connection.
|
* Updates the heartbeat sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateHeartbeat = () => {
|
const updateHeartbeat = async () => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const local = new Date(now.getTime() - now.getTimezoneOffset() * 60 * 1000);
|
const local = new Date(now.getTime() - now.getTimezoneOffset() * 60 * 1000);
|
||||||
const heartbeat = local.toISOString().replace(/\.\d{3}Z$/, "");
|
const heartbeat = local.toISOString().replace(/\.\d{3}Z$/, "");
|
||||||
@@ -850,10 +978,10 @@ const initLastActive = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the last active sensor via the mqtt connection.
|
* Updates the last active sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateLastActive = () => {
|
const updateLastActive = async () => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const then = WEBVIEW.pointer.time;
|
const then = WEBVIEW.tracker.pointer.time;
|
||||||
const lastActive = Math.abs(now - then) / (1000 * 60);
|
const lastActive = (now - then) / (1000 * 60);
|
||||||
publishState("last_active", lastActive);
|
publishState("last_active", lastActive);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+110
-63
@@ -1,17 +1,19 @@
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
|
const https = require("https");
|
||||||
const hardware = require("./hardware");
|
const hardware = require("./hardware");
|
||||||
const integration = require("./integration");
|
const integration = require("./integration");
|
||||||
const { app, nativeTheme, globalShortcut, ipcMain, session, BaseWindow, WebContentsView } = require("electron");
|
const { app, nativeTheme, globalShortcut, ipcMain, session, BaseWindow, WebContentsView } = require("electron");
|
||||||
const Events = require("events");
|
|
||||||
|
|
||||||
global.WEBVIEW = global.WEBVIEW || {
|
global.WEBVIEW = global.WEBVIEW || {
|
||||||
initialized: false,
|
initialized: false,
|
||||||
events: new Events(),
|
tracker: {
|
||||||
status: null,
|
pointer: {
|
||||||
locked: false,
|
position: {},
|
||||||
pointer: {
|
time: new Date(),
|
||||||
time: new Date(),
|
},
|
||||||
|
display: {},
|
||||||
|
status: null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -49,13 +51,11 @@ const init = async () => {
|
|||||||
WEBVIEW.navigationTheme = theme;
|
WEBVIEW.navigationTheme = theme;
|
||||||
WEBVIEW.navigationEnabled = widget;
|
WEBVIEW.navigationEnabled = widget;
|
||||||
nativeTheme.themeSource = WEBVIEW.viewTheme;
|
nativeTheme.themeSource = WEBVIEW.viewTheme;
|
||||||
WEBVIEW.events.on("reloadView", reloadView);
|
|
||||||
WEBVIEW.events.on("updateView", updateView);
|
|
||||||
|
|
||||||
// Init global root window
|
// Init global root window
|
||||||
WEBVIEW.window = new BaseWindow({
|
WEBVIEW.window = new BaseWindow({
|
||||||
title: "TouchKio",
|
title: APP.title,
|
||||||
icon: path.join(__dirname, "..", "img", "icon.png"),
|
icon: path.join(APP.path, "img", "icon.png"),
|
||||||
});
|
});
|
||||||
WEBVIEW.window.setMenuBarVisibility(false);
|
WEBVIEW.window.setMenuBarVisibility(false);
|
||||||
WEBVIEW.window.setFullScreen(fullscreen);
|
WEBVIEW.window.setFullScreen(fullscreen);
|
||||||
@@ -91,7 +91,7 @@ const init = async () => {
|
|||||||
});
|
});
|
||||||
WEBVIEW.pager.setBackgroundColor("#00000000");
|
WEBVIEW.pager.setBackgroundColor("#00000000");
|
||||||
WEBVIEW.window.contentView.addChildView(WEBVIEW.pager);
|
WEBVIEW.window.contentView.addChildView(WEBVIEW.pager);
|
||||||
WEBVIEW.pager.webContents.loadFile(path.join(app.getAppPath(), "html", "pager.html"));
|
WEBVIEW.pager.webContents.loadFile(path.join(APP.path, "html", "pager.html"));
|
||||||
|
|
||||||
// Init global widget
|
// Init global widget
|
||||||
WEBVIEW.widget = new WebContentsView({
|
WEBVIEW.widget = new WebContentsView({
|
||||||
@@ -103,7 +103,7 @@ const init = async () => {
|
|||||||
});
|
});
|
||||||
WEBVIEW.widget.setBackgroundColor("#00000000");
|
WEBVIEW.widget.setBackgroundColor("#00000000");
|
||||||
WEBVIEW.window.contentView.addChildView(WEBVIEW.widget);
|
WEBVIEW.window.contentView.addChildView(WEBVIEW.widget);
|
||||||
WEBVIEW.widget.webContents.loadFile(path.join(app.getAppPath(), "html", "widget.html"));
|
WEBVIEW.widget.webContents.loadFile(path.join(APP.path, "html", "widget.html"));
|
||||||
|
|
||||||
// Init global navigation
|
// Init global navigation
|
||||||
WEBVIEW.navigation = new WebContentsView({
|
WEBVIEW.navigation = new WebContentsView({
|
||||||
@@ -115,14 +115,24 @@ const init = async () => {
|
|||||||
});
|
});
|
||||||
WEBVIEW.navigation.setBackgroundColor("#00000000");
|
WEBVIEW.navigation.setBackgroundColor("#00000000");
|
||||||
WEBVIEW.window.contentView.addChildView(WEBVIEW.navigation);
|
WEBVIEW.window.contentView.addChildView(WEBVIEW.navigation);
|
||||||
WEBVIEW.navigation.webContents.loadFile(path.join(app.getAppPath(), "html", "navigation.html"));
|
WEBVIEW.navigation.webContents.loadFile(path.join(APP.path, "html", "navigation.html"));
|
||||||
|
|
||||||
// Register events
|
// Register global events
|
||||||
windowEvents();
|
EVENTS.on("reloadView", reloadView);
|
||||||
widgetEvents();
|
EVENTS.on("updateView", updateView);
|
||||||
navigationEvents();
|
EVENTS.on("updateDisplay", () => {
|
||||||
viewEvents();
|
const status = hardware.getDisplayStatus();
|
||||||
appEvents();
|
if (status) {
|
||||||
|
WEBVIEW.tracker.display[status.toLowerCase()] = new Date();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register local events
|
||||||
|
await windowEvents();
|
||||||
|
await widgetEvents();
|
||||||
|
await navigationEvents();
|
||||||
|
await viewEvents();
|
||||||
|
await appEvents();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -135,15 +145,15 @@ const update = async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update windows status
|
// Update window status
|
||||||
if (WEBVIEW.window.isFullScreen()) {
|
if (WEBVIEW.window.isFullScreen()) {
|
||||||
WEBVIEW.status = "Fullscreen";
|
WEBVIEW.tracker.status = "Fullscreen";
|
||||||
} else if (WEBVIEW.window.isMinimized()) {
|
} else if (WEBVIEW.window.isMinimized()) {
|
||||||
WEBVIEW.status = "Minimized";
|
WEBVIEW.tracker.status = "Minimized";
|
||||||
} else if (WEBVIEW.window.isMaximized()) {
|
} else if (WEBVIEW.window.isMaximized()) {
|
||||||
WEBVIEW.status = "Maximized";
|
WEBVIEW.tracker.status = "Maximized";
|
||||||
} else {
|
} else {
|
||||||
WEBVIEW.status = "Framed";
|
WEBVIEW.tracker.status = "Framed";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update widget status
|
// Update widget status
|
||||||
@@ -153,7 +163,7 @@ const update = async () => {
|
|||||||
updateNavigation();
|
updateNavigation();
|
||||||
|
|
||||||
// Update integration sensor
|
// Update integration sensor
|
||||||
console.log("Update Kiosk Status:", WEBVIEW.status);
|
console.log("Update Kiosk Status:", WEBVIEW.tracker.status);
|
||||||
integration.update();
|
integration.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -166,7 +176,7 @@ const updateView = () => {
|
|||||||
}
|
}
|
||||||
const url = WEBVIEW.views[WEBVIEW.viewActive].webContents.getURL();
|
const url = WEBVIEW.views[WEBVIEW.viewActive].webContents.getURL();
|
||||||
const host = url.startsWith("data:") ? "whoopsie" : new URL(url).host;
|
const host = url.startsWith("data:") ? "whoopsie" : new URL(url).host;
|
||||||
const title = `TouchKio - ${host} (${WEBVIEW.viewActive})`;
|
const title = `${APP.title} - ${host} (${WEBVIEW.viewActive})`;
|
||||||
|
|
||||||
// Update window title
|
// Update window title
|
||||||
console.log(`Update View: ${title}`);
|
console.log(`Update View: ${title}`);
|
||||||
@@ -427,27 +437,12 @@ const resizeView = () => {
|
|||||||
/**
|
/**
|
||||||
* Register window events and handler.
|
* Register window events and handler.
|
||||||
*/
|
*/
|
||||||
const windowEvents = () => {
|
const windowEvents = async () => {
|
||||||
// Handle window resize events
|
// Handle window resize events
|
||||||
WEBVIEW.window.on("ready-to-show", resizeView);
|
WEBVIEW.window.on("ready-to-show", resizeView);
|
||||||
WEBVIEW.window.on("resize", resizeView);
|
WEBVIEW.window.on("resize", resizeView);
|
||||||
resizeView();
|
resizeView();
|
||||||
|
|
||||||
// Handle window focus events
|
|
||||||
WEBVIEW.window.on("focus", () => {
|
|
||||||
if (WEBVIEW.locked) {
|
|
||||||
hardware.setDisplayStatus("ON");
|
|
||||||
WEBVIEW.window.blur();
|
|
||||||
}
|
|
||||||
WEBVIEW.locked = false;
|
|
||||||
});
|
|
||||||
HARDWARE.events.on("updateDisplay", () => {
|
|
||||||
WEBVIEW.locked = hardware.getDisplayStatus() === "OFF";
|
|
||||||
if (WEBVIEW.locked) {
|
|
||||||
WEBVIEW.window.blur();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle window status updates
|
// Handle window status updates
|
||||||
WEBVIEW.window.on("minimize", update);
|
WEBVIEW.window.on("minimize", update);
|
||||||
WEBVIEW.window.on("restore", update);
|
WEBVIEW.window.on("restore", update);
|
||||||
@@ -476,11 +471,11 @@ const windowEvents = () => {
|
|||||||
historyForward();
|
historyForward();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle window touch events
|
// Check for window touch events (1s)
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const then = WEBVIEW.pointer.time;
|
const then = WEBVIEW.tracker.pointer.time;
|
||||||
const delta = Math.abs(now - then) / 1000;
|
const delta = (now - then) / 1000;
|
||||||
|
|
||||||
// Auto-hide navigation
|
// Auto-hide navigation
|
||||||
if (delta > 60) {
|
if (delta > 60) {
|
||||||
@@ -495,7 +490,7 @@ const windowEvents = () => {
|
|||||||
/**
|
/**
|
||||||
* Register widget events and handler.
|
* Register widget events and handler.
|
||||||
*/
|
*/
|
||||||
const widgetEvents = () => {
|
const widgetEvents = async () => {
|
||||||
if (!WEBVIEW.widgetEnabled) {
|
if (!WEBVIEW.widgetEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -581,7 +576,7 @@ const widgetEvents = () => {
|
|||||||
/**
|
/**
|
||||||
* Register navigation events and handler.
|
* Register navigation events and handler.
|
||||||
*/
|
*/
|
||||||
const navigationEvents = () => {
|
const navigationEvents = async () => {
|
||||||
if (!WEBVIEW.navigationEnabled) {
|
if (!WEBVIEW.navigationEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -680,7 +675,7 @@ const navigationEvents = () => {
|
|||||||
/**
|
/**
|
||||||
* Register view events and handler.
|
* Register view events and handler.
|
||||||
*/
|
*/
|
||||||
const viewEvents = () => {
|
const viewEvents = async () => {
|
||||||
const ready = [];
|
const ready = [];
|
||||||
WEBVIEW.views.forEach((view, i) => {
|
WEBVIEW.views.forEach((view, i) => {
|
||||||
// Enable webview touch emulation
|
// Enable webview touch emulation
|
||||||
@@ -740,18 +735,38 @@ const viewEvents = () => {
|
|||||||
// Handle webview mouse events
|
// Handle webview mouse events
|
||||||
view.webContents.on("before-mouse-event", (e, mouse) => {
|
view.webContents.on("before-mouse-event", (e, mouse) => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const then = WEBVIEW.pointer.time;
|
const then = WEBVIEW.tracker.pointer.time;
|
||||||
const delta = Math.abs(now - then) / 1000;
|
const delta = (now - then) / 1000;
|
||||||
WEBVIEW.pointer.time = now;
|
|
||||||
switch (mouse.type) {
|
switch (mouse.type) {
|
||||||
case "mouseMove":
|
case "mouseMove":
|
||||||
if (delta > 30) {
|
const posNew = { x: mouse.globalX, y: mouse.globalY };
|
||||||
console.log("Update Last Active");
|
if (posNew.x < 0 || posNew.y < 0) {
|
||||||
integration.update();
|
break;
|
||||||
|
}
|
||||||
|
// Update last active on pointer position change
|
||||||
|
const posOld = WEBVIEW.tracker.pointer.position;
|
||||||
|
if (posOld.x !== posNew.x || posOld.y !== posNew.y) {
|
||||||
|
WEBVIEW.tracker.pointer.time = now;
|
||||||
|
WEBVIEW.tracker.pointer.position = posNew;
|
||||||
|
if (delta > 30) {
|
||||||
|
console.log("Update Last Active");
|
||||||
|
integration.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "mouseDown":
|
case "mouseDown":
|
||||||
switch (mouse.button) {
|
switch (mouse.button) {
|
||||||
|
case "left":
|
||||||
|
// Ignore touch event if display was off
|
||||||
|
if (WEBVIEW.tracker.display.off > WEBVIEW.tracker.display.on) {
|
||||||
|
console.log("Display Touch Event: Ignored");
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
// Turn display on if it was off
|
||||||
|
if (hardware.getDisplayStatus() === "OFF") {
|
||||||
|
hardware.setDisplayStatus("ON");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "back":
|
case "back":
|
||||||
historyBackward();
|
historyBackward();
|
||||||
break;
|
break;
|
||||||
@@ -768,14 +783,7 @@ const viewEvents = () => {
|
|||||||
/**
|
/**
|
||||||
* Register app events and handler.
|
* Register app events and handler.
|
||||||
*/
|
*/
|
||||||
const appEvents = () => {
|
const appEvents = async () => {
|
||||||
// Handle signal and exit events
|
|
||||||
process.on("SIGINT", app.quit);
|
|
||||||
app.on("before-quit", () => {
|
|
||||||
WEBVIEW.status = "Terminated";
|
|
||||||
integration.update();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle multiple instances
|
// Handle multiple instances
|
||||||
app.on("second-instance", () => {
|
app.on("second-instance", () => {
|
||||||
if (WEBVIEW.window.isMinimized()) {
|
if (WEBVIEW.window.isMinimized()) {
|
||||||
@@ -784,8 +792,43 @@ const appEvents = () => {
|
|||||||
WEBVIEW.window.focus();
|
WEBVIEW.window.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle signal and exit events
|
||||||
|
app.on("before-quit", () => {
|
||||||
|
WEBVIEW.tracker.status = "Terminated";
|
||||||
|
console.warn(`${APP.title} Terminated`);
|
||||||
|
integration.update();
|
||||||
|
});
|
||||||
|
process.on("SIGINT", app.quit);
|
||||||
|
|
||||||
// Webview initialized
|
// Webview initialized
|
||||||
WEBVIEW.initialized = true;
|
WEBVIEW.initialized = true;
|
||||||
|
|
||||||
|
// Check for latest release infos (2h)
|
||||||
|
setInterval(() => {
|
||||||
|
latestRelease();
|
||||||
|
}, 7200 * 1000);
|
||||||
|
await latestRelease();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the latest app release infos from github.
|
||||||
|
*/
|
||||||
|
const latestRelease = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`${APP.releases.url}/latest`, { timeout: 10000 });
|
||||||
|
const data = response ? response.data : null;
|
||||||
|
if (!data || data.draft || data.prerelease) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
APP.releases.latest = {
|
||||||
|
title: APP.title,
|
||||||
|
version: (data.tag_name || data.name || " ").replace(/^v/i, ""),
|
||||||
|
summary: data.body || " ",
|
||||||
|
url: data.html_url || " ",
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Github Error:", error.message);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -803,7 +846,8 @@ const onlineStatus = (url, interval = 1000, timeout = 60000) => {
|
|||||||
const elapsed = Date.now() - start;
|
const elapsed = Date.now() - start;
|
||||||
try {
|
try {
|
||||||
if (!url.startsWith("data:")) {
|
if (!url.startsWith("data:")) {
|
||||||
await axios.get(url, { timeout: 10000 });
|
const agent = new https.Agent({ rejectUnauthorized: !("ignore_certificate_errors" in ARGS) });
|
||||||
|
await axios.get(url, { httpsAgent: agent, timeout: 10000 });
|
||||||
}
|
}
|
||||||
resolve(true);
|
resolve(true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -811,6 +855,9 @@ const onlineStatus = (url, interval = 1000, timeout = 60000) => {
|
|||||||
console.warn(`Checking Connection: ${url}`, error.message);
|
console.warn(`Checking Connection: ${url}`, error.message);
|
||||||
}
|
}
|
||||||
if (elapsed >= timeout) {
|
if (elapsed >= timeout) {
|
||||||
|
if (error.message?.includes("certificate")) {
|
||||||
|
console.error("Certificate Error: See https://github.com/leukipp/touchkio/issues/76");
|
||||||
|
}
|
||||||
resolve(false);
|
resolve(false);
|
||||||
} else {
|
} else {
|
||||||
setTimeout(check, interval);
|
setTimeout(check, interval);
|
||||||
|
|||||||
+12
-9
@@ -1,28 +1,31 @@
|
|||||||
{
|
{
|
||||||
"name": "touchkio",
|
"name": "touchkio",
|
||||||
|
"title": "TouchKio",
|
||||||
"description": "Home Assistant Touch Kiosk",
|
"description": "Home Assistant Touch Kiosk",
|
||||||
"homepage": "https://github.com/leukipp/touchkio",
|
"homepage": "https://github.com/leukipp/touchkio",
|
||||||
"author": "leukipp",
|
"author": "leukipp",
|
||||||
"version": "1.2.1",
|
"version": "1.3.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron . --web-url=https://demo.home-assistant.io,https://demo.immichkiosk.app --app-debug=false --trace-warnings",
|
"start": "electron . --web-url=https://demo.home-assistant.io,https://demo.immichkiosk.app --app-debug=false --trace-warnings --ignore-certificate-errors",
|
||||||
"build": "electron-forge make"
|
"build": "electron-forge make"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"printWidth": 120
|
"printWidth": 120
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@electron-forge/cli": "^7.8.3",
|
"@electron-forge/cli": "^7.9.0",
|
||||||
"@electron-forge/maker-deb": "^7.8.3",
|
"@electron-forge/maker-deb": "^7.9.0",
|
||||||
"@electron-forge/maker-zip": "^7.8.3",
|
"@electron-forge/maker-zip": "^7.9.0",
|
||||||
"@electron-forge/publisher-github": "^7.8.3",
|
"@electron-forge/publisher-github": "^7.9.0",
|
||||||
"electron": "^37.4.0",
|
"electron": "^38.1.2",
|
||||||
|
"jszip": "^3.10.1",
|
||||||
"prettier": "^3.6.2"
|
"prettier": "^3.6.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.12.2",
|
||||||
"mqtt": "^5.14.0"
|
"electron-log": "^5.4.3",
|
||||||
|
"mqtt": "^5.14.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,21 @@
|
|||||||
|
|
||||||
|
|
||||||
"@babel/runtime@^7.28.3":
|
"@babel/runtime@^7.28.3":
|
||||||
version "7.28.3"
|
version "7.28.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.3.tgz#75c5034b55ba868121668be5d5bb31cc64e6e61a"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326"
|
||||||
integrity sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==
|
integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==
|
||||||
|
|
||||||
"@electron-forge/cli@^7.8.3":
|
"@electron-forge/cli@^7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/cli/-/cli-7.8.3.tgz#22eb1409047f747a9f2a8b697c1e2c5f461d2d84"
|
resolved "https://registry.yarnpkg.com/@electron-forge/cli/-/cli-7.9.0.tgz#de79184bbcdceaa5a8beb35c27bf15f4ba022ab7"
|
||||||
integrity sha512-BSAjGGfVf0yp3NQhXYmyCw9T//YCQHuktMv4HXfDVfo7AoV6DA1oEhqldI4Q7aHKeRob5+yBkvRRYPiu5ayCPw==
|
integrity sha512-FIs9rV6gN1v8rY73j/dvhQWF8tht035bN2LatY/z99H2KpWr0lhD03MOkIM2lRgrPEqVTExA4JEl9ja9yXBD3Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/core" "7.8.3"
|
"@electron-forge/core" "7.9.0"
|
||||||
"@electron-forge/core-utils" "7.8.3"
|
"@electron-forge/core-utils" "7.9.0"
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
"@electron/get" "^3.0.0"
|
"@electron/get" "^3.0.0"
|
||||||
|
"@inquirer/prompts" "^6.0.1"
|
||||||
|
"@listr2/prompt-adapter-inquirer" "^2.0.22"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
commander "^11.1.0"
|
commander "^11.1.0"
|
||||||
debug "^4.3.1"
|
debug "^4.3.1"
|
||||||
@@ -24,12 +26,12 @@
|
|||||||
log-symbols "^4.0.0"
|
log-symbols "^4.0.0"
|
||||||
semver "^7.2.1"
|
semver "^7.2.1"
|
||||||
|
|
||||||
"@electron-forge/core-utils@7.8.3":
|
"@electron-forge/core-utils@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/core-utils/-/core-utils-7.8.3.tgz#8aac92271fbf5de3e1f657179db5e027ea5dd48a"
|
resolved "https://registry.yarnpkg.com/@electron-forge/core-utils/-/core-utils-7.9.0.tgz#0c9fa40460182ad03e6eb392d72e7a65f3c04471"
|
||||||
integrity sha512-8jhK7AvUKEqDyTMMuRhvS1TkE73YEnHYAxVvkJq35e1KdCwGbGnSRhaEs7OOqRfkKxfepdJ7BMKFSoKFeP+z0Q==
|
integrity sha512-votOf1+20cUJim0smYZW7OylXrl89JlpuFTgFpn5WFpDfAV6C0iH9202K1sa33v9OQ989JnpWDZtQNQzQHHNtg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
"@electron/rebuild" "^3.7.0"
|
"@electron/rebuild" "^3.7.0"
|
||||||
"@malept/cross-spawn-promise" "^2.0.0"
|
"@malept/cross-spawn-promise" "^2.0.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
@@ -39,26 +41,27 @@
|
|||||||
log-symbols "^4.0.0"
|
log-symbols "^4.0.0"
|
||||||
semver "^7.2.1"
|
semver "^7.2.1"
|
||||||
|
|
||||||
"@electron-forge/core@7.8.3":
|
"@electron-forge/core@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/core/-/core-7.8.3.tgz#d7a715e9cef80b083e898b4c6b941178276d4a36"
|
resolved "https://registry.yarnpkg.com/@electron-forge/core/-/core-7.9.0.tgz#96e7b0990cc661b2344648be8108c45a815a910c"
|
||||||
integrity sha512-qX2vi/LP3HcSqSfLfzMeH2ll8SFZQnOk8VN/b3bq6XrBCbrfrSsTYYWakN6mmfalLJcQRm4jCEc6gcyuGO4i6Q==
|
integrity sha512-S5uFv9sFAVYSO80/K4HZsJL9L2Bs51IxCqR0a2Lk4NdKr9Fpzp6txwuALSJzM1bIpohtqbjmgut49o95wg30ZA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/core-utils" "7.8.3"
|
"@electron-forge/core-utils" "7.9.0"
|
||||||
"@electron-forge/maker-base" "7.8.3"
|
"@electron-forge/maker-base" "7.9.0"
|
||||||
"@electron-forge/plugin-base" "7.8.3"
|
"@electron-forge/plugin-base" "7.9.0"
|
||||||
"@electron-forge/publisher-base" "7.8.3"
|
"@electron-forge/publisher-base" "7.9.0"
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
"@electron-forge/template-base" "7.8.3"
|
"@electron-forge/template-base" "7.9.0"
|
||||||
"@electron-forge/template-vite" "7.8.3"
|
"@electron-forge/template-vite" "7.9.0"
|
||||||
"@electron-forge/template-vite-typescript" "7.8.3"
|
"@electron-forge/template-vite-typescript" "7.9.0"
|
||||||
"@electron-forge/template-webpack" "7.8.3"
|
"@electron-forge/template-webpack" "7.9.0"
|
||||||
"@electron-forge/template-webpack-typescript" "7.8.3"
|
"@electron-forge/template-webpack-typescript" "7.9.0"
|
||||||
"@electron-forge/tracer" "7.8.3"
|
"@electron-forge/tracer" "7.9.0"
|
||||||
"@electron/get" "^3.0.0"
|
"@electron/get" "^3.0.0"
|
||||||
"@electron/packager" "^18.3.5"
|
"@electron/packager" "^18.3.5"
|
||||||
"@electron/rebuild" "^3.7.0"
|
"@electron/rebuild" "^3.7.0"
|
||||||
"@malept/cross-spawn-promise" "^2.0.0"
|
"@malept/cross-spawn-promise" "^2.0.0"
|
||||||
|
"@vscode/sudo-prompt" "^9.3.1"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
debug "^4.3.1"
|
debug "^4.3.1"
|
||||||
fast-glob "^3.2.7"
|
fast-glob "^3.2.7"
|
||||||
@@ -76,60 +79,59 @@
|
|||||||
rechoir "^0.8.0"
|
rechoir "^0.8.0"
|
||||||
semver "^7.2.1"
|
semver "^7.2.1"
|
||||||
source-map-support "^0.5.13"
|
source-map-support "^0.5.13"
|
||||||
sudo-prompt "^9.1.1"
|
|
||||||
username "^5.1.0"
|
username "^5.1.0"
|
||||||
|
|
||||||
"@electron-forge/maker-base@7.8.3":
|
"@electron-forge/maker-base@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-base/-/maker-base-7.8.3.tgz#e500ebe3eacfa84d3f02faac2aa3b2773c27250a"
|
resolved "https://registry.yarnpkg.com/@electron-forge/maker-base/-/maker-base-7.9.0.tgz#0bcdac4573f88ba493beb2c42b382fc6f010f095"
|
||||||
integrity sha512-WmF66cHdziaK8Asi7IRTLxZjCZ8IqXXHr6IPl4d5oatN6s5RG+HHzG1hiJ7LzlOEntqdSpE8Wh2nB2TmyR4huQ==
|
integrity sha512-u0jo2kaYRxh/Rai6DyFSGJcNLRVWxiKaGUjMhX1LrKolufUkCxxR4TEmv4Hvl03WTr9pQb06umlIrVMaNb+j9A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
fs-extra "^10.0.0"
|
fs-extra "^10.0.0"
|
||||||
which "^2.0.2"
|
which "^2.0.2"
|
||||||
|
|
||||||
"@electron-forge/maker-deb@^7.8.3":
|
"@electron-forge/maker-deb@^7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-deb/-/maker-deb-7.8.3.tgz#940427f406a107eca6bc80029c62d259833f9b9b"
|
resolved "https://registry.yarnpkg.com/@electron-forge/maker-deb/-/maker-deb-7.9.0.tgz#6309d8e6b78010a32a55f2eb51a5e952f233b7e3"
|
||||||
integrity sha512-GZHJU06LRFJkv1wMc3bjMVzedQhyxnyMZqgDJjE9TIlXXZkN2EqGmKLw/HxwNRA1R8yuQeA4Ih6/dEB4bZTevg==
|
integrity sha512-b1TRMKkeuZ2PTKVsTMWLY+82O6UQVPQ17x5hkWe0lyIxRyCfJr6hD+AqYbvEJ50ncDkvyCtENBT6GnhfbKOGxA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/maker-base" "7.8.3"
|
"@electron-forge/maker-base" "7.9.0"
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
electron-installer-debian "^3.2.0"
|
electron-installer-debian "^3.2.0"
|
||||||
|
|
||||||
"@electron-forge/maker-zip@^7.8.3":
|
"@electron-forge/maker-zip@^7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-zip/-/maker-zip-7.8.3.tgz#450b17d6517633bbdeb82397600db61abd8461d6"
|
resolved "https://registry.yarnpkg.com/@electron-forge/maker-zip/-/maker-zip-7.9.0.tgz#bf198f8b6316649f33f83d77ae539c904136636f"
|
||||||
integrity sha512-ytao285wKAjKBO6eULzLeqUDP5Zh7beQlGyHjgOMknk7FI0sNy+zGdh3CrCGIhkXSHU/DpukPwRu2SiKvIaIGA==
|
integrity sha512-UGeziReiz8yuDTjliOjvbdyulIHpKAWkDeW3kOcMTUmRcCgrCkBNr+Pp6ih8Q3aBhG+CCd4++oe2rDnnuVvxFw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/maker-base" "7.8.3"
|
"@electron-forge/maker-base" "7.9.0"
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
cross-zip "^4.0.0"
|
cross-zip "^4.0.0"
|
||||||
fs-extra "^10.0.0"
|
fs-extra "^10.0.0"
|
||||||
got "^11.8.5"
|
got "^11.8.5"
|
||||||
|
|
||||||
"@electron-forge/plugin-base@7.8.3":
|
"@electron-forge/plugin-base@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/plugin-base/-/plugin-base-7.8.3.tgz#2def4cf41aca2f63c3486e651487571efafc284b"
|
resolved "https://registry.yarnpkg.com/@electron-forge/plugin-base/-/plugin-base-7.9.0.tgz#a39f0e0a9e406686f298e0595ee514091e6144f9"
|
||||||
integrity sha512-0CzPQlO3BGu5bLCrx2Xqo6B1yoHhA9wG9boZE58ANr8Qma1NQfAWZU3LnMmF3EdWNTX76PxpZeeb3QbPNcxSuA==
|
integrity sha512-2cnShgfes0sqH7A3+54fWhfJEfU++1OC2HE50a4sWtWEDwyWLGbwW7tp9BgSXrvIexO2AGKHQ1pKIjpZYVC0fA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
|
|
||||||
"@electron-forge/publisher-base@7.8.3":
|
"@electron-forge/publisher-base@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/publisher-base/-/publisher-base-7.8.3.tgz#a90ef4532e2a319c2ee44de741dd1968b5b42735"
|
resolved "https://registry.yarnpkg.com/@electron-forge/publisher-base/-/publisher-base-7.9.0.tgz#f129cc24d916c27adbee35f5cdf868172b5cc263"
|
||||||
integrity sha512-kurRKVNyLsK2JgmVl88UHu0+qSH+PysMtk/xP0YX5sYNMVxRay8+S1T10tAh6Qom94KwpF3CLYtkebvxb/fq+A==
|
integrity sha512-z3eH4+C++LiDqlKmri04IbSNNWLRYLvc49uNiOgfvnejplLsos720TTbwgruyI3D2fbpmhrVmz9kp9H9YzXdVg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
|
|
||||||
"@electron-forge/publisher-github@^7.8.3":
|
"@electron-forge/publisher-github@^7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/publisher-github/-/publisher-github-7.8.3.tgz#45e51d7d91e63e8c7872217e3b5d16111fd8a3e7"
|
resolved "https://registry.yarnpkg.com/@electron-forge/publisher-github/-/publisher-github-7.9.0.tgz#759f44a7cbc8c7fcd524ccc5cc57a99f9ad3a4fc"
|
||||||
integrity sha512-hFZMDAWXkNrvJA/dA64m2+uLVz1cVyMbX94YXqu9zbW6sMWJzT96om1Gr+c1CnK+mmj5E/ZqVu0846Rq+rcfEQ==
|
integrity sha512-kJzRLRaYmRa9D0e/PCnnhDChWhs3nipYgx3b4QFDVUFmbQ1ytBCmZnCO2vH0NXr7HZE3ozcAHm+Zw0TvEpXmeA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/publisher-base" "7.8.3"
|
"@electron-forge/publisher-base" "7.9.0"
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
"@octokit/core" "^5.2.1"
|
"@octokit/core" "^5.2.1"
|
||||||
"@octokit/plugin-retry" "^6.1.0"
|
"@octokit/plugin-retry" "^6.1.0"
|
||||||
"@octokit/request-error" "^5.1.1"
|
"@octokit/request-error" "^5.1.1"
|
||||||
@@ -141,68 +143,69 @@
|
|||||||
log-symbols "^4.0.0"
|
log-symbols "^4.0.0"
|
||||||
mime-types "^2.1.25"
|
mime-types "^2.1.25"
|
||||||
|
|
||||||
"@electron-forge/shared-types@7.8.3":
|
"@electron-forge/shared-types@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/shared-types/-/shared-types-7.8.3.tgz#0b7c54b3fa09bfdc931e22d254b70f1685744fde"
|
resolved "https://registry.yarnpkg.com/@electron-forge/shared-types/-/shared-types-7.9.0.tgz#ac3dd22da586957fcd6fb1c035155bd65bf2ffd3"
|
||||||
integrity sha512-gkZtD7ALXHPDOthJo1rQYLDNfG09fdDRMWvjEgaXdF3Z69xXFfnOWPNuOkRUODNalMnuuGs6l7jDl+QFQgHlDg==
|
integrity sha512-6jZF+zq3SYMnweQpgr5fwlSgOd2yOZ5qlfz/CgXyVljiv0e0UThzpOjfTLuwuVgZX7a60xV+h0mg1h82Glu3wQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/tracer" "7.8.3"
|
"@electron-forge/tracer" "7.9.0"
|
||||||
"@electron/packager" "^18.3.5"
|
"@electron/packager" "^18.3.5"
|
||||||
"@electron/rebuild" "^3.7.0"
|
"@electron/rebuild" "^3.7.0"
|
||||||
listr2 "^7.0.2"
|
listr2 "^7.0.2"
|
||||||
|
|
||||||
"@electron-forge/template-base@7.8.3":
|
"@electron-forge/template-base@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-base/-/template-base-7.8.3.tgz#009ba783b3e214fb8a0ed23386cc2ff7c514f796"
|
resolved "https://registry.yarnpkg.com/@electron-forge/template-base/-/template-base-7.9.0.tgz#1716913b7485f61a8a1ec73132b9e91c7cfb1ea4"
|
||||||
integrity sha512-C0tVODDNKoqhCf7T1HRONJs9DKAmjmk8Of0t8rVjT0ERDzMvLGlBByd785v5lFlKbGERyoaXsYltxPAu92G3aA==
|
integrity sha512-DvXdJHh4qP+LBX6xNBlO0nfljvJNTmiQNfLRfSouRdYCWbr5hC7wyWAX803HqwRsVLRZj2oiLYZjmyG3jESp8Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/core-utils" "7.8.3"
|
"@electron-forge/core-utils" "7.9.0"
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
"@malept/cross-spawn-promise" "^2.0.0"
|
"@malept/cross-spawn-promise" "^2.0.0"
|
||||||
debug "^4.3.1"
|
debug "^4.3.1"
|
||||||
fs-extra "^10.0.0"
|
fs-extra "^10.0.0"
|
||||||
|
semver "^7.2.1"
|
||||||
username "^5.1.0"
|
username "^5.1.0"
|
||||||
|
|
||||||
"@electron-forge/template-vite-typescript@7.8.3":
|
"@electron-forge/template-vite-typescript@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.8.3.tgz#57194eb6faa4e154118b4ac49ae6091f784eb0d3"
|
resolved "https://registry.yarnpkg.com/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.9.0.tgz#1c5cedc3392e1dc2fdec2eec4549b0dea06d1d27"
|
||||||
integrity sha512-HJjjY9xmlpl0vx10mrXdWn2RYHExfazACxmDNNmGO1eq3eqrQk/3R+NDGyqMJ7ajBsRVbkQNt+wayH7HkRJUjA==
|
integrity sha512-qGK649YnC3iOVrj/hHUu/TXG7Nn/a7QykEOPrCrxROWL7mtw8CMUE+FOVETd+eew7/4ldUNzl+5b9ebP8jHOmg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
"@electron-forge/template-base" "7.8.3"
|
"@electron-forge/template-base" "7.9.0"
|
||||||
fs-extra "^10.0.0"
|
fs-extra "^10.0.0"
|
||||||
|
|
||||||
"@electron-forge/template-vite@7.8.3":
|
"@electron-forge/template-vite@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-vite/-/template-vite-7.8.3.tgz#ecc651c9641747b71becc740522ef0cf15c28bf5"
|
resolved "https://registry.yarnpkg.com/@electron-forge/template-vite/-/template-vite-7.9.0.tgz#0233840a305280efbecf8d8a4930a6f031594895"
|
||||||
integrity sha512-tDL5h+UO5iOzdEYNVsSu4zkUVN4RTxti5iXzcBquKd9Kgt/A/M7xHeuKj7g1Ds7Ul/n2XcFvcfgLcRmiXQeVDA==
|
integrity sha512-m8Fi40XaF7YDJo7YqmfJbkjRRsttN9EEHkmq+McLrDUbln15Ppm59RAwUhizDQzs4enmLcNQPaFllbAg/2t8vQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
"@electron-forge/template-base" "7.8.3"
|
"@electron-forge/template-base" "7.9.0"
|
||||||
fs-extra "^10.0.0"
|
fs-extra "^10.0.0"
|
||||||
|
|
||||||
"@electron-forge/template-webpack-typescript@7.8.3":
|
"@electron-forge/template-webpack-typescript@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.8.3.tgz#f79276aa60463a8cc45c85e17bec9c42779ac12b"
|
resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.9.0.tgz#ea4d31626d7790960857d119a3f1687bcbb69ada"
|
||||||
integrity sha512-Xz3X7YJvot08Xm+0BLIS28GJH+0z9vEN9xYX76SOL4jqDcHH8lRFpNWcE2HsxxxRbCVH+s0etVmACZcWoujUrw==
|
integrity sha512-z7PB72sI11LBSPz9w9nwwk0le/lZ3VT8TrLc0NYh4F4LbZ19Z+lxcraaAdf21efvWzodhWx8khAyA8WvkNxVSw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
"@electron-forge/template-base" "7.8.3"
|
"@electron-forge/template-base" "7.9.0"
|
||||||
fs-extra "^10.0.0"
|
fs-extra "^10.0.0"
|
||||||
|
|
||||||
"@electron-forge/template-webpack@7.8.3":
|
"@electron-forge/template-webpack@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack/-/template-webpack-7.8.3.tgz#b82b47e8b5e3b2716a0afe4fa1c263b46b4c5271"
|
resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack/-/template-webpack-7.9.0.tgz#2e48610cf28508c13f5b7adb64e743590df267bc"
|
||||||
integrity sha512-1zkji5px1kDXbigFN5959anCf3HAVBvam3bHh2VejnCScegLQP3JBjAn2Nw2ILWq6ej5JNuA/V99b1dr11hPOw==
|
integrity sha512-ser22QczYGor7N6bnMUwexdWbLMNApr6zpBoT+Xfn6P4Ks67ttzcfkAges7GXHNjXwox4ePYZ3+D7cWQem5C4g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron-forge/shared-types" "7.8.3"
|
"@electron-forge/shared-types" "7.9.0"
|
||||||
"@electron-forge/template-base" "7.8.3"
|
"@electron-forge/template-base" "7.9.0"
|
||||||
fs-extra "^10.0.0"
|
fs-extra "^10.0.0"
|
||||||
|
|
||||||
"@electron-forge/tracer@7.8.3":
|
"@electron-forge/tracer@7.9.0":
|
||||||
version "7.8.3"
|
version "7.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron-forge/tracer/-/tracer-7.8.3.tgz#c2c27fb9b2bd770b39f02bc3ae6e254064421af6"
|
resolved "https://registry.yarnpkg.com/@electron-forge/tracer/-/tracer-7.9.0.tgz#a512ea5e0c4564ace978546b50e8ec1aa150fa68"
|
||||||
integrity sha512-YVVDaPEUOvR1z+DDdj8wR/vO9OSlC91wz4/2Iqe9rqQz8sztnnQBClMAZTqu9bkDTFyHrns8j8v7tPVuVS6ULQ==
|
integrity sha512-7itsjW1WJQADg7Ly61ggI5CCRt+QDVx3HOZC1w69jMUtnipKyPRCbvTBf1oplsNqbIzZxceXdfex6W53YNehvA==
|
||||||
dependencies:
|
dependencies:
|
||||||
chrome-trace-event "^1.0.3"
|
chrome-trace-event "^1.0.3"
|
||||||
|
|
||||||
@@ -357,6 +360,158 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
|
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
|
||||||
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
|
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
|
||||||
|
|
||||||
|
"@inquirer/checkbox@^3.0.1":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-3.0.1.tgz#0a57f704265f78c36e17f07e421b98efb4b9867b"
|
||||||
|
integrity sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/core" "^9.2.1"
|
||||||
|
"@inquirer/figures" "^1.0.6"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
ansi-escapes "^4.3.2"
|
||||||
|
yoctocolors-cjs "^2.1.2"
|
||||||
|
|
||||||
|
"@inquirer/confirm@^4.0.1":
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-4.0.1.tgz#9106d6bffa0b2fdd0e4f60319b6f04f2e06e6e25"
|
||||||
|
integrity sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/core" "^9.2.1"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
|
||||||
|
"@inquirer/core@^9.2.1":
|
||||||
|
version "9.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-9.2.1.tgz#677c49dee399c9063f31e0c93f0f37bddc67add1"
|
||||||
|
integrity sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/figures" "^1.0.6"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
"@types/mute-stream" "^0.0.4"
|
||||||
|
"@types/node" "^22.5.5"
|
||||||
|
"@types/wrap-ansi" "^3.0.0"
|
||||||
|
ansi-escapes "^4.3.2"
|
||||||
|
cli-width "^4.1.0"
|
||||||
|
mute-stream "^1.0.0"
|
||||||
|
signal-exit "^4.1.0"
|
||||||
|
strip-ansi "^6.0.1"
|
||||||
|
wrap-ansi "^6.2.0"
|
||||||
|
yoctocolors-cjs "^2.1.2"
|
||||||
|
|
||||||
|
"@inquirer/editor@^3.0.1":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-3.0.1.tgz#d109f21e050af6b960725388cb1c04214ed7c7bc"
|
||||||
|
integrity sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/core" "^9.2.1"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
external-editor "^3.1.0"
|
||||||
|
|
||||||
|
"@inquirer/expand@^3.0.1":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-3.0.1.tgz#aed9183cac4d12811be47a4a895ea8e82a17e22c"
|
||||||
|
integrity sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/core" "^9.2.1"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
yoctocolors-cjs "^2.1.2"
|
||||||
|
|
||||||
|
"@inquirer/figures@^1.0.6":
|
||||||
|
version "1.0.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.13.tgz#ad0afd62baab1c23175115a9b62f511b6a751e45"
|
||||||
|
integrity sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw==
|
||||||
|
|
||||||
|
"@inquirer/input@^3.0.1":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-3.0.1.tgz#de63d49e516487388508d42049deb70f2cb5f28e"
|
||||||
|
integrity sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/core" "^9.2.1"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
|
||||||
|
"@inquirer/number@^2.0.1":
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-2.0.1.tgz#b9863080d02ab7dc2e56e16433d83abea0f2a980"
|
||||||
|
integrity sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/core" "^9.2.1"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
|
||||||
|
"@inquirer/password@^3.0.1":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-3.0.1.tgz#2a9a9143591088336bbd573bcb05d5bf080dbf87"
|
||||||
|
integrity sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/core" "^9.2.1"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
ansi-escapes "^4.3.2"
|
||||||
|
|
||||||
|
"@inquirer/prompts@^6.0.1":
|
||||||
|
version "6.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-6.0.1.tgz#43f5c0ed35c5ebfe52f1d43d46da2d363d950071"
|
||||||
|
integrity sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/checkbox" "^3.0.1"
|
||||||
|
"@inquirer/confirm" "^4.0.1"
|
||||||
|
"@inquirer/editor" "^3.0.1"
|
||||||
|
"@inquirer/expand" "^3.0.1"
|
||||||
|
"@inquirer/input" "^3.0.1"
|
||||||
|
"@inquirer/number" "^2.0.1"
|
||||||
|
"@inquirer/password" "^3.0.1"
|
||||||
|
"@inquirer/rawlist" "^3.0.1"
|
||||||
|
"@inquirer/search" "^2.0.1"
|
||||||
|
"@inquirer/select" "^3.0.1"
|
||||||
|
|
||||||
|
"@inquirer/rawlist@^3.0.1":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-3.0.1.tgz#729def358419cc929045f264131878ed379e0af3"
|
||||||
|
integrity sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/core" "^9.2.1"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
yoctocolors-cjs "^2.1.2"
|
||||||
|
|
||||||
|
"@inquirer/search@^2.0.1":
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-2.0.1.tgz#69b774a0a826de2e27b48981d01bc5ad81e73721"
|
||||||
|
integrity sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/core" "^9.2.1"
|
||||||
|
"@inquirer/figures" "^1.0.6"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
yoctocolors-cjs "^2.1.2"
|
||||||
|
|
||||||
|
"@inquirer/select@^3.0.1":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-3.0.1.tgz#1df9ed27fb85a5f526d559ac5ce7cc4e9dc4e7ec"
|
||||||
|
integrity sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/core" "^9.2.1"
|
||||||
|
"@inquirer/figures" "^1.0.6"
|
||||||
|
"@inquirer/type" "^2.0.0"
|
||||||
|
ansi-escapes "^4.3.2"
|
||||||
|
yoctocolors-cjs "^2.1.2"
|
||||||
|
|
||||||
|
"@inquirer/type@^1.5.5":
|
||||||
|
version "1.5.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.5.5.tgz#303ea04ce7ad2e585b921b662b3be36ef7b4f09b"
|
||||||
|
integrity sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==
|
||||||
|
dependencies:
|
||||||
|
mute-stream "^1.0.0"
|
||||||
|
|
||||||
|
"@inquirer/type@^2.0.0":
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-2.0.0.tgz#08fa513dca2cb6264fe1b0a2fabade051444e3f6"
|
||||||
|
integrity sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==
|
||||||
|
dependencies:
|
||||||
|
mute-stream "^1.0.0"
|
||||||
|
|
||||||
|
"@listr2/prompt-adapter-inquirer@^2.0.22":
|
||||||
|
version "2.0.22"
|
||||||
|
resolved "https://registry.yarnpkg.com/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.22.tgz#95f7730de62089be79a87a80aa333f5f4644f3c5"
|
||||||
|
integrity sha512-hV36ZoY+xKL6pYOt1nPNnkciFkn89KZwqLhAFzJvYysAvL5uBQdiADZx/8bIDXIukzzwG0QlPYolgMzQUtKgpQ==
|
||||||
|
dependencies:
|
||||||
|
"@inquirer/type" "^1.5.5"
|
||||||
|
|
||||||
"@malept/cross-spawn-promise@^1.0.0":
|
"@malept/cross-spawn-promise@^1.0.0":
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d"
|
resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d"
|
||||||
@@ -570,17 +725,24 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/mute-stream@^0.0.4":
|
||||||
version "24.3.0"
|
version "0.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-24.3.0.tgz#89b09f45cb9a8ee69466f18ee5864e4c3eb84dec"
|
resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478"
|
||||||
integrity sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==
|
integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~7.10.0"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/node@^22.7.7":
|
"@types/node@*":
|
||||||
version "22.18.0"
|
version "24.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.18.0.tgz#9e4709be4f104e3568f7dd1c71e2949bf147a47b"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-24.5.2.tgz#52ceb83f50fe0fcfdfbd2a9fab6db2e9e7ef6446"
|
||||||
integrity sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==
|
integrity sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==
|
||||||
|
dependencies:
|
||||||
|
undici-types "~7.12.0"
|
||||||
|
|
||||||
|
"@types/node@^22.5.5", "@types/node@^22.7.7":
|
||||||
|
version "22.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.18.6.tgz#38172ef0b65e09d1a4fc715eb09a7d5decfdc748"
|
||||||
|
integrity sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~6.21.0"
|
undici-types "~6.21.0"
|
||||||
|
|
||||||
@@ -598,6 +760,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/wrap-ansi@^3.0.0":
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd"
|
||||||
|
integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==
|
||||||
|
|
||||||
"@types/ws@^8.18.1":
|
"@types/ws@^8.18.1":
|
||||||
version "8.18.1"
|
version "8.18.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9"
|
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9"
|
||||||
@@ -612,6 +779,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@vscode/sudo-prompt@^9.3.1":
|
||||||
|
version "9.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vscode/sudo-prompt/-/sudo-prompt-9.3.1.tgz#c562334bc6647733649fd42afc96c0eea8de3b65"
|
||||||
|
integrity sha512-9ORTwwS74VaTn38tNbQhsA5U44zkJfcb0BdTSyyG6frP4e8KMtHuTXYmwefe5dpL8XB1aGSIVTaLjD3BbWb5iA==
|
||||||
|
|
||||||
"@xmldom/xmldom@^0.8.8":
|
"@xmldom/xmldom@^0.8.8":
|
||||||
version "0.8.11"
|
version "0.8.11"
|
||||||
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.11.tgz#b79de2d67389734c57c52595f7a7305e30c2d608"
|
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.11.tgz#b79de2d67389734c57c52595f7a7305e30c2d608"
|
||||||
@@ -651,6 +823,13 @@ aggregate-error@^3.0.0:
|
|||||||
clean-stack "^2.0.0"
|
clean-stack "^2.0.0"
|
||||||
indent-string "^4.0.0"
|
indent-string "^4.0.0"
|
||||||
|
|
||||||
|
ansi-escapes@^4.3.2:
|
||||||
|
version "4.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
|
||||||
|
integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
|
||||||
|
dependencies:
|
||||||
|
type-fest "^0.21.3"
|
||||||
|
|
||||||
ansi-escapes@^5.0.0:
|
ansi-escapes@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz#b6a0caf0eef0c41af190e9a749e0c00ec04bb2a6"
|
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz#b6a0caf0eef0c41af190e9a749e0c00ec04bb2a6"
|
||||||
@@ -664,9 +843,9 @@ ansi-regex@^5.0.1:
|
|||||||
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||||
|
|
||||||
ansi-regex@^6.0.1:
|
ansi-regex@^6.0.1:
|
||||||
version "6.2.0"
|
version "6.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.0.tgz#2f302e7550431b1b7762705fffb52cf1ffa20447"
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1"
|
||||||
integrity sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==
|
integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==
|
||||||
|
|
||||||
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
@@ -676,9 +855,9 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
|||||||
color-convert "^2.0.1"
|
color-convert "^2.0.1"
|
||||||
|
|
||||||
ansi-styles@^6.0.0, ansi-styles@^6.1.0:
|
ansi-styles@^6.0.0, ansi-styles@^6.1.0:
|
||||||
version "6.2.1"
|
version "6.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
|
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041"
|
||||||
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
|
integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==
|
||||||
|
|
||||||
asynckit@^0.4.0:
|
asynckit@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
@@ -695,10 +874,10 @@ author-regex@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/author-regex/-/author-regex-1.0.0.tgz#d08885be6b9bbf9439fe087c76287245f0a81450"
|
resolved "https://registry.yarnpkg.com/author-regex/-/author-regex-1.0.0.tgz#d08885be6b9bbf9439fe087c76287245f0a81450"
|
||||||
integrity sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==
|
integrity sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==
|
||||||
|
|
||||||
axios@^1.11.0:
|
axios@^1.12.2:
|
||||||
version "1.11.0"
|
version "1.12.2"
|
||||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.11.0.tgz#c2ec219e35e414c025b2095e8b8280278478fdb6"
|
resolved "https://registry.yarnpkg.com/axios/-/axios-1.12.2.tgz#6c307390136cf7a2278d09cec63b136dfc6e6da7"
|
||||||
integrity sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==
|
integrity sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "^1.15.6"
|
follow-redirects "^1.15.6"
|
||||||
form-data "^4.0.4"
|
form-data "^4.0.4"
|
||||||
@@ -729,9 +908,9 @@ bl@^4.1.0:
|
|||||||
readable-stream "^3.4.0"
|
readable-stream "^3.4.0"
|
||||||
|
|
||||||
bl@^6.0.8:
|
bl@^6.0.8:
|
||||||
version "6.1.2"
|
version "6.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/bl/-/bl-6.1.2.tgz#fd4274e73c24f4c34ada6d69a612ec924f3df345"
|
resolved "https://registry.yarnpkg.com/bl/-/bl-6.1.3.tgz#158ac572ee2a3446884585ddd02d02b4c5d122bf"
|
||||||
integrity sha512-6J3oG82fpJ71WF4l0W6XslkwAPMr+Zcp+AmdxJ0L8LsXNzFeO8GYesV2J9AzGArBjrsb2xR50Ocbn/CL1B44TA==
|
integrity sha512-nHB8B5roHlGX5TFsWeiQJijdddZIOHuv1eL2cM2kHnG3qR91CYLsysGe+CvxQfEd23EKD0eJf4lto0frTbddKA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/readable-stream" "^4.0.0"
|
"@types/readable-stream" "^4.0.0"
|
||||||
buffer "^6.0.3"
|
buffer "^6.0.3"
|
||||||
@@ -869,6 +1048,11 @@ chalk@^4.0.0, chalk@^4.1.0:
|
|||||||
ansi-styles "^4.1.0"
|
ansi-styles "^4.1.0"
|
||||||
supports-color "^7.1.0"
|
supports-color "^7.1.0"
|
||||||
|
|
||||||
|
chardet@^0.7.0:
|
||||||
|
version "0.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||||
|
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
|
||||||
|
|
||||||
chownr@^2.0.0:
|
chownr@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
|
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
|
||||||
@@ -911,6 +1095,11 @@ cli-truncate@^3.1.0:
|
|||||||
slice-ansi "^5.0.0"
|
slice-ansi "^5.0.0"
|
||||||
string-width "^5.0.0"
|
string-width "^5.0.0"
|
||||||
|
|
||||||
|
cli-width@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5"
|
||||||
|
integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==
|
||||||
|
|
||||||
cliui@^7.0.2:
|
cliui@^7.0.2:
|
||||||
version "7.0.4"
|
version "7.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
||||||
@@ -1005,6 +1194,11 @@ concat-stream@^2.0.0:
|
|||||||
readable-stream "^3.0.2"
|
readable-stream "^3.0.2"
|
||||||
typedarray "^0.0.6"
|
typedarray "^0.0.6"
|
||||||
|
|
||||||
|
core-util-is@~1.0.0:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
|
||||||
|
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
|
||||||
|
|
||||||
cross-dirname@^0.1.0:
|
cross-dirname@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/cross-dirname/-/cross-dirname-0.1.0.tgz#b899599f30a5389f59e78c150e19f957ad16a37c"
|
resolved "https://registry.yarnpkg.com/cross-dirname/-/cross-dirname-0.1.0.tgz#b899599f30a5389f59e78c150e19f957ad16a37c"
|
||||||
@@ -1036,9 +1230,9 @@ cross-zip@^4.0.0:
|
|||||||
integrity sha512-n63i0lZ0rvQ6FXiGQ+/JFCKAUyPFhLQYJIqKaa+tSJtfKeULF/IDNDAbdnSIxgS4NTuw2b0+lj8LzfITuq+ZxQ==
|
integrity sha512-n63i0lZ0rvQ6FXiGQ+/JFCKAUyPFhLQYJIqKaa+tSJtfKeULF/IDNDAbdnSIxgS4NTuw2b0+lj8LzfITuq+ZxQ==
|
||||||
|
|
||||||
debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4, debug@^4.4.1:
|
debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4, debug@^4.4.1:
|
||||||
version "4.4.1"
|
version "4.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a"
|
||||||
integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
|
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
|
||||||
dependencies:
|
dependencies:
|
||||||
ms "^2.1.3"
|
ms "^2.1.3"
|
||||||
|
|
||||||
@@ -1097,9 +1291,9 @@ deprecation@^2.0.0:
|
|||||||
integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
|
integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
|
||||||
|
|
||||||
detect-libc@^2.0.1:
|
detect-libc@^2.0.1:
|
||||||
version "2.0.4"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.4.tgz#f04715b8ba815e53b4d8109655b6508a6865a7e8"
|
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.0.tgz#3ca811f60a7b504b0480e5008adacc660b0b8c4f"
|
||||||
integrity sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==
|
integrity sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==
|
||||||
|
|
||||||
detect-node@^2.0.4:
|
detect-node@^2.0.4:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
@@ -1159,10 +1353,15 @@ electron-installer-debian@^3.2.0:
|
|||||||
word-wrap "^1.2.3"
|
word-wrap "^1.2.3"
|
||||||
yargs "^16.0.2"
|
yargs "^16.0.2"
|
||||||
|
|
||||||
electron@^37.4.0:
|
electron-log@^5.4.3:
|
||||||
version "37.4.0"
|
version "5.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/electron/-/electron-37.4.0.tgz#08b2eff9d6250fac7b298f17f93946ecd586f38e"
|
resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-5.4.3.tgz#02a90baf4256950ca416095db6e5745268584d20"
|
||||||
integrity sha512-HhsSdWowE5ODOeWNc/323Ug2C52mq/TqNBG+4uMeOA3G2dMXNc/nfyi0RYu1rJEgiaJLEjtHveeZZaYRYFsFCQ==
|
integrity sha512-sOUsM3LjZdugatazSQ/XTyNcw8dfvH1SYhXWiJyfYodAAKOZdHs0txPiLDXFzOZbhXgAgshQkshH2ccq0feyLQ==
|
||||||
|
|
||||||
|
electron@^38.1.2:
|
||||||
|
version "38.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/electron/-/electron-38.1.2.tgz#3509999a1b635fb92e99a8e5eaf239110a9a7734"
|
||||||
|
integrity sha512-WXUcN3W8h8NTTZViA3KNX0rV2YBU0X0mEUM3ubupXTDY4QtIN7tmiqYVOKSKpR2LckTmBWGuEeY4D6xVoffwKQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron/get" "^2.0.0"
|
"@electron/get" "^2.0.0"
|
||||||
"@types/node" "^22.7.7"
|
"@types/node" "^22.7.7"
|
||||||
@@ -1203,9 +1402,9 @@ err-code@^2.0.2:
|
|||||||
integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
|
integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
|
||||||
|
|
||||||
error-ex@^1.2.0:
|
error-ex@^1.2.0:
|
||||||
version "1.3.2"
|
version "1.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414"
|
||||||
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
|
integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.2.1"
|
is-arrayish "^0.2.1"
|
||||||
|
|
||||||
@@ -1289,6 +1488,15 @@ exponential-backoff@^3.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.2.tgz#a8f26adb96bf78e8cd8ad1037928d5e5c0679d91"
|
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.2.tgz#a8f26adb96bf78e8cd8ad1037928d5e5c0679d91"
|
||||||
integrity sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==
|
integrity sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==
|
||||||
|
|
||||||
|
external-editor@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
|
||||||
|
integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
|
||||||
|
dependencies:
|
||||||
|
chardet "^0.7.0"
|
||||||
|
iconv-lite "^0.4.24"
|
||||||
|
tmp "^0.0.33"
|
||||||
|
|
||||||
extract-zip@^2.0.0, extract-zip@^2.0.1:
|
extract-zip@^2.0.0, extract-zip@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
|
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
|
||||||
@@ -1403,9 +1611,9 @@ fs-extra@^10.0.0, fs-extra@^10.1.0:
|
|||||||
universalify "^2.0.0"
|
universalify "^2.0.0"
|
||||||
|
|
||||||
fs-extra@^11.1.0, fs-extra@^11.1.1:
|
fs-extra@^11.1.0, fs-extra@^11.1.1:
|
||||||
version "11.3.1"
|
version "11.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.1.tgz#ba7a1f97a85f94c6db2e52ff69570db3671d5a74"
|
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.2.tgz#c838aeddc6f4a8c74dd15f85e11fe5511bfe02a4"
|
||||||
integrity sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==
|
integrity sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==
|
||||||
dependencies:
|
dependencies:
|
||||||
graceful-fs "^4.2.0"
|
graceful-fs "^4.2.0"
|
||||||
jsonfile "^6.0.1"
|
jsonfile "^6.0.1"
|
||||||
@@ -1684,6 +1892,13 @@ humanize-ms@^1.2.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms "^2.0.0"
|
ms "^2.0.0"
|
||||||
|
|
||||||
|
iconv-lite@^0.4.24:
|
||||||
|
version "0.4.24"
|
||||||
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||||
|
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||||
|
dependencies:
|
||||||
|
safer-buffer ">= 2.1.2 < 3"
|
||||||
|
|
||||||
iconv-lite@^0.6.2:
|
iconv-lite@^0.6.2:
|
||||||
version "0.6.3"
|
version "0.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
||||||
@@ -1696,6 +1911,11 @@ ieee754@^1.1.13, ieee754@^1.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||||
|
|
||||||
|
immediate@~3.0.5:
|
||||||
|
version "3.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||||
|
integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==
|
||||||
|
|
||||||
imurmurhash@^0.1.4:
|
imurmurhash@^0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||||
@@ -1719,7 +1939,7 @@ inflight@^1.0.4:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@2, inherits@^2.0.3, inherits@^2.0.4:
|
inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
@@ -1798,6 +2018,11 @@ is-unicode-supported@^0.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
|
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
|
||||||
integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
|
integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
|
||||||
|
|
||||||
|
isarray@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||||
|
integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
|
||||||
|
|
||||||
isbinaryfile@^4.0.8:
|
isbinaryfile@^4.0.8:
|
||||||
version "4.0.10"
|
version "4.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3"
|
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3"
|
||||||
@@ -1844,6 +2069,16 @@ jsonfile@^6.0.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
graceful-fs "^4.1.6"
|
graceful-fs "^4.1.6"
|
||||||
|
|
||||||
|
jszip@^3.10.1:
|
||||||
|
version "3.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2"
|
||||||
|
integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==
|
||||||
|
dependencies:
|
||||||
|
lie "~3.3.0"
|
||||||
|
pako "~1.0.2"
|
||||||
|
readable-stream "~2.3.6"
|
||||||
|
setimmediate "^1.0.5"
|
||||||
|
|
||||||
junk@^3.1.0:
|
junk@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1"
|
resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1"
|
||||||
@@ -1856,6 +2091,13 @@ keyv@^4.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
json-buffer "3.0.1"
|
json-buffer "3.0.1"
|
||||||
|
|
||||||
|
lie@~3.3.0:
|
||||||
|
version "3.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
|
||||||
|
integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
|
||||||
|
dependencies:
|
||||||
|
immediate "~3.0.5"
|
||||||
|
|
||||||
listr2@^7.0.2:
|
listr2@^7.0.2:
|
||||||
version "7.0.2"
|
version "7.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/listr2/-/listr2-7.0.2.tgz#3aa3e1549dfaf3c57ab5eeaba754da3b87f33063"
|
resolved "https://registry.yarnpkg.com/listr2/-/listr2-7.0.2.tgz#3aa3e1549dfaf3c57ab5eeaba754da3b87f33063"
|
||||||
@@ -2126,10 +2368,10 @@ mqtt-packet@^9.0.2:
|
|||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
process-nextick-args "^2.0.1"
|
process-nextick-args "^2.0.1"
|
||||||
|
|
||||||
mqtt@^5.14.0:
|
mqtt@^5.14.1:
|
||||||
version "5.14.0"
|
version "5.14.1"
|
||||||
resolved "https://registry.yarnpkg.com/mqtt/-/mqtt-5.14.0.tgz#eeeb1563884f73cad4fb973449d3973666a4202f"
|
resolved "https://registry.yarnpkg.com/mqtt/-/mqtt-5.14.1.tgz#c65063b2cc9d9336430bde27a337ae98e5b4705a"
|
||||||
integrity sha512-H7EmeCJhbGblbWjm6APF5sAH3SkdI7lxHw/UkblZp8fjSNl8b2MsLcdAkIaQKxvZYmiORkdAjffvKjqQWPkd6w==
|
integrity sha512-NxkPxE70Uq3Ph7goefQa7ggSsVzHrayCD0OyxlJgITN/EbzlZN+JEPmaAZdxP1LsIT5FamDyILoQTF72W7Nnbw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/readable-stream" "^4.0.21"
|
"@types/readable-stream" "^4.0.21"
|
||||||
"@types/ws" "^8.18.1"
|
"@types/ws" "^8.18.1"
|
||||||
@@ -2158,6 +2400,11 @@ ms@^2.0.0, ms@^2.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||||
|
|
||||||
|
mute-stream@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e"
|
||||||
|
integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==
|
||||||
|
|
||||||
negotiator@^0.6.3:
|
negotiator@^0.6.3:
|
||||||
version "0.6.4"
|
version "0.6.4"
|
||||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7"
|
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7"
|
||||||
@@ -2169,9 +2416,9 @@ nice-try@^1.0.4:
|
|||||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||||
|
|
||||||
node-abi@^3.45.0:
|
node-abi@^3.45.0:
|
||||||
version "3.75.0"
|
version "3.77.0"
|
||||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.75.0.tgz#2f929a91a90a0d02b325c43731314802357ed764"
|
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.77.0.tgz#3ad90d5c9d45663420e5aa4ff58dbf4e3625419a"
|
||||||
integrity sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==
|
integrity sha512-DSmt0OEcLoK4i3NuscSbGjOf3bqiDEutejqENSplMSFA/gmB8mkED9G4pKWnPl7MDU4rSHebKPHeitpDfyH0cQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
semver "^7.3.5"
|
semver "^7.3.5"
|
||||||
|
|
||||||
@@ -2260,6 +2507,11 @@ ora@^5.1.0:
|
|||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
wcwidth "^1.0.1"
|
wcwidth "^1.0.1"
|
||||||
|
|
||||||
|
os-tmpdir@~1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||||
|
integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
|
||||||
|
|
||||||
p-cancelable@^2.0.0:
|
p-cancelable@^2.0.0:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
|
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
|
||||||
@@ -2320,6 +2572,11 @@ p-try@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
||||||
integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==
|
integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==
|
||||||
|
|
||||||
|
pako@~1.0.2:
|
||||||
|
version "1.0.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
|
||||||
|
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
|
||||||
|
|
||||||
parse-author@^2.0.0:
|
parse-author@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/parse-author/-/parse-author-2.0.0.tgz#d3460bf1ddd0dfaeed42da754242e65fb684a81f"
|
resolved "https://registry.yarnpkg.com/parse-author/-/parse-author-2.0.0.tgz#d3460bf1ddd0dfaeed42da754242e65fb684a81f"
|
||||||
@@ -2417,7 +2674,7 @@ proc-log@^2.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685"
|
resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685"
|
||||||
integrity sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==
|
integrity sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==
|
||||||
|
|
||||||
process-nextick-args@^2.0.1:
|
process-nextick-args@^2.0.1, process-nextick-args@~2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||||
@@ -2512,6 +2769,19 @@ readable-stream@^4.2.0, readable-stream@^4.7.0:
|
|||||||
process "^0.11.10"
|
process "^0.11.10"
|
||||||
string_decoder "^1.3.0"
|
string_decoder "^1.3.0"
|
||||||
|
|
||||||
|
readable-stream@~2.3.6:
|
||||||
|
version "2.3.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
|
||||||
|
integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
|
||||||
|
dependencies:
|
||||||
|
core-util-is "~1.0.0"
|
||||||
|
inherits "~2.0.3"
|
||||||
|
isarray "~1.0.0"
|
||||||
|
process-nextick-args "~2.0.0"
|
||||||
|
safe-buffer "~5.1.1"
|
||||||
|
string_decoder "~1.1.1"
|
||||||
|
util-deprecate "~1.0.1"
|
||||||
|
|
||||||
rechoir@^0.8.0:
|
rechoir@^0.8.0:
|
||||||
version "0.8.0"
|
version "0.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
|
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
|
||||||
@@ -2609,12 +2879,17 @@ run-parallel@^1.1.9:
|
|||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask "^1.2.2"
|
queue-microtask "^1.2.2"
|
||||||
|
|
||||||
|
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||||
|
version "5.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||||
|
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||||
|
|
||||||
safe-buffer@~5.2.0:
|
safe-buffer@~5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
|
||||||
"safer-buffer@>= 2.1.2 < 3.0.0":
|
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||||
@@ -2646,6 +2921,11 @@ serialize-error@^7.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
type-fest "^0.13.1"
|
type-fest "^0.13.1"
|
||||||
|
|
||||||
|
setimmediate@^1.0.5:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
|
||||||
|
integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
|
||||||
|
|
||||||
shebang-command@^1.2.0:
|
shebang-command@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||||
@@ -2675,6 +2955,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||||
|
|
||||||
|
signal-exit@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
|
||||||
|
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
|
||||||
|
|
||||||
slice-ansi@^5.0.0:
|
slice-ansi@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a"
|
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a"
|
||||||
@@ -2786,6 +3071,13 @@ string_decoder@^1.1.1, string_decoder@^1.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.2.0"
|
safe-buffer "~5.2.0"
|
||||||
|
|
||||||
|
string_decoder@~1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||||
|
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "~5.1.0"
|
||||||
|
|
||||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
@@ -2794,9 +3086,9 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
|||||||
ansi-regex "^5.0.1"
|
ansi-regex "^5.0.1"
|
||||||
|
|
||||||
strip-ansi@^7.0.1:
|
strip-ansi@^7.0.1:
|
||||||
version "7.1.0"
|
version "7.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba"
|
||||||
integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
|
integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex "^6.0.1"
|
ansi-regex "^6.0.1"
|
||||||
|
|
||||||
@@ -2817,11 +3109,6 @@ strip-outer@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
escape-string-regexp "^1.0.2"
|
escape-string-regexp "^1.0.2"
|
||||||
|
|
||||||
sudo-prompt@^9.1.1:
|
|
||||||
version "9.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd"
|
|
||||||
integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==
|
|
||||||
|
|
||||||
sumchecker@^3.0.1:
|
sumchecker@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42"
|
resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42"
|
||||||
@@ -2865,6 +3152,13 @@ tmp-promise@^3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tmp "^0.2.0"
|
tmp "^0.2.0"
|
||||||
|
|
||||||
|
tmp@^0.0.33:
|
||||||
|
version "0.0.33"
|
||||||
|
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||||
|
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
|
||||||
|
dependencies:
|
||||||
|
os-tmpdir "~1.0.2"
|
||||||
|
|
||||||
tmp@^0.2.0:
|
tmp@^0.2.0:
|
||||||
version "0.2.5"
|
version "0.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.5.tgz#b06bcd23f0f3c8357b426891726d16015abfd8f8"
|
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.5.tgz#b06bcd23f0f3c8357b426891726d16015abfd8f8"
|
||||||
@@ -2899,6 +3193,11 @@ type-fest@^0.13.1:
|
|||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
|
||||||
integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
|
integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
|
||||||
|
|
||||||
|
type-fest@^0.21.3:
|
||||||
|
version "0.21.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
|
||||||
|
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
|
||||||
|
|
||||||
type-fest@^1.0.2:
|
type-fest@^1.0.2:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1"
|
||||||
@@ -2914,10 +3213,10 @@ undici-types@~6.21.0:
|
|||||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
|
||||||
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
|
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
|
||||||
|
|
||||||
undici-types@~7.10.0:
|
undici-types@~7.12.0:
|
||||||
version "7.10.0"
|
version "7.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.10.0.tgz#4ac2e058ce56b462b056e629cc6a02393d3ff350"
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.12.0.tgz#15c5c7475c2a3ba30659529f5cdb4674b622fafb"
|
||||||
integrity sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==
|
integrity sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==
|
||||||
|
|
||||||
unique-filename@^2.0.0:
|
unique-filename@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
@@ -2956,7 +3255,7 @@ username@^5.1.0:
|
|||||||
execa "^1.0.0"
|
execa "^1.0.0"
|
||||||
mem "^4.3.0"
|
mem "^4.3.0"
|
||||||
|
|
||||||
util-deprecate@^1.0.1:
|
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||||
@@ -3047,6 +3346,15 @@ worker-timers@^8.0.23:
|
|||||||
worker-timers-broker "^8.0.10"
|
worker-timers-broker "^8.0.10"
|
||||||
worker-timers-worker "^9.0.10"
|
worker-timers-worker "^9.0.10"
|
||||||
|
|
||||||
|
wrap-ansi@^6.2.0:
|
||||||
|
version "6.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
||||||
|
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
|
||||||
|
dependencies:
|
||||||
|
ansi-styles "^4.0.0"
|
||||||
|
string-width "^4.1.0"
|
||||||
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
wrap-ansi@^7.0.0:
|
wrap-ansi@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
@@ -3138,3 +3446,8 @@ yocto-queue@^0.1.0:
|
|||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||||
|
|
||||||
|
yoctocolors-cjs@^2.1.2:
|
||||||
|
version "2.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa"
|
||||||
|
integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==
|
||||||
|
|||||||
Reference in New Issue
Block a user