diff --git a/.entity_generator b/.entity_generator new file mode 100644 index 0000000..8171792 --- /dev/null +++ b/.entity_generator @@ -0,0 +1,3 @@ +[hass] +BASE_URL=http://localhost:9123 +TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhYTdjOGQ5MzBiMDM0MDM2OGVjZTdjOTRjMTcyOWQ0OSIsImlhdCI6MTcxNDYwMzkyMywiZXhwIjoyMDI5OTYzOTIzfQ.Tvoh25bukQh5T5WIuvvkL9jVBihcOGG6D5JYdqdwx1U diff --git a/.eslintrc.json b/.eslintrc.json index a10eb20..ff50bb2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -42,9 +42,9 @@ "unicorn/no-empty-file": "off", "sonarjs/prefer-single-boolean-return": "off", "unicorn/no-array-callback-reference": "off", + "@typescript-eslint/unbound-method": "off", "unicorn/no-await-expression-member": "off", "unicorn/no-useless-undefined": "off", - "@typescript-eslint/unbound-method": "error", "import/no-extraneous-dependencies": [ "error", { @@ -72,7 +72,6 @@ "unicorn/prefer-node-protocol": "off", "unicorn/no-array-for-each": "off", "unicorn/import-style": "off", - "sonarjs/cognitive-complexity": "off", "sort-keys-fix/sort-keys-fix": "warn", "unicorn/prefer-event-target": "off", "simple-import-sort/imports": "warn", diff --git a/.prettierrc b/.prettierrc index ba0fbe6..4d8124d 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,5 +2,6 @@ "singleQuote": false, "trailingComma": "all", "jsxSingleQuote": false, + "printWidth": 100, "arrowParens": "avoid" } diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2843801 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to process", + "type": "node", + "request": "attach", + "port": 9229, + "skipFiles": [ + // Node.js internal core modules + "/**", + + // Ignore all dependencies (optional) + // "${workspaceFolder}/node_modules/**", + // "!${workspaceFolder}/node_modules/@digital-alchemy/**", + ], + } + ] +} diff --git a/README.md b/README.md index 11e9b1d..d1f626c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Welcome to `@digital-alchemy/synapse`! This project builds on the functions provided by `@digital-alchemy/hass` to provide the ability to generate entities within your Home Assistant install. With the help of a [custom component](https://github.com/Digital-Alchemy-TS/synapse-extension), you can gate logic behind switches, report states with sensors, attach functions to buttons, and more! - [Extended docs](https://docs.digital-alchemy.app/Synapse) -- [Discord](https://discord.com/invite/mtWHk36upW) +- [Discord](https://discord.gg/JkZ35Gv97Y) ## 💾 Install @@ -52,10 +52,12 @@ export function Example({ scheduler, context, synapse }: TServiceParams) { // create a new phrase // taking into consideration the current state of the switch const regenerate = () => { - sensor.state = + sensor.storage.set( + "state", useHacker.state === "on" ? faker.hacker.phrase() - : faker.company.catchPhrase(); + : faker.company.catchPhrase() + ); }; // update sensor every 10 minutes @@ -73,32 +75,6 @@ export function Example({ scheduler, context, synapse }: TServiceParams) { } ``` -> Names should be unique per domain! - -### 🔌 Automatic availability reporting - -A `binary_sensor.{app_name}_online` will be created and managed by the extension. This binary sensor will display the connected state of your application and is always available. All other entities owned by this application will have their `availability` state tied to the online state. - -When your application disconnects, it emits a "going offline" message to automatically flag entities. Applications also emit a heartbeat that the custom component uses to identify more sudden failures. - -### 🔁 Reloading in Home Assistant - -By default, applications don't automatically send their current list of entities to Home Assistant. To trigger an update/resync with your application and the custom component, use the `reload` button. - -![reload button](./docs//reload.png) - -## 🌐 Supported Domains - -Current support includes - -| Domain | Notes | -| --------------- | ------------------------------------------------------------- | -| `binary_sensor` | reports an `on`/`off` state, not much else | -| `button` | create a quick callback to some code on your dashboard | -| `sensor` | report `string`/`number`/`date` states, as well as attributes | -| `switch` | create virtual switches to gate logic with | -| `scene` | slightly different buttons, bring your own scene setting logic| - ## 🤝 Related Projects | GitHub | Description | NPM | diff --git a/cspell.config.yaml b/cspell.config.yaml index 9fc0342..1b9f7f1 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -3,7 +3,26 @@ ignorePaths: [] dictionaryDefinitions: [] dictionaries: [] words: - - hass + - alexa + - cbar + - comms + - datetime + - desync + - endregion + - gbit - gotify + - hass + - homeassistant + - hvac + - kbit + - mbar + - mbit + - programminghorror + - rgbw + - rgbww + - sonarjs + - tvshow + - utcnow + - zeroconf ignoreWords: [] import: [] diff --git a/package-lock.json b/package-lock.json index 49097fb..657a5ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,172 +1,108 @@ { "name": "@digital-alchemy/synapse", - "version": "0.3.4", + "version": "0.3.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@digital-alchemy/synapse", - "version": "0.3.4", + "version": "0.3.6", "license": "MIT", "dependencies": { - "@digital-alchemy/core": "^0.3.8", - "@digital-alchemy/hass": "^0.3.7", - "dayjs": "^1.11.10", - "prom-client": "^15.1.0", - "ws": "^8.16.0" + "@digital-alchemy/core": "^0.3.16", + "@digital-alchemy/fastify-extension": "^0.3.3", + "@digital-alchemy/hass": "^0.3.30", + "bonjour": "^3.5.0", + "dayjs": "^1.11.11" }, "devDependencies": { - "@cspell/eslint-plugin": "^8.6.1", + "@cspell/eslint-plugin": "^8.8.1", + "@types/bonjour": "^3.5.13", "@types/figlet": "^1.5.8", "@types/jest": "^29.5.12", "@types/js-yaml": "^4.0.9", "@types/minimist": "^1.2.5", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.11.30", + "@types/node": "^20.12.12", "@types/uuid": "^9.0.8", "@types/ws": "^8.5.10", - "@typescript-eslint/eslint-plugin": "7.4.0", - "@typescript-eslint/parser": "7.4.0", + "@typescript-eslint/eslint-plugin": "7.9.0", + "@typescript-eslint/parser": "7.9.0", "eslint": "8.57.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsonc": "^2.14.1", + "eslint-plugin-jsonc": "^2.15.1", "eslint-plugin-no-unsanitized": "^4.0.2", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-security": "^2.1.1", - "eslint-plugin-simple-import-sort": "^12.0.0", - "eslint-plugin-sonarjs": "^0.24.0", + "eslint-plugin-security": "^3.0.0", + "eslint-plugin-simple-import-sort": "^12.1.0", + "eslint-plugin-sonarjs": "^0.25.1", "eslint-plugin-sort-keys-fix": "^1.1.2", - "eslint-plugin-unicorn": "^51.0.1", + "eslint-plugin-unicorn": "^52.0.0", "jest": "^29.7.0", "jest-environment-node": "^29.7.0", - "npm-check-updates": "^16.14.18", + "npm-check-updates": "^16.14.20", "prettier": "^3.2.5", "ts-jest": "^29.1.2", - "tsx": "^4.7.1", - "type-fest": "^4.14.0", - "typescript": "^5.4.3" + "tsx": "^4.10.3", + "type-fest": "^4.18.2", + "typescript": "^5.4.5" }, "engines": { "node": ">=20" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -191,14 +127,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", "dev": true, "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -277,28 +213,28 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", + "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-simple-access": "^7.24.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -308,51 +244,51 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", + "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", "dev": true, "engines": { "node": ">=6.9.0" @@ -368,28 +304,29 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", + "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", "dev": true, "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", + "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.5", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -452,9 +389,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -524,12 +461,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -626,12 +563,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -641,33 +578,33 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -685,13 +622,13 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -715,9 +652,9 @@ } }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.6.1.tgz", - "integrity": "sha512-s6Av1xIgctYLuUiazKZjQ2WRUXc9dU38BOZXwM/lb7y8grQMEuTjST1c+8MOkZkppx48/sO7GHIF3k9rEzD3fg==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.8.1.tgz", + "integrity": "sha512-zP/cC7ABk9PM6X1/itEOYa9raWrdUtUXCcUtHLnEr83HhPUHZ8vzaBgMJ176No/7EgZ4BHGXVvA0v079ukXVxw==", "dev": true, "dependencies": { "@cspell/dict-ada": "^4.0.2", @@ -733,7 +670,7 @@ "@cspell/dict-docker": "^1.1.7", "@cspell/dict-dotnet": "^5.0.0", "@cspell/dict-elixir": "^4.0.3", - "@cspell/dict-en_us": "^4.3.17", + "@cspell/dict-en_us": "^4.3.19", "@cspell/dict-en-common-misspellings": "^2.0.0", "@cspell/dict-en-gb": "1.1.33", "@cspell/dict-filetypes": "^3.0.3", @@ -753,7 +690,8 @@ "@cspell/dict-lorem-ipsum": "^4.0.0", "@cspell/dict-lua": "^4.0.3", "@cspell/dict-makefile": "^1.0.0", - "@cspell/dict-node": "^4.0.3", + "@cspell/dict-monkeyc": "^1.0.6", + "@cspell/dict-node": "^5.0.1", "@cspell/dict-npm": "^5.0.15", "@cspell/dict-php": "^4.0.6", "@cspell/dict-powershell": "^5.0.3", @@ -761,14 +699,14 @@ "@cspell/dict-python": "^4.1.11", "@cspell/dict-r": "^2.0.1", "@cspell/dict-ruby": "^5.0.2", - "@cspell/dict-rust": "^4.0.2", + "@cspell/dict-rust": "^4.0.3", "@cspell/dict-scala": "^5.0.0", - "@cspell/dict-software-terms": "^3.3.18", + "@cspell/dict-software-terms": "^3.3.20", "@cspell/dict-sql": "^2.1.3", "@cspell/dict-svelte": "^1.0.2", "@cspell/dict-swift": "^2.0.1", "@cspell/dict-terraform": "^1.0.0", - "@cspell/dict-typescript": "^3.1.2", + "@cspell/dict-typescript": "^3.1.4", "@cspell/dict-vue": "^3.0.0" }, "engines": { @@ -776,18 +714,18 @@ } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.6.1.tgz", - "integrity": "sha512-guIlGhhOLQwfqevBSgp26b+SX4I1hCH+puAksWAk93bybKkcGtGpcavAQSN9qvamox4zcHnvGutEPF+UcXuceQ==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.8.1.tgz", + "integrity": "sha512-AMQ0s7qH71tNnrpX8ILl+OZceDHt//h/T3Yk//qvn69x1Dzfg4Saqv/qhfG1VClQVyV5F4y7tIa4UNd5X6mW4g==", "dev": true, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.6.1.tgz", - "integrity": "sha512-ZUbYcvEhfokHG9qfUlIylUqEobG84PiDozCkE8U4h/rTSmYkf/nAD+M6yg+jQ0F2aTFGNbvpKKGFlfXFXveX7A==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.8.1.tgz", + "integrity": "sha512-K5sPp05Pz3tYU9roFGILSB6OdSVYqyr4Y/NW1CxZsXgq+hmwxAJQag/RyhW6cUp/1Jhy5RKYGNy0H0u/jODx3A==", "dev": true, "dependencies": { "global-directory": "^4.0.1" @@ -797,18 +735,18 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.6.1.tgz", - "integrity": "sha512-WpI3fSW8t00UMetfd6tS8f9+xE3+ElIUO/bQ1YKK95TMIRdEUcH+QDxcHM66pJXEm4WiaN3H/MfWk1fIhGlJ8g==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.8.1.tgz", + "integrity": "sha512-dxZ/ymwP6XNMGkU5iIUVgFP2JEqEvpJZavpAerB/y5E560Agv1WuUpkZE/PMCmseoLjSiV5yQzcnLNoT5X/w7A==", "dev": true, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-types": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.6.1.tgz", - "integrity": "sha512-MXa9v6sXbbwyiNno7v7vczNph6AsMNWnpMRCcW3h/siXNQYRuMssdxqT5sQJ8Kurh3M/Wo7DlKX4n74elKL3iQ==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.8.1.tgz", + "integrity": "sha512-JEbLN+b3XdHIpEaoZJnpPfL8iTKWraqE7x1VwG7FIQ9wjP6fCPwfNRVM0CUWEmT+85O/zvbYVOlTJn1uIOLnZw==", "dev": true, "engines": { "node": ">=18" @@ -839,9 +777,9 @@ "dev": true }, "node_modules/@cspell/dict-cpp": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.1.3.tgz", - "integrity": "sha512-sqnriXRAInZH9W75C+APBh6dtben9filPqVbIsiRMUXGg+s02ekz0z6LbS7kXeJ5mD2qXoMLBrv13qH2eIwutQ==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.1.5.tgz", + "integrity": "sha512-5059TJREAIwvstJBqJjoHrs7yrPijnqB2SUZ7uc8nCA/Q4KbdvKjiDsKVr4Y624J8Ns9KnImoH6FVfkAEv6oqw==", "dev": true }, "node_modules/@cspell/dict-cryptocurrencies": { @@ -887,9 +825,9 @@ "dev": true }, "node_modules/@cspell/dict-dotnet": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.0.tgz", - "integrity": "sha512-EOwGd533v47aP5QYV8GlSSKkmM9Eq8P3G/eBzSpH3Nl2+IneDOYOBLEUraHuiCtnOkNsz0xtZHArYhAB2bHWAw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.2.tgz", + "integrity": "sha512-UD/pO2A2zia/YZJ8Kck/F6YyDSpCMq0YvItpd4YbtDVzPREfTZ48FjZsbYi4Jhzwfvc6o8R56JusAE58P+4sNQ==", "dev": true }, "node_modules/@cspell/dict-elixir": { @@ -899,9 +837,9 @@ "dev": true }, "node_modules/@cspell/dict-en_us": { - "version": "4.3.17", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.17.tgz", - "integrity": "sha512-CS0Tb2f2YwQZ4VZ6+WLAO5uOzb0iO/iYSRl34kX4enq6quXxLYzwdfGAwv85wSYHPdga8tGiZFP+p8GPsi2JEg==", + "version": "4.3.19", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.19.tgz", + "integrity": "sha512-tHcXdkmm0t9LlRct1vgu3+h0KW/wlXCInkTiR4D/rl730q1zu2qVEgiy1saMiTUSNmdu7Hiy+Mhb+1braVqnZQ==", "dev": true }, "node_modules/@cspell/dict-en-common-misspellings": { @@ -917,9 +855,9 @@ "dev": true }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.3.tgz", - "integrity": "sha512-J9UP+qwwBLfOQ8Qg9tAsKtSY/WWmjj21uj6zXTI9hRLD1eG1uUOLcfVovAmtmVqUWziPSKMr87F6SXI3xmJXgw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.4.tgz", + "integrity": "sha512-IBi8eIVdykoGgIv5wQhOURi5lmCNJq0we6DvqKoPQJHthXbgsuO1qrHSiUVydMiQl/XvcnUWTMeAlVUlUClnVg==", "dev": true }, "node_modules/@cspell/dict-fonts": { @@ -953,9 +891,9 @@ "dev": true }, "node_modules/@cspell/dict-golang": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.5.tgz", - "integrity": "sha512-w4mEqGz4/wV+BBljLxduFNkMrd3rstBNDXmoX5kD4UTzIb4Sy0QybWCtg2iVT+R0KWiRRA56QKOvBsgXiddksA==", + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.8.tgz", + "integrity": "sha512-1OwJNMU0oVISaNjaoQJatgYszFlNESzXPOg1f5/9V0+nL+R08nzDpZi4cWwPaHr8pIBtXzEoHL0dGY+IuoLFtQ==", "dev": true }, "node_modules/@cspell/dict-haskell": { @@ -989,9 +927,9 @@ "dev": true }, "node_modules/@cspell/dict-k8s": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.2.tgz", - "integrity": "sha512-tLT7gZpNPnGa+IIFvK9SP1LrSpPpJ94a/DulzAPOb1Q2UBFwdpFd82UWhio0RNShduvKG/WiMZf/wGl98pn+VQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.3.tgz", + "integrity": "sha512-dR58QCcsOYeOoPT+d3kUPrEQ9FQ62cohLHqPu4kiWvsrLszEUMopjGu3p5tVnq496M+RY5PLlbLLaW9ixHmFOQ==", "dev": true }, "node_modules/@cspell/dict-latex": { @@ -1018,22 +956,28 @@ "integrity": "sha512-3W9tHPcSbJa6s0bcqWo6VisEDTSN5zOtDbnPabF7rbyjRpNo0uHXHRJQF8gAbFzoTzBBhgkTmrfSiuyQm7vBUQ==", "dev": true }, + "node_modules/@cspell/dict-monkeyc": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.6.tgz", + "integrity": "sha512-oO8ZDu/FtZ55aq9Mb67HtaCnsLn59xvhO/t2mLLTHAp667hJFxpp7bCtr2zOrR1NELzFXmKln/2lw/PvxMSvrA==", + "dev": true + }, "node_modules/@cspell/dict-node": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-4.0.3.tgz", - "integrity": "sha512-sFlUNI5kOogy49KtPg8SMQYirDGIAoKBO3+cDLIwD4MLdsWy1q0upc7pzGht3mrjuyMiPRUV14Bb0rkVLrxOhg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.1.tgz", + "integrity": "sha512-lax/jGz9h3Dv83v8LHa5G0bf6wm8YVRMzbjJPG/9rp7cAGPtdrga+XANFq+B7bY5+jiSA3zvj10LUFCFjnnCCg==", "dev": true }, "node_modules/@cspell/dict-npm": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.15.tgz", - "integrity": "sha512-sX0X5YWNW54F4baW7b5JJB6705OCBIZtUqjOghlJNORS5No7QY1IX1zc5FxNNu4gsaCZITAmfMi4ityXEsEThA==", + "version": "5.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.16.tgz", + "integrity": "sha512-ZWPnLAziEcSCvV0c8k9Qj88pfMu+wZwM5Qks87ShsfBgI8uLZ9tGHravA7gmjH1Gd7Bgxy2ulvXtSqIWPh1lew==", "dev": true }, "node_modules/@cspell/dict-php": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.6.tgz", - "integrity": "sha512-ySAXisf7twoVFZqBV2o/DKiCLIDTHNqfnj0EfH9OoOUR7HL3rb6zJkm0viLUFDO2G/8SyIi6YrN/6KX+Scjjjg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.7.tgz", + "integrity": "sha512-SUCOBfRDDFz1E2jnAZIIuy8BNbCc8i+VkiL9g4HH9tTN6Nlww5Uz2pMqYS6rZQkXuubqsbkbPlsRiuseEnTmYA==", "dev": true }, "node_modules/@cspell/dict-powershell": { @@ -1070,21 +1014,21 @@ "dev": true }, "node_modules/@cspell/dict-rust": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.2.tgz", - "integrity": "sha512-RhziKDrklzOntxAbY3AvNR58wnFGIo3YS8+dNeLY36GFuWOvXDHFStYw5Pod4f/VXbO/+1tXtywCC4zWfB2p1w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.3.tgz", + "integrity": "sha512-8DFCzkFQ+2k3fDaezWc/D+0AyiBBiOGYfSDUfrTNU7wpvUvJ6cRcAUshMI/cn2QW/mmxTspRgVlXsE6GUMz00Q==", "dev": true }, "node_modules/@cspell/dict-scala": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.0.tgz", - "integrity": "sha512-ph0twaRoV+ylui022clEO1dZ35QbeEQaKTaV2sPOsdwIokABPIiK09oWwGK9qg7jRGQwVaRPEq0Vp+IG1GpqSQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.2.tgz", + "integrity": "sha512-v97ClgidZt99JUm7OjhQugDHmhx4U8fcgunHvD/BsXWjXNj4cTr0m0YjofyZoL44WpICsNuFV9F/sv9OM5HUEw==", "dev": true }, "node_modules/@cspell/dict-software-terms": { - "version": "3.3.18", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.3.18.tgz", - "integrity": "sha512-LJZGGMGqS8KzgXJrSMs3T+6GoqHG9z8Bc+rqLzLzbtoR3FbsMasE9U8oP2PmS3q7jJLFjQkzmg508DrcuZuo2g==", + "version": "3.3.22", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.3.22.tgz", + "integrity": "sha512-uEtaN0xeDbGh88QX+SSvvBNvZahk3ZXBRnfgHWoppUF6WGtg1oLtuLWO6fGGtwRE4klXvSWP8rA2ixzAbWvYqw==", "dev": true }, "node_modules/@cspell/dict-sql": { @@ -1112,9 +1056,9 @@ "dev": true }, "node_modules/@cspell/dict-typescript": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.2.tgz", - "integrity": "sha512-lcNOYWjLUvDZdLa0UMNd/LwfVdxhE9rKA+agZBGjL3lTA3uNvH7IUqSJM/IXhJoBpLLMVEOk8v1N9xi+vDuCdA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.4.tgz", + "integrity": "sha512-jUcPa0rsPca5ur1+G56DXnSc5hbbJkzvPHHvyQtkbPXBQd3CXPMNfrTVCgzex/7cY/7FONcpFCUwgwfni9Jqbw==", "dev": true }, "node_modules/@cspell/dict-vue": { @@ -1124,61 +1068,48 @@ "dev": true }, "node_modules/@cspell/dynamic-import": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.6.1.tgz", - "integrity": "sha512-Fjvkcb5umIAcHfw/iiciYWgO2mXVuRZzQAWPSub6UFCxxcJlRz39YPXa+3O/m3lnXCeo8ChoaEN8qnuV4ogk6g==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.8.1.tgz", + "integrity": "sha512-IyKEbSaHkw9V4Oc4JDasF96+BHKV8motBrepjLIMUjdJ152fBg8zqbvF769POdCJg0QouZVUV+h9V7zC6v45/g==", "dev": true, "dependencies": { - "import-meta-resolve": "^4.0.0" + "import-meta-resolve": "^4.1.0" }, "engines": { "node": ">=18.0" } }, "node_modules/@cspell/eslint-plugin": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@cspell/eslint-plugin/-/eslint-plugin-8.6.1.tgz", - "integrity": "sha512-PIY7lyaVFd1CuLpnuCtXD07Qlod1mLGcUy2NI6ghgXku34oyTrbU4NYC5lNNM1tUxNSGwz2NQOdoTWnEOacllw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/eslint-plugin/-/eslint-plugin-8.8.1.tgz", + "integrity": "sha512-vPeuy0QxfQpY6Jj36u5+QY7v0nDScxIRp8cVQxf0bfLkMCbkmk8Zs6bUcX4D7i58TdrTXOIbxswrK7t7g0bgTA==", "dev": true, "dependencies": { - "@cspell/cspell-types": "8.6.1", - "cspell-lib": "8.6.1", + "@cspell/cspell-types": "8.8.1", + "cspell-lib": "8.8.1", "estree-walker": "^3.0.3", "synckit": "^0.9.0" }, "engines": { "node": ">=18" - } - }, - "node_modules/@cspell/eslint-plugin/node_modules/synckit": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.0.tgz", - "integrity": "sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==", - "dev": true, - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" }, - "funding": { - "url": "https://opencollective.com/unts" + "peerDependencies": { + "eslint": "^7 || ^8 || ^9" } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.6.1.tgz", - "integrity": "sha512-X6/7cy+GGVJFXsfrZapxVKn5mtehNTr7hTlg0bVj3iFoNYEPW9zq9l6WIcI4psmaU8G4DSrNsBK7pp87W3u16A==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.8.1.tgz", + "integrity": "sha512-QNnMY5jKP/ItVYRGS4w3KF+1iXBUUjldZNVtEoQe2dFergxvbIYQ0S++TZb25G/o9nRF5GmOpecJaOvwUBZsiw==", "dev": true, "engines": { "node": ">=18" } }, "node_modules/@digital-alchemy/core": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@digital-alchemy/core/-/core-0.3.8.tgz", - "integrity": "sha512-8FtrxW8ZCwc1yUjKB+q0bbo5uv5y2UisCrD8aWnKTXVl6ntOmbw8Fr6lbhYc+tYYRZKiQ6Zu1B5+Z/QMB7UePA==", + "version": "0.3.16", + "resolved": "https://registry.npmjs.org/@digital-alchemy/core/-/core-0.3.16.tgz", + "integrity": "sha512-O8OwY23US1eCKRut2cs1KD6C3bAQ9m7/G16mqWp6E8EDMB7Hoj5kMxSjJdsKj7PNHtXEnxIUCknZWmvZtzpv3w==", "dependencies": { "chalk": "^5.3.0", "dayjs": "^1.11.10", @@ -1196,32 +1127,44 @@ "redis": "^4.6.13" } }, - "node_modules/@digital-alchemy/core/node_modules/ini": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", - "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", + "node_modules/@digital-alchemy/fastify-extension": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@digital-alchemy/fastify-extension/-/fastify-extension-0.3.3.tgz", + "integrity": "sha512-aVw+TIAPnYqmsmyDz4P2hk2pGUWW+UUisj6JlWuOf10Y5QWO+sJXnjuf4JJrnpDIXU5N6otrhXbRVW24QMvuMg==", + "dependencies": { + "@digital-alchemy/core": "^0.3.8", + "@fastify/auth": "^4.6.1", + "@fastify/basic-auth": "^5.1.1", + "@fastify/jwt": "^8.0.0", + "dayjs": "^1.11.10", + "fastify": "^4.26.2", + "prom-client": "^15.1.0" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=20" } }, "node_modules/@digital-alchemy/hass": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@digital-alchemy/hass/-/hass-0.3.7.tgz", - "integrity": "sha512-7AOn1YRXIelnIjPWvcQHI2DyECePD8BUthauRVMT9jsloaKTJUOlN1ZGkkhIoPia19u2dEr3yulUBjLIh28ocA==", + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@digital-alchemy/hass/-/hass-0.3.30.tgz", + "integrity": "sha512-13MnEoSWSx51b56XrkJ2rMi+WQZa9tOEr0VvP1bag/8cypqUy1saq3Xn7pG4s+J60y5tDFc3amikOq17mcH/vw==", "dependencies": { - "@digital-alchemy/core": "^0.3.8", - "dayjs": "^1.11.10", - "prom-client": "^15.1.0", - "ws": "^8.16.0" + "@digital-alchemy/core": "^0.3.15", + "dayjs": "^1.11.11", + "prom-client": "^15.1.2", + "ws": "^8.17.0" + }, + "bin": { + "mock-assistant": "dist/mock_assistant/main.js" }, "engines": { "node": ">=20" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", "cpu": [ "ppc64" ], @@ -1235,9 +1178,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], @@ -1251,9 +1194,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], @@ -1267,9 +1210,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], @@ -1283,9 +1226,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -1299,9 +1242,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], @@ -1315,9 +1258,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], @@ -1331,9 +1274,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], @@ -1347,9 +1290,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], @@ -1363,9 +1306,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], @@ -1379,9 +1322,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], @@ -1395,9 +1338,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], @@ -1411,9 +1354,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], @@ -1427,9 +1370,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], @@ -1443,9 +1386,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], @@ -1459,9 +1402,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], @@ -1475,9 +1418,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], @@ -1491,9 +1434,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], @@ -1507,9 +1450,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], @@ -1523,9 +1466,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], @@ -1539,9 +1482,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], @@ -1555,9 +1498,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], @@ -1571,9 +1514,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], @@ -1664,6 +1607,87 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fastify/ajv-compiler": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-3.5.0.tgz", + "integrity": "sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==", + "dependencies": { + "ajv": "^8.11.0", + "ajv-formats": "^2.1.1", + "fast-uri": "^2.0.0" + } + }, + "node_modules/@fastify/ajv-compiler/node_modules/ajv": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@fastify/ajv-compiler/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/@fastify/auth": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@fastify/auth/-/auth-4.6.1.tgz", + "integrity": "sha512-J/UkZw6EYUX7aXu78YLV1uE1ESbHsGNKxyO+H82ixdC3AnzBT8qeBI6K19mqVHfJTICy5m9uspj7PjC7EvZQ/A==", + "dependencies": { + "fastify-plugin": "^4.0.0", + "reusify": "^1.0.4" + } + }, + "node_modules/@fastify/basic-auth": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@fastify/basic-auth/-/basic-auth-5.1.1.tgz", + "integrity": "sha512-L4b7EK5LKZnV6fdH1+rQbjhkKGXjCfiKJ0JkdGHZQPBMHMiXDZF8xbZsCakWGf9c7jDXJicP3FPcIXUPBkuSeQ==", + "dependencies": { + "@fastify/error": "^3.0.0", + "fastify-plugin": "^4.0.0" + } + }, + "node_modules/@fastify/error": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", + "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==" + }, + "node_modules/@fastify/fast-json-stringify-compiler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz", + "integrity": "sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==", + "dependencies": { + "fast-json-stringify": "^5.7.0" + } + }, + "node_modules/@fastify/jwt": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@fastify/jwt/-/jwt-8.0.1.tgz", + "integrity": "sha512-295bd7V6bDCnZOu8MAQgM6r7V1KILB+kdEq1q6nbHfXCnML569n7NSo3WzeLDG6IAqDl+Rhzi1vjxwaNHhRCBA==", + "dependencies": { + "@fastify/error": "^3.0.0", + "@lukeed/ms": "^2.0.0", + "fast-jwt": "^4.0.0", + "fastify-plugin": "^4.0.0", + "steed": "^1.1.3" + } + }, + "node_modules/@fastify/merge-json-schemas": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz", + "integrity": "sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -1720,9 +1744,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@isaacs/cliui": { @@ -1882,6 +1906,12 @@ "node": ">=8" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -2363,19 +2393,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@jest/transform/node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/@jest/types": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", @@ -2443,32 +2460,32 @@ "dev": true }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" @@ -2481,15 +2498,23 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@lukeed/ms": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", + "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", + "engines": { + "node": ">=8" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2526,9 +2551,9 @@ } }, "node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", + "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", "dev": true, "dependencies": { "semver": "^7.3.5" @@ -2581,16 +2606,16 @@ } }, "node_modules/@npmcli/installed-package-contents": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", - "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz", + "integrity": "sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==", "dev": true, "dependencies": { "npm-bundled": "^3.0.0", "npm-normalize-package-bin": "^3.0.0" }, "bin": { - "installed-package-contents": "lib/index.js" + "installed-package-contents": "bin/index.js" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -2678,9 +2703,9 @@ } }, "node_modules/@opentelemetry/api": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.7.0.tgz", - "integrity": "sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", + "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==", "engines": { "node": ">=8.0.0" } @@ -2758,9 +2783,9 @@ } }, "node_modules/@redis/client": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.14.tgz", - "integrity": "sha512-YGn0GqsRBFUQxklhY7v562VMOP0DcmlrHHs3IV1mFE3cbxe31IITUkqhBcIhVSI/2JqtWAJXg5mjV4aU+zD0HA==", + "version": "1.5.16", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.16.tgz", + "integrity": "sha512-X1a3xQ5kEMvTib5fBrHKh6Y+pXbeKXqziYuxOUo1ojQNECg4M5Etd1qqyhMap+lFUOAh8S7UYevgJHOm4A+NOg==", "optional": true, "dependencies": { "cluster-key-slot": "1.1.2", @@ -2771,6 +2796,12 @@ "node": ">=14" } }, + "node_modules/@redis/client/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, "node_modules/@redis/graph": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz", @@ -2975,6 +3006,15 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -3042,12 +3082,6 @@ "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", "dev": true }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -3070,9 +3104,9 @@ } }, "node_modules/@types/node": { - "version": "20.11.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", - "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3084,12 +3118,6 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, "node_modules/@types/semver-utils": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@types/semver-utils/-/semver-utils-1.1.3.tgz", @@ -3133,22 +3161,20 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz", - "integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz", + "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/type-utils": "7.4.0", - "@typescript-eslint/utils": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/type-utils": "7.9.0", + "@typescript-eslint/utils": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3168,15 +3194,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz", - "integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", + "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "debug": "^4.3.4" }, "engines": { @@ -3196,13 +3222,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", + "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3213,15 +3239,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz", - "integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz", + "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/utils": "7.4.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/utils": "7.9.0", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3240,9 +3266,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", + "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3253,19 +3279,19 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", + "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3281,18 +3307,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz", + "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3306,13 +3329,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", + "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.9.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3334,6 +3357,22 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abstract-logging": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==" + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -3408,13 +3447,49 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dependencies": { - "string-width": "^4.1.0" + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" } }, "node_modules/ansi-escapes": { @@ -3484,10 +3559,16 @@ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==" + }, "node_modules/are-we-there-yet": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", "dev": true, "dependencies": { "delegates": "^1.0.0", @@ -3497,20 +3578,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -3532,16 +3599,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -3566,35 +3639,17 @@ "node": ">=8" } }, - "node_modules/array.prototype.filter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", - "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", - "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" }, "engines": { @@ -3662,11 +3717,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/available-typed-arrays": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", - "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -3674,6 +3751,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/avvio": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.3.0.tgz", + "integrity": "sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==", + "dependencies": { + "@fastify/error": "^3.3.0", + "archy": "^1.0.0", + "debug": "^4.0.0", + "fastq": "^1.17.1" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -3845,11 +3933,48 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/bintrees": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" }, + "node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==", + "dependencies": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, "node_modules/boxen": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", @@ -3968,9 +4093,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -3987,8 +4112,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -4020,12 +4145,40 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" + }, "node_modules/builtin-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", @@ -4038,15 +4191,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "dependencies": { - "semver": "^7.0.0" - } - }, "node_modules/cacache": { "version": "17.1.4", "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", @@ -4071,22 +4215,22 @@ } }, "node_modules/cacache/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.3.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz", + "integrity": "sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", + "jackspeak": "^2.3.6", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "minipass": "^7.0.4", + "path-scurry": "^1.11.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4102,9 +4246,9 @@ } }, "node_modules/cacache/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", + "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -4138,15 +4282,15 @@ } }, "node_modules/call-bind": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", - "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", - "dev": true, + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "set-function-length": "^1.2.0" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -4174,9 +4318,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001585", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001585.tgz", - "integrity": "sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q==", + "version": "1.0.30001620", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz", + "integrity": "sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==", "dev": true, "funding": [ { @@ -4238,9 +4382,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", "dev": true }, "node_modules/clean-regexp": { @@ -4302,9 +4446,9 @@ } }, "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, "dependencies": { "string-width": "^4.2.0" @@ -4503,6 +4647,18 @@ "url": "https://github.com/yeoman/configstore?sponsor=1" } }, + "node_modules/configstore/node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -4515,13 +4671,21 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/core-js-compat": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.1.tgz", - "integrity": "sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==", + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", "dev": true, "dependencies": { - "browserslist": "^4.22.2" + "browserslist": "^4.23.0" }, "funding": { "type": "opencollective", @@ -4646,28 +4810,28 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.6.1.tgz", - "integrity": "sha512-I6LatgXJb8mxKFzIywO81TlUD/qWnUDrhB6yTUPdP90bwZcXMmGoCsZxhd2Rvl9fz5fWne0T839I1coShfm86g==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.8.1.tgz", + "integrity": "sha512-NTFfwL7Si1jp+0TINS9miXGdtPtDq95PhSbZKF9jnuBwnsnAURHCGALryLHlkRvj5JZk6dpkDfw4WxqQXdULNw==", "dev": true, "dependencies": { - "@cspell/cspell-types": "8.6.1", + "@cspell/cspell-types": "8.8.1", "comment-json": "^4.2.3", - "yaml": "^2.4.1" + "yaml": "^2.4.2" }, "engines": { "node": ">=18" } }, "node_modules/cspell-dictionary": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.6.1.tgz", - "integrity": "sha512-0SfKPi1QoWbGpZ/rWMR7Jn0+GaQT9PAMLWjVOu66PUNUXI5f4oCTHpnZE1Xts+5VX8shZC3TAMHEgtgKuQn4RQ==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.8.1.tgz", + "integrity": "sha512-WJqCLR/icyZc0rphEO6dZZDlSIaWIXd95QjZu3agL7a1LRLjorqhVJty6WZrV4zkOLT6PPB+qcjMxcCCxIlWiw==", "dev": true, "dependencies": { - "@cspell/cspell-pipe": "8.6.1", - "@cspell/cspell-types": "8.6.1", - "cspell-trie-lib": "8.6.1", + "@cspell/cspell-pipe": "8.8.1", + "@cspell/cspell-types": "8.8.1", + "cspell-trie-lib": "8.8.1", "fast-equals": "^5.0.1", "gensequence": "^7.0.0" }, @@ -4676,9 +4840,9 @@ } }, "node_modules/cspell-glob": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.6.1.tgz", - "integrity": "sha512-QjtngIR0XsUQLmHHDO86hps/JR5sRxSBwCvcsNCEmSdpdofLFc8cuxi3o33JWge7UAPBCQOLGfpA7/Wx31srmw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.8.1.tgz", + "integrity": "sha512-x2rS6gJzaF3KZB6FuNkuS3Kb3ynYns0zfC0uG/QJb9V/xc0DmAjQGQhiLIDx6XmvvDvowKmyQ/kBjY/K4VjCvQ==", "dev": true, "dependencies": { "micromatch": "^4.0.5" @@ -4688,13 +4852,13 @@ } }, "node_modules/cspell-grammar": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.6.1.tgz", - "integrity": "sha512-MaG0e/F0b2FnIRULCZ61JxEiJgTP/6rsbUoR5nG9X+WmJYItYmxC1F/FPPrVeTu+jJr/8O4pdnslE20pimHaCw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.8.1.tgz", + "integrity": "sha512-YTyrutwIkiPH9t255l+BQtneGAkgE3uZXmnRHeIi6X+qdmnf61i8XYaSaO66VKQJX6VPZG18hBVMSUPZmYtoSw==", "dev": true, "dependencies": { - "@cspell/cspell-pipe": "8.6.1", - "@cspell/cspell-types": "8.6.1" + "@cspell/cspell-pipe": "8.8.1", + "@cspell/cspell-types": "8.8.1" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4704,73 +4868,124 @@ } }, "node_modules/cspell-io": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.6.1.tgz", - "integrity": "sha512-ofxBB8QtUPvh/bOwKLYsqU1hwQCet8E98jkn/5f4jtG+/x5Zd80I0Ez+tlbjiBmrrQfOKh+i8ipfzHD8JtoreQ==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.8.1.tgz", + "integrity": "sha512-qwKEV2kfwT9gbq6EpYt6gcEs0oe0sDPG1YJunt8niuX4YoBe7/9ZHBfUyqNOEA+sBmvI/tjY/Wy6g9mmSRaOYA==", "dev": true, "dependencies": { - "@cspell/cspell-service-bus": "8.6.1" + "@cspell/cspell-service-bus": "8.8.1" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.6.1.tgz", - "integrity": "sha512-kGeDUypRtThFT81IdUK7yU8eUwO5MYWj8pGQ0N8WFsqbCahJrUdcocceVSpnCX48W3CXu12DkqYG9kv5Umn7Xw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.8.1.tgz", + "integrity": "sha512-xntkgDGwDtUehM+fZudp4GbB87a2tY29G6ZqDF7WBcQsg3eyDVK/nc9KzbIfCvdWUCrsB9p+SGBoOmjYTwcocg==", "dev": true, "dependencies": { - "@cspell/cspell-bundled-dicts": "8.6.1", - "@cspell/cspell-pipe": "8.6.1", - "@cspell/cspell-resolver": "8.6.1", - "@cspell/cspell-types": "8.6.1", - "@cspell/dynamic-import": "8.6.1", - "@cspell/strong-weak-map": "8.6.1", + "@cspell/cspell-bundled-dicts": "8.8.1", + "@cspell/cspell-pipe": "8.8.1", + "@cspell/cspell-resolver": "8.8.1", + "@cspell/cspell-types": "8.8.1", + "@cspell/dynamic-import": "8.8.1", + "@cspell/strong-weak-map": "8.8.1", "clear-module": "^4.1.2", "comment-json": "^4.2.3", - "configstore": "^6.0.0", - "cspell-config-lib": "8.6.1", - "cspell-dictionary": "8.6.1", - "cspell-glob": "8.6.1", - "cspell-grammar": "8.6.1", - "cspell-io": "8.6.1", - "cspell-trie-lib": "8.6.1", + "cspell-config-lib": "8.8.1", + "cspell-dictionary": "8.8.1", + "cspell-glob": "8.8.1", + "cspell-grammar": "8.8.1", + "cspell-io": "8.8.1", + "cspell-trie-lib": "8.8.1", + "env-paths": "^3.0.0", "fast-equals": "^5.0.1", "gensequence": "^7.0.0", "import-fresh": "^3.3.0", "resolve-from": "^5.0.0", "vscode-languageserver-textdocument": "^1.0.11", - "vscode-uri": "^3.0.8" + "vscode-uri": "^3.0.8", + "xdg-basedir": "^5.1.0" }, "engines": { "node": ">=18" } }, "node_modules/cspell-trie-lib": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.6.1.tgz", - "integrity": "sha512-iuJuAyWoqTH/TpFAR/ISJGQQoW3oiw54GyvXIucPoCJt/jgQONDuzqPW+skiLvcgcTbXCN9dutZTb2gImIkmpw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.8.1.tgz", + "integrity": "sha512-S84XzQYGqKGApjVgamMp8tbHfKCeGZFxMwqedb4vxEJTYnUuCHaVPX2BK2SKaLSv/Vrd8mrJ/57sx5f8C44cFg==", "dev": true, "dependencies": { - "@cspell/cspell-pipe": "8.6.1", - "@cspell/cspell-types": "8.6.1", + "@cspell/cspell-pipe": "8.8.1", + "@cspell/cspell-types": "8.8.1", "gensequence": "^7.0.0" }, "engines": { "node": ">=18" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -4811,9 +5026,9 @@ } }, "node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" @@ -4824,6 +5039,25 @@ } } }, + "node_modules/deep-equal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "dependencies": { + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.5.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -4858,25 +5092,25 @@ } }, "node_modules/define-data-property": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", - "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", - "dev": true, + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.2", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -4925,6 +5159,28 @@ "node": ">=8" } }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + }, + "node_modules/dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dependencies": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==", + "dependencies": { + "buffer-indexof": "^1.0.0" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4958,10 +5214,18 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/electron-to-chromium": { - "version": "1.4.665", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.665.tgz", - "integrity": "sha512-UpyCWObBoD+nSZgOC2ToaIdZB0r9GhqT2WahPKiSki6ckkSuKhQNso8V2PrFcHBMleI/eqbKgVQgVC4Wni4ilw==", + "version": "1.4.775", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.775.tgz", + "integrity": "sha512-JpOfl1aNAiZ88wFzjPczTLwYIoPIsij8S9/XQH9lqMpiJOf23kxea68B8wje4f68t4rOIq4Bh+vP4I65njiJBw==", "dev": true }, "node_modules/emittery": { @@ -4993,12 +5257,15 @@ } }, "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", "dev": true, "engines": { - "node": ">=6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/err-code": { @@ -5017,50 +5284,57 @@ } }, "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -5069,30 +5343,46 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { + "node_modules/es-define-property": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { "node": ">= 0.4" } }, "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -5125,9 +5415,9 @@ } }, "node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "dev": true, "hasInstallScript": true, "bin": { @@ -5137,29 +5427,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/escalade": { @@ -5298,9 +5588,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -5407,9 +5697,9 @@ } }, "node_modules/eslint-plugin-jsonc": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.14.1.tgz", - "integrity": "sha512-Tei6G4N7pZulP5MHi0EIdtseiCqUPkDMd0O8Zrw4muMIlsjJ5/B9X+U3Pfo6B7l0mTL9LN9FwuWT70dRJ6z7tg==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.15.1.tgz", + "integrity": "sha512-PVFrqIJa8BbM/e828RSn0SwB/Z5ye+2LDuy2XqG6AymNgPsfApRRcznsbxP7VrjdLEU4Nb+g9n/d6opyp0jp9A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -5481,28 +5771,47 @@ } } }, + "node_modules/eslint-plugin-prettier/node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/eslint-plugin-security": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-2.1.1.tgz", - "integrity": "sha512-7cspIGj7WTfR3EhaILzAPcfCo5R9FbeWvbgsPYWivSurTBKW88VQxtP3c4aWMG9Hz/GfJlJVdXEJ3c8LqS+u2w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.0.tgz", + "integrity": "sha512-2Ij7PkmXIF2cKwoVkEgemwoXbOnxg5UfdhdcpNxZwJxC/10dbsdhHISrTyJ/n8DUkt3yiN6P1ywEgcMGjIwHIw==", "dev": true, "dependencies": { "safe-regex": "^2.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/eslint-plugin-simple-import-sort": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.0.0.tgz", - "integrity": "sha512-8o0dVEdAkYap0Cn5kNeklaKcT1nUsa3LITWEuFk3nJifOoD+5JQGoyDUW2W/iPWwBsNBJpyJS9y4je/BgxLcyQ==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.0.tgz", + "integrity": "sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig==", "dev": true, "peerDependencies": { "eslint": ">=5.0.0" } }, "node_modules/eslint-plugin-sonarjs": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.24.0.tgz", - "integrity": "sha512-87zp50mbbNrSTuoEOebdRQBPa0mdejA5UEjyuScyIw8hEpEjfWP89Qhkq5xVZfVyVSRQKZc9alVm7yRKQvvUmg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.25.1.tgz", + "integrity": "sha512-5IOKvj/GMBNqjxBdItfotfRHo7w48496GOu1hxdeXuD0mB1JBlDCViiLHETDTfA8pDAVSBimBEQoetRXYceQEw==", "dev": true, "engines": { "node": ">=16" @@ -5562,9 +5871,9 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "51.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-51.0.1.tgz", - "integrity": "sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==", + "version": "52.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-52.0.0.tgz", + "integrity": "sha512-1Yzm7/m+0R4djH0tjDjfVei/ju2w3AzUGjG6q8JnuNIL5xIwsflyCooW5sfBvQp2pMYQFSWWCFONsjCax1EHng==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -5774,6 +6083,45 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -5805,11 +6153,20 @@ "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", "dev": true }, + "node_modules/fast-content-type-parse": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz", + "integrity": "sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==" + }, + "node_modules/fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -5860,6 +6217,70 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fast-json-stringify": { + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.15.1.tgz", + "integrity": "sha512-JopGtkvvguRqrS4gHXSSA2jf4pDgOZkeBAkLO1LbzOpiOMo7/kugoR+KiWifpLpluaVeYDkAuxCJOj4Gyc6L9A==", + "dependencies": { + "@fastify/merge-json-schemas": "^0.1.0", + "ajv": "^8.10.0", + "ajv-formats": "^3.0.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^2.1.0", + "json-schema-ref-resolver": "^1.0.1", + "rfdc": "^1.2.0" + } + }, + "node_modules/fast-json-stringify/node_modules/ajv": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fast-json-stringify/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/fast-json-stringify/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/fast-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/fast-jwt/-/fast-jwt-4.0.1.tgz", + "integrity": "sha512-+mdSoH0QdOdFSbbGBctJu7L1yfXRtbmjbVJ4W/PEjyvivobDena0RKwihtBkOML1P+kUJ1QuewnH8u+mROsR1w==", + "dependencies": { + "@lukeed/ms": "^2.0.1", + "asn1.js": "^5.4.1", + "ecdsa-sig-formatter": "^1.0.11", + "mnemonist": "^0.39.5" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", @@ -5872,15 +6293,102 @@ "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==", "dev": true }, + "node_modules/fast-querystring": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "dependencies": { + "fast-decode-uri-component": "^1.0.1" + } + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-uri": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.3.0.tgz", + "integrity": "sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==" + }, + "node_modules/fastfall": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/fastfall/-/fastfall-1.5.1.tgz", + "integrity": "sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==", + "dependencies": { + "reusify": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fastify": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.27.0.tgz", + "integrity": "sha512-ci9IXzbigB8dyi0mSy3faa3Bsj0xWAPb9JeT4KRzubdSb6pNhcADRUaXCBml6V1Ss/a05kbtQls5LBmhHydoTA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "dependencies": { + "@fastify/ajv-compiler": "^3.5.0", + "@fastify/error": "^3.4.0", + "@fastify/fast-json-stringify-compiler": "^4.3.0", + "abstract-logging": "^2.0.1", + "avvio": "^8.3.0", + "fast-content-type-parse": "^1.1.0", + "fast-json-stringify": "^5.8.0", + "find-my-way": "^8.0.0", + "light-my-request": "^5.11.0", + "pino": "^9.0.0", + "process-warning": "^3.0.0", + "proxy-addr": "^2.0.7", + "rfdc": "^1.3.0", + "secure-json-parse": "^2.7.0", + "semver": "^7.5.4", + "toad-cache": "^3.3.0" + } + }, + "node_modules/fastify-plugin": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz", + "integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==" + }, + "node_modules/fastparallel": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.1.tgz", + "integrity": "sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==", + "dependencies": { + "reusify": "^1.0.4", + "xtend": "^4.0.2" + } + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/fastseries": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-1.7.2.tgz", + "integrity": "sha512-dTPFrPGS8SNSzAt7u/CbMKCJ3s01N04s4JFbORHcmyvVfVKmbhMD1VtRbh5enGHxkaQDqWyLefiKOGGmohGDDQ==", + "dependencies": { + "reusify": "^1.0.0", + "xtend": "^4.0.0" + } + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -5914,6 +6422,19 @@ "node": ">=8" } }, + "node_modules/find-my-way": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-8.2.0.tgz", + "integrity": "sha512-HdWXgFYc6b1BJcOBDBwjqWuHJj1WYiqrxSh25qtU4DabpMFdj/gSunNBQb83t+8Zt67D7CXEzJWTkxaShMTMOA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-querystring": "^1.0.0", + "safe-regex2": "^3.1.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -5945,9 +6466,9 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/for-each": { @@ -5996,6 +6517,14 @@ "node": ">= 14.17" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fp-and-or": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/fp-and-or/-/fp-and-or-0.1.4.tgz", @@ -6018,9 +6547,9 @@ } }, "node_modules/fs-minipass/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", + "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -6050,7 +6579,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6077,7 +6605,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6086,6 +6613,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", "dev": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", @@ -6141,7 +6669,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -6207,9 +6734,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", "dev": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -6287,6 +6814,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/global-directory/node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -6339,12 +6875,13 @@ } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -6377,7 +6914,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -6450,22 +6986,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -6477,7 +7011,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -6489,7 +7022,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -6519,10 +7051,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", - "dev": true, + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -6603,6 +7134,15 @@ "node": ">= 6" } }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -6625,6 +7165,25 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -6635,9 +7194,9 @@ } }, "node_modules/ignore-walk": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.4.tgz", - "integrity": "sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", + "integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==", "dev": true, "dependencies": { "minimatch": "^9.0.0" @@ -6712,9 +7271,9 @@ } }, "node_modules/import-meta-resolve": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", - "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", "dev": true, "funding": { "type": "github", @@ -6758,14 +7317,12 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", - "dev": true, + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", + "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -6785,10 +7342,45 @@ } }, "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==" + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/is-array-buffer": { "version": "3.0.4", @@ -6906,11 +7498,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -6983,9 +7589,9 @@ "dev": true }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -7052,7 +7658,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -7065,15 +7670,30 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-string": { @@ -7170,14 +7790,14 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", - "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", "dev": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", "istanbul-lib-coverage": "^3.2.0", "semver": "^7.5.4" }, @@ -7214,9 +7834,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -7284,95 +7904,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-changed-files/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/jest-changed-files/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/jest-changed-files/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/jest-changed-files/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-changed-files/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/jest-circus": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", @@ -8627,6 +9158,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, "node_modules/jsesc": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", @@ -8660,6 +9197,14 @@ "jju": "^1.1.0" } }, + "node_modules/json-schema-ref-resolver": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz", + "integrity": "sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -8772,6 +9317,16 @@ "node": ">= 0.8.0" } }, + "node_modules/light-my-request": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.13.0.tgz", + "integrity": "sha512-9IjUN9ZyCS9pTG+KqTDEQo68Sui2lHsYBrfMyVUTTZ3XhH8PMZq7xO94Kr+eP9dhi/kcKsx4N41p2IXEBil1pQ==", + "dependencies": { + "cookie": "^0.6.0", + "process-warning": "^3.0.0", + "set-cookie-parser": "^2.4.1" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -8832,12 +9387,6 @@ "yallist": "^3.0.2" } }, - "node_modules/lru-cache/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -8931,6 +9480,15 @@ "node": ">=8.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/mimic-response": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", @@ -8952,10 +9510,15 @@ "node": ">=4" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -9008,10 +9571,16 @@ "node": ">=8" } }, + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", + "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", "dev": true, "dependencies": { "minipass": "^7.0.3", @@ -9026,9 +9595,9 @@ } }, "node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", + "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -9058,6 +9627,12 @@ "node": ">=8" } }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/minipass-json-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", @@ -9080,6 +9655,12 @@ "node": ">=8" } }, + "node_modules/minipass-json-stream/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", @@ -9104,6 +9685,12 @@ "node": ">=8" } }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", @@ -9128,6 +9715,12 @@ "node": ">=8" } }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", @@ -9153,6 +9746,12 @@ "node": ">=8" } }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -9165,11 +9764,35 @@ "node": ">=10" } }, + "node_modules/mnemonist": { + "version": "0.39.8", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.8.tgz", + "integrity": "sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ==", + "dependencies": { + "obliterator": "^2.0.1" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dependencies": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -9208,14 +9831,6 @@ "node": ">=6.0.0" } }, - "node_modules/node-cron/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/node-gyp": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", @@ -9302,6 +9917,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/node-gyp/node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/node-gyp/node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -9427,6 +10051,12 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -9500,9 +10130,9 @@ } }, "node_modules/normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", "dev": true, "engines": { "node": ">=14.16" @@ -9512,9 +10142,9 @@ } }, "node_modules/npm-bundled": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", - "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", + "integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==", "dev": true, "dependencies": { "npm-normalize-package-bin": "^3.0.0" @@ -9524,9 +10154,9 @@ } }, "node_modules/npm-check-updates": { - "version": "16.14.18", - "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-16.14.18.tgz", - "integrity": "sha512-9iaRe9ohx9ykdbLjPRIYcq1A0RkrPYUx9HmQK1JIXhfxtJCNE/+497H9Z4PGH6GWRALbz5KF+1iZoySK2uSEpQ==", + "version": "16.14.20", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-16.14.20.tgz", + "integrity": "sha512-sYbIhun4DrjO7NFOTdvs11nCar0etEhZTsEjL47eM0TuiGMhmYughRCxG2SpGRmGAQ7AkwN7bw2lWzoE7q6yOQ==", "dev": true, "dependencies": { "@types/semver-utils": "^1.1.1", @@ -9584,31 +10214,40 @@ } }, "node_modules/npm-check-updates/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.3.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz", + "integrity": "sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", + "jackspeak": "^2.3.6", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "minipass": "^7.0.4", + "path-scurry": "^1.11.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/npm-check-updates/node_modules/minipass": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", + "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/npm-check-updates/node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", + "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", "dev": true, "dependencies": { "glob": "^10.3.7" @@ -9617,7 +10256,7 @@ "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": ">=14" + "node": ">=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -9762,10 +10401,23 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/npmlog": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", "dev": true, "dependencies": { "are-we-there-yet": "^3.0.0", @@ -9786,11 +10438,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -9814,14 +10480,15 @@ } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -9831,27 +10498,28 @@ } }, "node_modules/object.groupby": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", - "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "dependencies": { - "array.prototype.filter": "^1.0.3", - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0" + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -9860,6 +10528,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obliterator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -9869,18 +10550,33 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -10075,25 +10771,25 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -10109,9 +10805,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "node_modules/picomatch": { @@ -10126,6 +10822,56 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pino": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.1.0.tgz", + "integrity": "sha512-qUcgfrlyOtjwhNLdbhoL7NR4NkHjzykAPw0V2QLFbvu/zss29h4NkRnibyFzBrNCbzCOY3WZ9hhKSwfOkNggYA==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -10208,6 +10954,15 @@ "node": ">=4" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -10267,6 +11022,19 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -10277,9 +11045,9 @@ } }, "node_modules/prom-client": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.0.tgz", - "integrity": "sha512-cCD7jLTqyPdjEPBo/Xk4Iu8jxjuZgZJ3e/oET3L+ZwOuap/7Cw3dH/TJSsZKs1TQLZ2IHpIlRAKw82ef06kmMw==", + "version": "15.1.2", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.2.tgz", + "integrity": "sha512-on3h1iXb04QFLLThrmVYg1SChBQ9N1c+nKAjebBjokBqipddH3uxmOUcEkTnzmJ8Jh/5TSUnUqS40i2QB2dJHQ==", "dependencies": { "@opentelemetry/api": "^1.4.0", "tdigest": "^0.1.1" @@ -10348,11 +11116,22 @@ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", "dev": true }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "engines": { "node": ">=6" } @@ -10373,9 +11152,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { @@ -10408,6 +11187,11 @@ } ] }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", @@ -10463,15 +11247,16 @@ } }, "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, "node_modules/read-package-json": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", + "deprecated": "This package is no longer supported. Please use @npmcli/package-json instead.", "dev": true, "dependencies": { "glob": "^10.2.2", @@ -10497,45 +11282,54 @@ } }, "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/read-package-json/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.3.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz", + "integrity": "sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", + "jackspeak": "^2.3.6", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "minipass": "^7.0.4", + "path-scurry": "^1.11.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/read-package-json/node_modules/minipass": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", + "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -10665,14 +11459,36 @@ "node": ">=8" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/redis": { - "version": "4.6.13", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.13.tgz", - "integrity": "sha512-MHgkS4B+sPjCXpf+HfdetBwbRz6vCtsceTmw1pHNYJAsYxrfpOP6dz+piJWGos8wqG7qb3vj/Rrc5qOlmInUuA==", + "version": "4.6.14", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.14.tgz", + "integrity": "sha512-GrNg/e33HtsQwNXL7kJT+iNFPSwE1IPmd7wzV3j4f2z0EYxZfZE7FVTmUysgAtqQQtg5NXF5SNLR9OdO/UHOfw==", "optional": true, "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.14", + "@redis/client": "1.5.16", "@redis/graph": "1.1.1", "@redis/json": "1.0.6", "@redis/search": "1.1.6", @@ -10692,7 +11508,6 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, "dependencies": { "call-bind": "^1.0.6", "define-properties": "^1.2.1", @@ -10785,7 +11600,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -10876,6 +11690,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ret": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.4.3.tgz", + "integrity": "sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -10889,12 +11711,16 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -10934,13 +11760,13 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -10955,7 +11781,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -10997,21 +11822,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-regex2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-3.1.0.tgz", + "integrity": "sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==", + "dependencies": { + "ret": "~0.4.0" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "optional": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "bin": { "semver": "bin/semver.js" }, @@ -11040,50 +11880,42 @@ "integrity": "sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==", "dev": true }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" + }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "dev": true, + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -11111,12 +11943,12 @@ } }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -11179,16 +12011,16 @@ } }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dev": true, "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -11206,6 +12038,14 @@ "node": ">= 10" } }, + "node_modules/sonic-boom": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", + "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -11248,9 +12088,9 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz", - "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -11269,16 +12109,24 @@ "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, "node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", "dev": true, "dependencies": { "minipass": "^7.0.3" @@ -11288,9 +12136,9 @@ } }, "node_modules/ssri/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", + "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -11317,11 +12165,22 @@ "node": ">=8" } }, + "node_modules/steed": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/steed/-/steed-1.1.3.tgz", + "integrity": "sha512-EUkci0FAUiE4IvGTSKcDJIQ/eRUP2JJb56+fvZ4sdnguLTqIdKjSxUe138poW8mkvKWXW2sFPrgTsxqoISnmoA==", + "dependencies": { + "fastfall": "^1.5.0", + "fastparallel": "^2.2.0", + "fastq": "^1.3.0", + "fastseries": "^1.7.0", + "reusify": "^1.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -11369,14 +12228,15 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -11386,28 +12246,31 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11447,6 +12310,15 @@ "node": ">=8" } }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -11496,9 +12368,9 @@ } }, "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.0.tgz", + "integrity": "sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==", "dev": true, "dependencies": { "@pkgr/core": "^0.1.0", @@ -11512,9 +12384,9 @@ } }, "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "dependencies": { "chownr": "^2.0.0", @@ -11552,6 +12424,12 @@ "node": ">=8" } }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/tdigest": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", @@ -11602,6 +12480,19 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thread-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.0.0.tgz", + "integrity": "sha512-oUIFjxaUT6knhPtWgDMc29zF1FcSl0yXpapkyrQrCGEfYA2HUZXCilUtKyYIv6HkCyqSPAMkY+EG0GbyIrNDQg==", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -11629,10 +12520,18 @@ "node": ">=8.0" } }, + "node_modules/toad-cache": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", + "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==", + "engines": { + "node": ">=12" + } + }, "node_modules/ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { "node": ">=16" @@ -11724,13 +12623,13 @@ "dev": true }, "node_modules/tsx": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.1.tgz", - "integrity": "sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==", + "version": "4.10.5", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.10.5.tgz", + "integrity": "sha512-twDSbf7Gtea4I2copqovUiNTEDrT8XNFXsuHpfGbdpW/z9ZW4fTghzzhAG0WfrCuJmJiOEY1nLIjq4u3oujRWQ==", "dev": true, "dependencies": { - "esbuild": "~0.19.10", - "get-tsconfig": "^4.7.2" + "esbuild": "~0.20.2", + "get-tsconfig": "^4.7.5" }, "bin": { "tsx": "dist/cli.mjs" @@ -11778,9 +12677,9 @@ } }, "node_modules/type-fest": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.14.0.tgz", - "integrity": "sha512-on5/Cw89wwqGZQu+yWO0gGMGu8VNxsaW9SB2HE8yJjllEk7IDTwnSN1dUVldYILhYPN5HzD7WAaw2cc/jBfn0Q==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.18.2.tgz", + "integrity": "sha512-+suCYpfJLAe4OXS6+PPXjW3urOS4IoP9waSiLuXfLgqZODKw/aWwASvzqE886wA0kQgGy0mIWyhd87VpqIy6Xg==", "dev": true, "engines": { "node": ">=16" @@ -11790,12 +12689,12 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz", - "integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "is-typed-array": "^1.1.13" }, @@ -11804,15 +12703,16 @@ } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -11822,16 +12722,17 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -11841,14 +12742,20 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11864,9 +12771,9 @@ } }, "node_modules/typescript": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", - "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -11946,9 +12853,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "dev": true, "funding": [ { @@ -11965,8 +12872,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -12007,7 +12914,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -12018,6 +12924,14 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-to-istanbul": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", @@ -12043,13 +12957,10 @@ } }, "node_modules/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true, - "dependencies": { - "builtins": "^5.0.0" - }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -12107,16 +13018,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -12199,6 +13110,15 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -12336,21 +13256,22 @@ "dev": true }, "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", "engines": { "node": ">=10.0.0" }, @@ -12379,6 +13300,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -12389,15 +13318,15 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "devOptional": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yaml": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", - "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz", + "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==", "dev": true, "bin": { "yaml": "bin.mjs" diff --git a/package.json b/package.json index f637127..d508599 100644 --- a/package.json +++ b/package.json @@ -2,13 +2,13 @@ "name": "@digital-alchemy/synapse", "repository": "https://github.com/Digital-Alchemy-TS/synapse", "homepage": "https://docs.digital-alchemy.app/Synapse", - "version": "0.3.5", + "version": "0.3.6", "scripts": { "build": "rm -rf dist; tsc", "test": "./scripts/test.sh", "lint": "eslint src", "prepublishOnly": "npm run build", - "upgrade": "ncu -u; npm i" + "upgrade": "ncu -u -f '@digital-alchemy/*'; npm i" }, "author": { "url": "https://github.com/zoe-codez", @@ -25,42 +25,43 @@ }, "license": "MIT", "dependencies": { - "@digital-alchemy/core": "^0.3.8", - "@digital-alchemy/hass": "^0.3.7", - "dayjs": "^1.11.10", - "prom-client": "^15.1.0", - "ws": "^8.16.0" + "@digital-alchemy/core": "^0.3.16", + "@digital-alchemy/fastify-extension": "^0.3.3", + "@digital-alchemy/hass": "^0.3.30", + "bonjour": "^3.5.0", + "dayjs": "^1.11.11" }, "devDependencies": { - "@cspell/eslint-plugin": "^8.6.1", + "@cspell/eslint-plugin": "^8.8.1", + "@types/bonjour": "^3.5.13", "@types/figlet": "^1.5.8", "@types/jest": "^29.5.12", "@types/js-yaml": "^4.0.9", "@types/minimist": "^1.2.5", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.11.30", + "@types/node": "^20.12.12", "@types/uuid": "^9.0.8", "@types/ws": "^8.5.10", - "@typescript-eslint/eslint-plugin": "7.4.0", - "@typescript-eslint/parser": "7.4.0", + "@typescript-eslint/eslint-plugin": "7.9.0", + "@typescript-eslint/parser": "7.9.0", "eslint": "8.57.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsonc": "^2.14.1", + "eslint-plugin-jsonc": "^2.15.1", "eslint-plugin-no-unsanitized": "^4.0.2", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-security": "^2.1.1", - "eslint-plugin-simple-import-sort": "^12.0.0", - "eslint-plugin-sonarjs": "^0.24.0", + "eslint-plugin-security": "^3.0.0", + "eslint-plugin-simple-import-sort": "^12.1.0", + "eslint-plugin-sonarjs": "^0.25.1", "eslint-plugin-sort-keys-fix": "^1.1.2", - "eslint-plugin-unicorn": "^51.0.1", + "eslint-plugin-unicorn": "^52.0.0", "jest": "^29.7.0", "jest-environment-node": "^29.7.0", - "npm-check-updates": "^16.14.18", + "npm-check-updates": "^16.14.20", "prettier": "^3.2.5", "ts-jest": "^29.1.2", - "tsx": "^4.7.1", - "type-fest": "^4.14.0", - "typescript": "^5.4.3" + "tsx": "^4.10.3", + "type-fest": "^4.18.2", + "typescript": "^5.4.5" } } diff --git a/src/extensions/binary-sensor.extension.ts b/src/extensions/binary-sensor.extension.ts deleted file mode 100644 index a5e7d80..0000000 --- a/src/extensions/binary-sensor.extension.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { - each, - is, - TBlackHole, - TContext, - TServiceParams, -} from "@digital-alchemy/core"; - -import { OnOff } from ".."; - -type TBinarySensor = { - context: TContext; - defaultState?: OnOff; - icon?: string; - name: string; -}; - -export type VirtualBinarySensor = { - state: OnOff; - name: string; - icon: string; - onUpdate: (callback: BinarySensorUpdateCallback) => void; - on: boolean; -}; -type BinarySensorUpdateCallback = (state: boolean) => TBlackHole; - -export function BinarySensor({ - logger, - context, - lifecycle, - internal, - synapse, -}: TServiceParams) { - const callbacks = [] as BinarySensorUpdateCallback[]; - - const registry = synapse.registry({ - context, - details: item => ({ state: item.state }), - domain: "binary_sensor", - }); - - // # Binary sensor entity creation function - function create(entity: TBinarySensor) { - let state: OnOff; - - // ## Handle state updates. Ignore non-updates - async function setState(newState: OnOff) { - if (newState === state) { - return; - } - state = newState; - setImmediate(async () => { - logger.trace( - { - name: entity.context, - sensor: entity.name, - }, - `syncing state`, - ); - await registry.setCache(id, state); - await registry.send(id, { state }); - await each( - callbacks, - async callback => - await internal.safeExec(async () => await callback(state === "on")), - ); - }); - } - - // ## Wait until bootstrap to load cache - lifecycle.onBootstrap(async () => { - state = await registry.getCache(id); - if (is.undefined(state)) { - state = entity.defaultState || "off"; - registry.loadFromHass<{ state: OnOff }>(id, data => { - if (is.empty(data)) { - // wat - return; - } - logger.debug({ data, id, name: entity.name }, `received value`); - state = data.state; - }); - } - }); - - // ## Proxy object as return - const out = new Proxy({} as VirtualBinarySensor, { - get(_, property: keyof VirtualBinarySensor) { - if (property === "state") { - return state; - } - if (property === "on") { - return state === "on"; - } - if (property === "icon") { - return entity.icon; - } - if (property === "onUpdate") { - return (callback: BinarySensorUpdateCallback) => - callbacks.push(callback); - } - if (property === "name") { - return entity.name; - } - return undefined; - }, - set(_, property: keyof VirtualBinarySensor, value: unknown) { - if (property === "state") { - setState(value as OnOff); - return true; - } - if (property === "on") { - setState(value ? "on" : "off"); - return true; - } - return false; - }, - }); - const id = registry.add(out); - return out; - } - - return create; -} diff --git a/src/extensions/button.extension.ts b/src/extensions/button.extension.ts deleted file mode 100644 index 15c1748..0000000 --- a/src/extensions/button.extension.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { TBlackHole, TContext, TServiceParams } from "@digital-alchemy/core"; - -import { - BUTTON_ERRORS, - BUTTON_EXECUTION_COUNT, - BUTTON_EXECUTION_TIME, -} from ".."; - -type TButton = { - exec: () => TBlackHole; - context: TContext; - label?: string; - icon?: string; - name: string; -}; - -type HassButtonUpdateEvent = { - event_type: "digital_alchemy_activate"; - data: { id: string }; -}; - -export function Button({ - logger, - hass, - context, - synapse, - internal, -}: TServiceParams) { - const registry = synapse.registry({ - context, - domain: "button", - }); - - // ### Listen for socket events - hass.socket.onEvent({ - context: context, - event: "digital_alchemy_activate", - exec({ data }: HassButtonUpdateEvent) { - const item = registry.byId(data.id); - if (!item) { - return; - } - const { exec, context, label, name } = item; - logger.trace({ data, label: name }, `received button press`); - setImmediate(async () => { - await internal.safeExec({ - duration: BUTTON_EXECUTION_TIME, - errors: BUTTON_ERRORS, - exec: async () => await exec(), - executions: BUTTON_EXECUTION_COUNT, - labels: { context, label }, - }); - }); - }, - }); - - /** - * ### Register a new button - * - * Can be called from construction phase - bootstrap. - * Auto syncs with home assistant onReady, and will emit warnings for new buttons after. - * - * Warnings indicate that a manual update of the integration may be required. - */ - return function create(entity: TButton) { - registry.add(entity); - }; -} diff --git a/src/extensions/configure.extension.ts b/src/extensions/configure.extension.ts new file mode 100644 index 0000000..135397a --- /dev/null +++ b/src/extensions/configure.extension.ts @@ -0,0 +1,40 @@ +import { is, TServiceParams } from "@digital-alchemy/core"; +import { networkInterfaces } from "os"; + +const EXTRA_EARLY = 1000; + +function getLocalIPAddress(): string | undefined { + const interfaces = networkInterfaces(); + for (const interfaceName in interfaces) { + const addresses = interfaces[interfaceName]; + if (addresses) { + for (const addressInfo of addresses) { + if (addressInfo.family === "IPv4" && !addressInfo.internal) { + return addressInfo.address; + } + } + } + } + return undefined; +} + +export function Configure({ lifecycle, config, logger, internal }: TServiceParams) { + // setting up the default that can't be declared at the module level + lifecycle.onPreInit(() => { + if (is.empty(config.synapse.METADATA_TITLE)) { + const { name } = internal.boot.application; + logger.debug({ METADATA_TITLE: name, name: "onPreInit" }, `updating [METADATA_TITLE]`); + internal.boilerplate.configuration.set("synapse", "METADATA_TITLE", name); + } + }); + + // Mental note: + // This needs to happen in the `onPostConfig` step because the fastify port may change + lifecycle.onPostConfig(() => { + if (is.empty(config.synapse.METADATA_HOST)) { + const METADATA_HOST = `${getLocalIPAddress()}:${config.fastify.PORT}`; + logger.debug({ METADATA_HOST, name: "onPostConfig" }, `updating [METADATA_HOST]`); + internal.boilerplate.configuration.set("synapse", "METADATA_HOST", METADATA_HOST); + } + }, EXTRA_EARLY); +} diff --git a/src/extensions/controller.extension.ts b/src/extensions/controller.extension.ts new file mode 100644 index 0000000..d590b67 --- /dev/null +++ b/src/extensions/controller.extension.ts @@ -0,0 +1,22 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { hostname, userInfo } from "os"; + +import { SynapseDescribeResponse } from "../helpers"; + +export function Controller({ fastify, config, synapse, logger, internal }: TServiceParams) { + fastify.routes(server => { + server.get("/synapse", (): SynapseDescribeResponse => { + logger.info(`describe app`); + return { + app: internal.boot.application.name, + device: synapse.device.getInfo(), + host: config.synapse.METADATA_HOST, + hostname: hostname(), + title: config.synapse.METADATA_TITLE, + unique_id: config.synapse.METADATA_UNIQUE_ID, + username: userInfo().username, + ...synapse.storage.dump(), + }; + }); + }); +} diff --git a/src/extensions/device.extension.ts b/src/extensions/device.extension.ts new file mode 100644 index 0000000..6cb3c03 --- /dev/null +++ b/src/extensions/device.extension.ts @@ -0,0 +1,34 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { existsSync, readFileSync } from "fs"; +import { join } from "path"; + +import { HassDeviceMetadata } from "../helpers"; + +export function DeviceExtension({ config, lifecycle, logger, internal }: TServiceParams) { + let synapseVersion: string; + + lifecycle.onPostConfig(() => { + const file = join(__dirname, "..", "..", "package.json"); + if (existsSync(file)) { + logger.trace("loading package"); + try { + const contents = readFileSync(file, "utf8"); + const data = JSON.parse(contents) as { version: string }; + synapseVersion = data?.version; + } catch (error) { + logger.error(error); + } + } + }); + + return { + getInfo(): HassDeviceMetadata { + return { + manufacturer: "Digital Alchemy", + name: internal.boot.application.name, + sw_version: synapseVersion, + ...config.synapse.METADATA, + }; + }, + }; +} diff --git a/src/extensions/discovery.extension.ts b/src/extensions/discovery.extension.ts new file mode 100644 index 0000000..d83ea8e --- /dev/null +++ b/src/extensions/discovery.extension.ts @@ -0,0 +1,45 @@ +import { is, TServiceParams } from "@digital-alchemy/core"; +import Bonjour from "bonjour"; +import { createHash } from "crypto"; +import { hostname, userInfo } from "os"; + +export function DiscoveryExtension({ config, lifecycle, logger, internal }: TServiceParams) { + let bonjour: Bonjour.Bonjour; + function uniqueProperties(): string[] { + return [hostname(), userInfo().username, internal.boot.application.name]; + } + + // Create a UNIQUE_ID, if one is not provided via .bootstrap() + lifecycle.onPreInit(() => { + if (is.empty(config.synapse.METADATA_UNIQUE_ID)) { + internal.boilerplate.configuration.set( + "synapse", + "METADATA_UNIQUE_ID", + createHash("md5").update(uniqueProperties().join("-")).digest("hex"), + ); + } + }); + + // lifecycle.onReady(() => { + // logger.info("WAT"); + // }); + + lifecycle.onPostConfig(() => { + if (!config.synapse.PUBLISH_BONJOUR) { + return; + } + logger.warn("zeroconf not currently available - [soon] {(tm)}"); + // logger.info({ name: "onPostConfig" }, `publishing`); + // bonjour = Bonjour(); + // bonjour.publish({ + // name: internal.boot.application.name, + // port: config.fastify.PORT, + // txt: { UNIQUE_ID: config.synapse.METADATA_UNIQUE_ID }, + // type: "da_synapse", + // }); + }); + + lifecycle.onShutdownStart(() => { + bonjour?.destroy(); + }); +} diff --git a/src/extensions/domains/alarm-control-panel.extension.ts b/src/extensions/domains/alarm-control-panel.extension.ts new file mode 100644 index 0000000..935d219 --- /dev/null +++ b/src/extensions/domains/alarm-control-panel.extension.ts @@ -0,0 +1,89 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type AlarmControlPanelStates = + | "disarmed" + | "armed_home" + | "armed_away" + | "armed_night" + | "armed_vacation" + | "armed_custom_bypass" + | "pending" + | "arming" + | "disarming" + | "triggered"; + +type EntityConfiguration = { + state?: AlarmControlPanelStates; + /** + * Whether the code is required for arm actions. + * + * default: true + */ + code_arm_required?: boolean; + /** + * One of the states listed in the code formats section. + */ + code_format?: "number" | "text"; + /** + * Last change triggered by. + */ + changed_by?: string; + supported_features?: number; + /** + * default: true + */ + managed?: boolean; +}; + +type EntityEvents = { + arm_custom_bypass: { code: string }; + trigger: { code: string }; + arm_vacation: { code: string }; + arm_night: { code: string }; + arm_away: { code: string }; + arm_home: { code: string }; + alarm_disarm: { code: string }; +}; + +export function VirtualAlarmControlPanel({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: [ + "arm_custom_bypass", + "trigger", + "arm_vacation", + "arm_night", + "arm_away", + "arm_home", + "alarm_disarm", + ], + context, + // @ts-expect-error its fine + domain: "alarm_control_panel", + load_config_keys: [ + "state", + "code_arm_required", + "code_format", + "changed_by", + "supported_features", + ], + }); + + return function ({ + managed = true, + ...options + }: AddEntityOptions) { + const entity = generate.add_entity(options); + if (managed) { + entity.onArmCustomBypass(() => entity.storage.set("state", "armed_away")); + entity.onTrigger(() => entity.storage.set("state", "triggered")); + entity.onArmVacation(() => entity.storage.set("state", "armed_vacation")); + entity.onArmNight(() => entity.storage.set("state", "armed_night")); + entity.onArmAway(() => entity.storage.set("state", "armed_away")); + entity.onArmHome(() => entity.storage.set("state", "armed_home")); + entity.onAlarmDisarm(() => entity.storage.set("state", "disarmed")); + } + return entity; + }; +} diff --git a/src/extensions/domains/binary-sensor.extension.ts b/src/extensions/domains/binary-sensor.extension.ts new file mode 100644 index 0000000..d9c8b83 --- /dev/null +++ b/src/extensions/domains/binary-sensor.extension.ts @@ -0,0 +1,33 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { BinarySensorDeviceClass } from "@digital-alchemy/hass"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * Type of binary sensor. + */ + device_class?: `${BinarySensorDeviceClass}`; + /** + * If the binary sensor is currently on or off. + */ + is_on?: boolean; +}; + +type EntityEvents = { + // +}; + +export function VirtualBinarySensor({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + context, + default_config: { is_on: false }, + domain: "binary_sensor", + load_config_keys: ["device_class", "is_on"], + map_config: [{ key: "is_on", load: entity => entity.state === "on" }], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/button.extension.ts b/src/extensions/domains/button.extension.ts new file mode 100644 index 0000000..be111f1 --- /dev/null +++ b/src/extensions/domains/button.extension.ts @@ -0,0 +1,28 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { ButtonDeviceClass } from "@digital-alchemy/hass"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + device_class?: `${ButtonDeviceClass}`; +}; + +type EntityEvents = { + press: { + // + }; +}; + +export function VirtualButton({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["press"], + context, + // @ts-expect-error its fine + domain: "button", + load_config_keys: ["device_class"], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/camera.extension.ts b/src/extensions/domains/camera.extension.ts new file mode 100644 index 0000000..e980bd7 --- /dev/null +++ b/src/extensions/domains/camera.extension.ts @@ -0,0 +1,83 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * The brand (manufacturer) of the camera. + */ + brand?: string; + /** + * The interval between frames of the stream. + */ + frame_interval?: number; + /** + * Used with CameraEntityFeature.STREAM to tell the frontend which type of stream to use (StreamType.HLS or StreamType.WEB_RTC) + */ + frontend_stream_type?: string; + /** + * Indication of whether the camera is on. + */ + is_on?: boolean; + /** + * Indication of whether the camera is recording. Used to determine state. + */ + is_recording?: boolean; + /** + * Indication of whether the camera is streaming. Used to determine state. + */ + is_streaming?: boolean; + /** + * The model of the camera. + */ + model?: string; + /** + * Indication of whether the camera has motion detection enabled. + */ + motion_detection_enabled?: boolean; + /** + * Determines whether or not to use the Stream integration to generate still images + */ + use_stream_for_stills?: boolean; + supported_features?: number; +}; + +type EntityEvents = { + turn_on: { + // + }; + turn_off: { + // + }; + enable_motion_detection: { + // + }; + disable_motion_detection: { + // + }; +}; + +export function VirtualCamera({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["turn_on", "turn_off", "enable_motion_detection", "disable_motion_detection"], + context, + // @ts-expect-error its fine + domain: "camera", + load_config_keys: [ + "brand", + "frame_interval", + "frontend_stream_type", + "is_on", + "is_recording", + "is_streaming", + "model", + "motion_detection_enabled", + "use_stream_for_stills", + "supported_features", + ], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/climate.extension.ts b/src/extensions/domains/climate.extension.ts new file mode 100644 index 0000000..713917b --- /dev/null +++ b/src/extensions/domains/climate.extension.ts @@ -0,0 +1,172 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { HVACAction, HVACMode } from "@digital-alchemy/hass"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * The current humidity. + */ + current_humidity?: number; + /** + * The current temperature. + */ + current_temperature?: number; + /** + * The current fan mode. + */ + fan_mode?: string; + /** + * The list of available fan modes. + */ + fan_modes?: string[]; + /** + * The current HVAC action (heating, cooling) + */ + hvac_action?: HVACAction; + /** + * The current operation (e.g. heat, cool, idle). Used to determine state. + */ + hvac_mode: HVACMode; + /** + * List of available operation modes. + */ + hvac_modes: HVACMode[]; + /** + * The maximum humidity. + */ + max_humidity?: number; + /** + * The maximum temperature in temperature_unit. + */ + max_temp?: number; + /** + * The minimum humidity. + */ + min_humidity?: number; + /** + * The minimum temperature in temperature_unit. + */ + min_temp?: number; + /** + * The precision of the temperature in the system. Defaults to tenths for TEMP_CELSIUS, whole number otherwise. + */ + precision?: number; + /** + * The current active preset. + */ + preset_mode?: string; + /** + * The available presets. + */ + preset_modes?: string[]; + /** + * The swing setting. + */ + swing_mode?: string; + /** + * Returns the list of available swing modes. + */ + swing_modes?: string[]; + /** + * The target humidity the device is trying to reach. + */ + target_humidity?: number; + /** + * The temperature currently set to be reached. + */ + target_temperature_high?: number; + /** + * The upper bound target temperature + */ + target_temperature_low?: number; + /** + * The lower bound target temperature + */ + target_temperature_step?: number; + /** + * The supported step size a target temperature can be increased or decreased + */ + target_temperature?: number; + /** + * The unit of temperature measurement for the system (TEMP_CELSIUS or TEMP_FAHRENHEIT). + */ + temperature_unit: string; +}; + +type EntityEvents = { + set_hvac_mode: { + // + }; + turn_on: { + // + }; + turn_off: { + // + }; + toggle: { + // + }; + set_preset_mode: { + preset_mode: string; + }; + set_fan_mode: { + fan_mode: string; + }; + set_humidity: { + humidity: number; + }; + set_swing_mode: { + swing_mode: string; + }; + set_temperature: { + humidity: number; + }; +}; + +export function VirtualClimate({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: [ + "set_hvac_mode", + "turn_on", + "turn_off", + "toggle", + "set_preset_mode", + "set_fan_mode", + "set_humidity", + "set_swing_mode", + "set_temperature", + ], + context, + // @ts-expect-error it's fine + domain: "climate", + load_config_keys: [ + "current_humidity", + "current_temperature", + "fan_mode", + "fan_modes", + "hvac_action", + "hvac_mode", + "hvac_modes", + "max_humidity", + "max_temp", + "min_humidity", + "min_temp", + "precision", + "preset_mode", + "preset_modes", + "swing_mode", + "swing_modes", + "target_humidity", + "target_temperature_high", + "target_temperature_low", + "target_temperature_step", + "target_temperature", + "temperature_unit", + ], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/cover.extension.ts b/src/extensions/domains/cover.extension.ts new file mode 100644 index 0000000..a45afee --- /dev/null +++ b/src/extensions/domains/cover.extension.ts @@ -0,0 +1,85 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { CoverDeviceClass } from "@digital-alchemy/hass"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * The current position of cover where 0 means closed and 100 is fully open. + */ + current_cover_position?: number; + /** + * The current tilt position of the cover where 0 means closed/no tilt and 100 means open/maximum tilt. + */ + current_cover_tilt_position?: number; + device_class?: `${CoverDeviceClass}`; + /** + * If the cover is closed or not. Used to determine state. + */ + is_closed?: boolean; + /** + * If the cover is closing or not. Used to determine state. + */ + is_closing?: boolean; + /** + * If the cover is opening or not. Used to determine state. + */ + is_opening?: boolean; +}; + +type EntityEvents = { + stop_cover_tilt: { + // + }; + set_cover_tilt_position: { + // + }; + close_cover_tilt: { + // + }; + open_cover_tilt: { + // + }; + stop_cover: { + // + }; + set_cover_position: { + // + }; + close_cover: { + // + }; + open_cover: { + // + }; +}; + +export function VirtualCover({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: [ + "stop_cover_tilt", + "set_cover_tilt_position", + "close_cover_tilt", + "open_cover_tilt", + "stop_cover", + "set_cover_position", + "close_cover", + "open_cover", + ], + context, + // @ts-expect-error its fine + domain: "cover", + load_config_keys: [ + "current_cover_position", + "current_cover_tilt_position", + "device_class", + "is_closed", + "is_closing", + "is_opening", + ], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/date.extension.ts b/src/extensions/domains/date.extension.ts new file mode 100644 index 0000000..84b30f2 --- /dev/null +++ b/src/extensions/domains/date.extension.ts @@ -0,0 +1,44 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type Year = `${number}${number}${number}${number}`; +type MD = `${number}${number}`; +/** + * YYYY-MM-DD + */ +export type SynapseDateFormat = `${Year}-${MD}-${MD}`; + +type EntityConfiguration = { + native_value?: SynapseDateFormat; + /** + * default: true + */ + managed?: boolean; +}; + +type EntityEvents = { + set_value: { value: SynapseDateFormat }; +}; + +export function VirtualDate({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["set_value"], + context, + // @ts-expect-error its fine + domain: "date", + load_config_keys: ["native_value"], + map_state: "native_value", + }); + + return function ({ + managed = true, + ...options + }: AddEntityOptions) { + const entity = generate.add_entity(options); + if (managed) { + entity.onSetValue(({ value }) => entity.storage.set("native_value", value)); + } + return entity; + }; +} diff --git a/src/extensions/domains/datetime.extension.ts b/src/extensions/domains/datetime.extension.ts new file mode 100644 index 0000000..9f3fd08 --- /dev/null +++ b/src/extensions/domains/datetime.extension.ts @@ -0,0 +1,43 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { Dayjs } from "dayjs"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * iso date string + * + * will translate Dayjs objects to correctly formatted strings + */ + native_value?: string | Dayjs; + /** + * default: true + */ + managed?: boolean; +}; + +type EntityEvents = { + set_value: { value: string }; +}; + +export function VirtualDateTime({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["set_value"], + context, + // @ts-expect-error its fine + domain: "datetime", + load_config_keys: ["native_value"], + map_state: "native_value", + }); + + return function ({ + managed = true, + ...options + }: AddEntityOptions) { + const entity = generate.add_entity(options); + if (managed) { + entity.onSetValue(({ value }) => entity.storage.set("native_value", value)); + } + return entity; + }; +} diff --git a/src/extensions/domains/fan.extension.ts b/src/extensions/domains/fan.extension.ts new file mode 100644 index 0000000..cfcffa3 --- /dev/null +++ b/src/extensions/domains/fan.extension.ts @@ -0,0 +1,82 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * The current direction of the fan. + */ + current_direction?: string; + /** + * True if the fan is on. + */ + is_on?: boolean; + /** + * True if the fan is oscillating. + */ + oscillating?: boolean; + /** + * The current speed percentage. Must be a value between 0 (off) and 100. + */ + percentage?: number; + /** + * The current preset_mode. One of the values in preset_modes or None if no preset is active. + */ + preset_mode?: string; + /** + * The list of supported preset_modes. This is an arbitrary list of str and should not contain any speeds. + */ + preset_modes?: string[]; + /** + * The number of speeds the fan supports. + */ + speed_count?: number; +}; + +type EntityEvents = { + set_direction: { direction: string }; + set_preset_mode: { preset_mode: string }; + set_percentage: { percentage: number }; + turn_on: { + speed?: string; + percentage?: number; + preset_mode?: string; + }; + turn_off: { + // + }; + toggle: { + // + }; + oscillate: { oscillating: boolean }; +}; + +export function VirtualFan({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: [ + "set_direction", + "set_preset_mode", + "set_percentage", + "turn_on", + "turn_off", + "toggle", + "oscillate", + ], + context, + // @ts-expect-error its fine + domain: "fan", + load_config_keys: [ + "current_direction", + "is_on", + "oscillating", + "percentage", + "preset_mode", + "preset_modes", + "speed_count", + ], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/humidifier.extension.ts b/src/extensions/domains/humidifier.extension.ts new file mode 100644 index 0000000..c51ab8d --- /dev/null +++ b/src/extensions/domains/humidifier.extension.ts @@ -0,0 +1,90 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { HumidifierDeviceClass } from "@digital-alchemy/hass"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * Returns the current status of the device. + */ + action?: string; + /** + * The available modes. Requires `SUPPORT_MODES`. + */ + available_modes?: `${HumidifierModes}`[]; + /** + * The current humidity measured by the device. + */ + current_humidity?: number; + /** + * Type of hygrostat + */ + device_class?: `${HumidifierDeviceClass}`; + /** + * Whether the device is on or off. + */ + is_on?: boolean; + /** + * The maximum humidity. + */ + max_humidity?: number; + /** + * The minimum humidity. + */ + min_humidity?: string; + /** + * The current active mode. Requires `SUPPORT_MODES`. + */ + mode?: `${HumidifierModes}`; + /** + * The target humidity the device is trying to reach. + */ + target_humidity?: number; +}; + +type HumidifierModes = + | "normal" + | "eco" + | "away" + | "boost" + | "comfort" + | "home" + | "sleep" + | "auto" + | "baby"; + +type EntityEvents = { + set_humidity: { + humidity: number; + }; + turn_on: { + // + }; + turn_off: { + // + }; +}; + +export function VirtualHumidifier({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["set_humidity", "turn_on", "turn_off"], + context, + // @ts-expect-error its fine + domain: "humidifier", + load_config_keys: [ + "action", + "available_modes", + "current_humidity", + "device_class", + "is_on", + "max_humidity", + "min_humidity", + "mode", + "target_humidity", + ], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/image.extension.ts b/src/extensions/domains/image.extension.ts new file mode 100644 index 0000000..1facf82 --- /dev/null +++ b/src/extensions/domains/image.extension.ts @@ -0,0 +1,37 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { Dayjs } from "dayjs"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * The content-type of the image, set automatically if the image entity provides a URL. + */ + content_type?: string; + /** + * Timestamp of when the image was last updated. Used to determine state. Frontend will call image or async_image after this changes. + */ + image_last_updated?: Dayjs; + /** + * Optional URL from where the image should be fetched. + */ + image_url?: string; +}; + +type EntityEvents = { + // +}; + +export function VirtualImage({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: [], + context, + // @ts-expect-error its fine + domain: "image", + load_config_keys: ["content_type", "image_last_updated", "image_url"], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/index.ts b/src/extensions/domains/index.ts new file mode 100644 index 0000000..6b08ada --- /dev/null +++ b/src/extensions/domains/index.ts @@ -0,0 +1,29 @@ +export * from "./alarm-control-panel.extension"; +export * from "./binary-sensor.extension"; +export * from "./button.extension"; +export * from "./camera.extension"; +export * from "./climate.extension"; +export * from "./cover.extension"; +export * from "./date.extension"; +export * from "./datetime.extension"; +export * from "./fan.extension"; +export * from "./image.extension"; +export * from "./lawn-mower.extension"; +export * from "./light.extension"; +export * from "./lock.extension"; +export * from "./media-player"; +export * from "./notify.extension"; +export * from "./number.extension"; +export * from "./remote.extension"; +export * from "./scene.extension"; +export * from "./select.extension"; +export * from "./sensor.extension"; +export * from "./siren.extension"; +export * from "./switch.extension"; +export * from "./text.extension"; +export * from "./time.extension"; +export * from "./todo-list.extension"; +export * from "./update.extension"; +export * from "./vacuum.extension"; +export * from "./valve.extension"; +export * from "./water-heater.extension"; diff --git a/src/extensions/domains/lawn-mower.extension.ts b/src/extensions/domains/lawn-mower.extension.ts new file mode 100644 index 0000000..1e84a48 --- /dev/null +++ b/src/extensions/domains/lawn-mower.extension.ts @@ -0,0 +1,37 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * Current activity. + */ + activity?: "mowing" | "docked" | "paused" | "error"; + supported_features?: number; +}; + +type EntityEvents = { + start_mowing: { + // + }; + dock: { + // + }; + pause: { + // + }; +}; + +export function VirtualLawnMower({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["start_mowing", "dock", "pause"], + context, + // @ts-expect-error its fine + domain: "lawn_mower", + load_config_keys: ["activity", "supported_features"], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/light.extension.ts b/src/extensions/domains/light.extension.ts new file mode 100644 index 0000000..b3f3459 --- /dev/null +++ b/src/extensions/domains/light.extension.ts @@ -0,0 +1,112 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * The brightness of this light between 1..255 + */ + brightness?: number; + /** + * The color mode of the light. + * The returned color mode must be present in the supported_color_modes property unless the light is rendering an effect. + */ + color_mode?: string; + /** + * The CT color value in K. + * This property will be copied to the light's state attribute when the light's color mode is set to ColorMode.COLOR_TEMP and ignored otherwise. + */ + color_temp_kelvin?: number; + /** + * The current effect. + * Should be EFFECT_OFF if the light supports effects and no effect is currently rendered. + */ + effect?: string; + /** + * The list of supported effects. + */ + effect_list?: string[]; + /** + * The hue and saturation color value (float, float). + * This property will be copied to the light's state attribute when the light's color mode is set to ColorMode.HS and ignored otherwise. + */ + hs_color?: [number, number]; + /** + * If the light entity is on or not. + */ + is_on?: boolean; + /** + * The coldest color_temp_kelvin that this light supports. + */ + max_color_temp_kelvin?: number; + /** + * The warmest color_temp_kelvin that this light supports. + */ + min_color_temp_kelvin?: number; + /** + * The rgb color value (int, int, int). + * This property will be copied to the light's state attribute when the light's color mode is set to ColorMode. + * RGB and ignored otherwise. + */ + rgb_color?: [r: number, g: number, b: number]; + /** + * The rgbw color value (int, int, int, int). + * This property will be copied to the light's state attribute when the light's color mode is set to ColorMode. + * RGBW and ignored otherwise. + */ + rgbw_color?: [r: number, g: number, b: number, w: number]; + /** + * The rgbww color value (int, int, int, int, int). + * This property will be copied to the light's state attribute when the light's color mode is set to ColorMode. + * RGBWW and ignored otherwise. + */ + rgbww_color?: [r: number, g: number, b: number, w: number, w: number]; + /** + * Flag supported color modes. + */ + supported_color_modes?: string[]; + supported_features?: number; + /** + * The xy color value (float, float). + * This property will be copied to the light's state attribute when the light's color mode is set to ColorMode.XY and ignored otherwise. + */ + xy_color?: [number, number]; +}; + +type EntityEvents = { + turn_on: { + // + }; + turn_off: { + // + }; +}; + +export function VirtualLight({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["turn_on", "turn_off"], + context, + domain: "light", + load_config_keys: [ + "brightness", + "color_mode", + "color_temp_kelvin", + "effect", + "effect_list", + "hs_color", + "is_on", + "max_color_temp_kelvin", + "min_color_temp_kelvin", + "rgb_color", + "rgbw_color", + "rgbww_color", + "supported_color_modes", + "supported_features", + "xy_color", + ], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/lock.extension.ts b/src/extensions/domains/lock.extension.ts new file mode 100644 index 0000000..316baee --- /dev/null +++ b/src/extensions/domains/lock.extension.ts @@ -0,0 +1,88 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * Describes what the last change was triggered by. + */ + changed_by?: string; + /** + * Regex for code format or None if no code is required. + */ + code_format?: string; + /** + * Indication of whether the lock is currently locked. Used to determine state. + */ + is_locked?: boolean; + /** + * Indication of whether the lock is currently locking. Used to determine state. + */ + is_locking?: boolean; + /** + * Indication of whether the lock is currently unlocking. Used to determine state. + */ + is_unlocking?: boolean; + /** + * Indication of whether the lock is currently jammed. Used to determine state. + */ + is_jammed?: boolean; + /** + * Indication of whether the lock is currently opening. Used to determine state. + */ + is_opening?: boolean; + /** + * + */ + is_open?: boolean; + supported_features?: number; + /** + * default: true + */ + managed?: boolean; +}; + +type EntityEvents = { + lock: { + // + }; + unlock: { + // + }; + open: { + // + }; +}; + +export function VirtualLock({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["lock", "unlock", "open"], + context, + // @ts-expect-error its fine + domain: "lock", + load_config_keys: [ + "changed_by", + "code_format", + "is_locked", + "is_locking", + "is_unlocking", + "is_jammed", + "is_opening", + "is_open", + "supported_features", + ], + }); + + return function ({ + managed = true, + ...options + }: AddEntityOptions) { + const entity = generate.add_entity(options); + if (managed) { + entity.onLock(({}) => entity.storage.set("is_locked", true)); + entity.onUnlock(({}) => entity.storage.set("is_locked", false)); + entity.onOpen(({}) => entity.storage.set("is_open", true)); + } + return entity; + }; +} diff --git a/src/extensions/domains/media-player.ts b/src/extensions/domains/media-player.ts new file mode 100644 index 0000000..07dfb7d --- /dev/null +++ b/src/extensions/domains/media-player.ts @@ -0,0 +1,214 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { Dayjs } from "dayjs"; + +import { AddEntityOptions } from "../.."; + +enum MediaType { + MUSIC = "music", + TVSHOW = "tvshow", + MOVIE = "movie", + VIDEO = "video", + EPISODE = "episode", + CHANNEL = "channel", + PLAYLIST = "playlist", + IMAGE = "image", + URL = "url", + GAME = "game", + APP = "app", +} + +enum MediaDeviceClass { + TV = "tv", + SPEAKER = "speaker", + RECEIVER = "receiver", +} + +type MediaPlayerEnqueue = "add" | "next" | "play" | "replace"; + +type EntityConfiguration = { + /** + * ID of the current running app. + */ + app_id?: string; + /** + * Name of the current running app. + */ + app_name?: string; + /** + * Type of media player. + */ + device_class?: `${MediaDeviceClass}`; + /** + * A dynamic list of player entities which are currently grouped together for synchronous playback. + * If the platform has a concept of defining a group leader, the leader should be the first element in that list. + */ + group_members?: string[]; + /** + * True if if volume is currently muted. + */ + is_volume_muted?: boolean; + /** + * Album artist of current playing media, music track only. + */ + media_album_artist?: string; + /** + * Album name of current playing media, music track only. + */ + media_album_name?: string; + /** + * Album artist of current playing media, music track only. + */ + media_artist?: string; + /** + * Channel currently playing. + */ + media_channel?: string; + /** + * Content ID of current playing media. + */ + media_content_id?: string; + /** + * Content type of current playing media. + */ + media_content_type?: `${MediaType}`; + /** + * Duration of current playing media in seconds. + */ + media_duration?: number; + /** + * Episode of current playing media, TV show only. + */ + media_episode?: string; + /** + * Hash of media image, defaults to SHA256 of media_image_url if media_image_url is not None. + */ + media_image_hash?: string; + /** + * True if property media_image_url is accessible outside of the home network. + */ + media_image_remotely_accessible?: boolean; + /** + * Image URL of current playing media. + */ + media_image_url?: string; + /** + * Title of Playlist currently playing. + */ + media_playlist?: string; + /** + * Position of current playing media in seconds. + */ + media_position?: number; + /** + * Timestamp of when _attr_media_position was last updated. The timestamp should be set by calling homeassistant.util.dt.utcnow(). + */ + media_position_updated_at?: Dayjs; + /** + * Season of current playing media, TV show only. + */ + media_season?: string; + /** + * Title of series of current playing media, TV show only. + */ + media_series_title?: string; + /** + * Title of current playing media. + */ + media_title?: string; + /** + * Track number of current playing media, music track only. + */ + media_track?: string; + /** + * Current repeat mode. + */ + repeat?: string; + /** + * True if shuffle is enabled. + */ + shuffle?: boolean; + /** + * The current sound mode of the media player. + */ + sound_mode?: string; + /** + * Dynamic list of available sound modes. + */ + sound_mode_list?: string[]; + /** + * The currently selected input source for the media player. + */ + source?: string; + /** + * The list of possible input sources for the media player. (This list should contain human readable names, suitable for frontend display). + */ + source_list?: string[]; + + supported_features?: number; + /** + * Volume level of the media player in the range (0..1). + */ + volume_level?: number; + /** + * Volume step to use for the volume_up and volume_down services. + */ + volume_step?: string; +}; + +type EntityEvents = { + select_sound_mode: { source: string }; + select_source: { source: string }; + play_media: { + media_type: string; + media_id: string; + enqueue?: MediaPlayerEnqueue; + announce?: boolean; + }; +}; + +export function VirtualMediaPlayer({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["select_sound_mode", "select_source", "play_media"], + context, + // @ts-expect-error its fine + domain: "media_player", + load_config_keys: [ + "app_id", + "app_name", + "device_class", + "group_members", + "is_volume_muted", + "media_album_artist", + "media_album_name", + "media_artist", + "media_channel", + "media_content_id", + "media_content_type", + "media_duration", + "media_episode", + "media_image_hash", + "media_image_remotely_accessible", + "media_image_url", + "media_playlist", + "media_position", + "media_position_updated_at", + "media_season", + "media_series_title", + "media_title", + "media_track", + "repeat", + "shuffle", + "sound_mode", + "sound_mode_list", + "source", + "source_list", + "supported_features", + "volume_level", + "volume_step", + ], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/notify.extension.ts b/src/extensions/domains/notify.extension.ts new file mode 100644 index 0000000..93d65e9 --- /dev/null +++ b/src/extensions/domains/notify.extension.ts @@ -0,0 +1,28 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + // +}; + +type EntityEvents = { + send_message: { + message: string; + title?: string; + }; +}; + +export function VirtualNotify({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["send_message"], + context, + // @ts-expect-error its fine + domain: "notify", + load_config_keys: [], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/number.extension.ts b/src/extensions/domains/number.extension.ts new file mode 100644 index 0000000..c6d27ec --- /dev/null +++ b/src/extensions/domains/number.extension.ts @@ -0,0 +1,65 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions, SensorDeviceClasses } from "../.."; + +type EntityConfiguration = SensorDeviceClasses & { + /** + * Defines how the number should be displayed in the UI. + * It's recommended to use the default `auto`. + * Can be `box` or `slider` to force a display mode. + */ + mode?: "auto" | "slider" | "box"; + /** + * The maximum accepted value in the number's native_unit_of_measurement (inclusive) + */ + native_max_value?: number; + /** + * The minimum accepted value in the number's native_unit_of_measurement (inclusive) + */ + native_min_value?: number; + /** + * Defines the resolution of the values, i.e. the smallest increment or decrement in the number's + */ + step?: number; + /** + * The value of the number in the number's native_unit_of_measurement. + */ + native_value?: number; + /** + * default: true + */ + managed?: boolean; +}; + +type EntityEvents = { + set_value: { value: number }; +}; + +export function VirtualNumber({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["set_value"], + context, + // @ts-expect-error its fine + domain: "number", + load_config_keys: [ + "device_class", + "unit_of_measurement", + "mode", + "native_max_value", + "native_min_value", + "step", + "native_value", + ], + }); + + return function ({ + managed = true, + ...options + }: AddEntityOptions) { + const entity = generate.add_entity(options); + if (managed) { + entity.onSetValue(({ value }) => entity.storage.set("native_value", value)); + } + return entity; + }; +} diff --git a/src/extensions/domains/remote.extension.ts b/src/extensions/domains/remote.extension.ts new file mode 100644 index 0000000..0c16690 --- /dev/null +++ b/src/extensions/domains/remote.extension.ts @@ -0,0 +1,49 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * Return the current active activity + */ + current_activity?: string; + /** + * Return the list of available activities + */ + activity_list?: string[]; + supported_features?: number; +}; + +type EntityEvents = { + turn_on: { activity?: string }; + turn_off: { activity?: string }; + toggle: { activity?: string }; + send_command: { command: string[] }; + learn_command: { + // + }; + delete_command: { + // + }; +}; + +export function VirtualRemote({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: [ + "turn_on", + "turn_off", + "toggle", + "send_command", + "learn_command", + "delete_command", + ], + context, + // @ts-expect-error its fine + domain: "remote", + load_config_keys: ["current_activity", "activity_list", "supported_features"], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/scene.extension.ts b/src/extensions/domains/scene.extension.ts new file mode 100644 index 0000000..4716877 --- /dev/null +++ b/src/extensions/domains/scene.extension.ts @@ -0,0 +1,25 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + // +}; + +type EntityEvents = { + activate: { + // + }; +}; + +export function VirtualScene({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["activate"], + context, + domain: "scene", + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/select.extension.ts b/src/extensions/domains/select.extension.ts new file mode 100644 index 0000000..d6b004d --- /dev/null +++ b/src/extensions/domains/select.extension.ts @@ -0,0 +1,44 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * The current select option + */ + current_option?: string; + /** + * A list of available options as strings + */ + options?: string[]; + /** + * default: true + */ + managed?: boolean; +}; + +type EntityEvents = { + select_option: { option: string }; +}; + +export function VirtualSelect({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["select_option"], + context, + // @ts-expect-error its fine + domain: "select", + load_config_keys: ["current_option", "options"], + map_state: "current_option", + }); + + return function ({ + managed = true, + ...options + }: AddEntityOptions) { + const entity = generate.add_entity(options); + if (managed) { + entity.onSelectOption(({ option }) => entity.storage.set("current_option", option)); + } + return entity; + }; +} diff --git a/src/extensions/domains/sensor.extension.ts b/src/extensions/domains/sensor.extension.ts new file mode 100644 index 0000000..c6dd0ec --- /dev/null +++ b/src/extensions/domains/sensor.extension.ts @@ -0,0 +1,28 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions, SensorConfiguration } from "../.."; + +type EntityConfiguration = SensorConfiguration; + +type EntityEvents = { + // +}; + +export function VirtualSensor({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + context, + domain: "sensor", + load_config_keys: [ + "device_class", + "last_reset", + "state", + "suggested_display_precision", + "suggested_unit_of_measurement", + "unit_of_measurement", + ], + }); + + return ( + options: AddEntityOptions, EntityEvents, ATTRIBUTES>, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/siren.extension.ts b/src/extensions/domains/siren.extension.ts new file mode 100644 index 0000000..3efbaac --- /dev/null +++ b/src/extensions/domains/siren.extension.ts @@ -0,0 +1,41 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * Whether the device is on or off. + */ + is_on?: boolean; + /** + * The list or dictionary of available tones on the device to pass into the turn_on service. + * If a dictionary is provided, when a user uses the dict value of a tone, + * it will get converted to the corresponding dict key before being passed on to the integration platform. + * Requires SUPPORT_TONES feature. + */ + available_tones?: string[]; + supported_features?: number; +}; + +type EntityEvents = { + turn_on: { + // + }; + turn_off: { + // + }; +}; + +export function VirtualSiren({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["turn_on", "turn_off"], + context, + // @ts-expect-error its fine + domain: "siren", + load_config_keys: ["is_on", "available_tones", "supported_features"], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/switch.extension.ts b/src/extensions/domains/switch.extension.ts new file mode 100644 index 0000000..be32be0 --- /dev/null +++ b/src/extensions/domains/switch.extension.ts @@ -0,0 +1,51 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { SwitchDeviceClass } from "@digital-alchemy/hass"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + device_class?: `${SwitchDeviceClass}`; + /** + * If the switch is currently on or off. + */ + is_on?: boolean; + /** + * default: true + */ + managed?: boolean; +}; + +type EntityEvents = { + turn_on: { + // + }; + turn_off: { + // + }; + toggle: { + // + }; +}; + +export function VirtualSwitch({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["turn_on", "turn_off", "toggle"], + context, + domain: "switch", + load_config_keys: ["device_class", "is_on"], + map_config: [{ key: "is_on", load: entity => entity.state === "on" }], + }); + + return function ({ + managed = true, + ...options + }: AddEntityOptions) { + const entity = generate.add_entity(options); + if (managed) { + entity.onToggle(() => entity.storage.set("is_on", !entity.storage.get("is_on"))); + entity.onTurnOff(() => entity.storage.set("is_on", false)); + entity.onTurnOn(() => entity.storage.set("is_on", true)); + } + return entity; + }; +} diff --git a/src/extensions/domains/text.extension.ts b/src/extensions/domains/text.extension.ts new file mode 100644 index 0000000..9dc35ab --- /dev/null +++ b/src/extensions/domains/text.extension.ts @@ -0,0 +1,56 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * Defines how the text should be displayed in the UI. Can be text or password. + */ + mode?: "text" | "password"; + /** + * The maximum number of characters in the text value (inclusive). + */ + native_max?: number; + /** + * The minimum number of characters in the text value (inclusive). + */ + native_min?: number; + /** + * A regex pattern that the text value must match to be valid. + */ + pattern?: string; + /** + * The value of the text. + */ + native_value?: string; + /** + * default: true + */ + managed?: boolean; +}; + +type EntityEvents = { + set_value: { value: string }; +}; + +export function VirtualText({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["set_value"], + context, + // @ts-expect-error its fine + domain: "text", + load_config_keys: ["mode", "native_max", "native_min", "pattern", "native_value"], + map_state: "native_value", + }); + + return function ({ + managed = true, + ...options + }: AddEntityOptions) { + const entity = generate.add_entity(options); + if (managed) { + entity.onSetValue(({ value }) => entity.storage.set("native_value", value)); + } + return entity; + }; +} diff --git a/src/extensions/domains/time.extension.ts b/src/extensions/domains/time.extension.ts new file mode 100644 index 0000000..a197ce2 --- /dev/null +++ b/src/extensions/domains/time.extension.ts @@ -0,0 +1,40 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +export type SynapseTimeFormat = `${number}${number}:${number}${number}:${number}${number}`; + +type EntityConfiguration = { + native_value?: SynapseTimeFormat; + + /** + * default: true + */ + managed?: boolean; +}; + +type EntityEvents = { + set_value: { value: SynapseTimeFormat }; +}; + +export function VirtualTime({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["set_value"], + context, + // @ts-expect-error its fine + domain: "time", + load_config_keys: ["native_value"], + map_state: "native_value", + }); + + return function ({ + managed = true, + ...options + }: AddEntityOptions) { + const entity = generate.add_entity(options); + if (managed) { + entity.onSetValue(({ value }) => entity.storage.set("native_value", value)); + } + return entity; + }; +} diff --git a/src/extensions/domains/todo-list.extension.ts b/src/extensions/domains/todo-list.extension.ts new file mode 100644 index 0000000..bfd79a2 --- /dev/null +++ b/src/extensions/domains/todo-list.extension.ts @@ -0,0 +1,58 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { Dayjs } from "dayjs"; + +import { AddEntityOptions } from "../.."; + +type TodoItem = { + /** + * A unique identifier for the to-do item. This field is required for updates and the entity state. + */ + uid?: string; + /** + * A title or summary of the to-do item. This field is required for the entity state. + */ + summary?: string; + /** + * The date and time that a to-do is expected to be completed. + * The types supported depend on TodoListEntityFeature.DUE_DATE or TodoListEntityFeature.DUE_DATETIME or both being set. + * As a datetime, must have a timezone. + */ + due?: Dayjs; + /** + * Defines the overall status for the to-do item, either NEEDS_ACTION or COMPLETE. This field is required for the entity state. + */ + status?: "needs_action" | "complete"; + /** + * A more complete description of the to-do item than that provided by the summary. + * Only supported when TodoListEntityFeature.DESCRIPTION is set. + */ + description?: string; +}; + +type EntityConfiguration = { + /** + * Required. The ordered contents of the To-do list. + */ + todo_items: TodoItem[]; + supported_features?: number; +}; + +type EntityEvents = { + create_todo_item: { item: TodoItem }; + delete_todo_item: { item: TodoItem }; + move_todo_item: { item: TodoItem }; +}; + +export function VirtualTodoList({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["create_todo_item", "delete_todo_item", "move_todo_item"], + context, + // @ts-expect-error its fine + domain: "todo_list", + load_config_keys: ["todo_items", "supported_features"], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/update.extension.ts b/src/extensions/domains/update.extension.ts new file mode 100644 index 0000000..7279ebc --- /dev/null +++ b/src/extensions/domains/update.extension.ts @@ -0,0 +1,76 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * The device or service that the entity represents has auto update logic. + * When this is set to `true` you can not skip updates. + */ + auto_update?: boolean; + device_class?: "firmware"; + /** + * Update installation progress. + * Can either return a boolean (True if in progress, False if not) or an integer to indicate the progress from 0 to 100%. + */ + in_progress?: boolean | number; + /** + * The currently installed and used version of the software. + */ + installed_version?: string; + /** + * The latest version of the software available. + */ + latest_version?: string; + /** + * This method can be implemented so users can can get the full release notes in the more-info dialog of the Home Assistant Frontend before they install the update. + * + * The returned string can contain markdown, and the frontend will format that correctly. + * + * This method requires UpdateEntityFeature.RELEASE_NOTES to be set. + */ + release_notes?: string; + /** + * Summary of the release notes or changelog. + * This is not suitable for long changelogs but merely suitable for a short excerpt update description of max 255 characters. + */ + release_summary?: string; + /** + * URL to the full release notes of the latest version available. + */ + release_url?: string; + supported_features?: number; + /** + * Title of the software. This helps to differentiate between the device or entity name versus the title of the software installed. + */ + title?: string; +}; + +type EntityEvents = { + install: { backup?: boolean; version?: string }; +}; + +export function VirtualUpdate({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["install"], + context, + // @ts-expect-error its fine + domain: "update", + load_config_keys: [ + "auto_update", + "device_class", + "in_progress", + "installed_version", + "latest_version", + "release_notes", + "release_summary", + "release_url", + "supported_features", + "title", + ], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/vacuum.extension.ts b/src/extensions/domains/vacuum.extension.ts new file mode 100644 index 0000000..29d6677 --- /dev/null +++ b/src/extensions/domains/vacuum.extension.ts @@ -0,0 +1,69 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * Current battery level. + */ + battery_level?: number; + /** + * The current fan speed. + */ + fan_speed?: string; + /** + * List of available fan speeds. + */ + fan_speed_list?: string[]; + supported_features?: number; +}; + +type EntityEvents = { + clean_spot: { + // + }; + locate: { + // + }; + pause: { + // + }; + return_to_base: { + // + }; + send_command: { + // + }; + set_fan_speed: { + // + }; + start: { + // + }; + stop: { + // + }; +}; + +export function VirtualVacuum({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: [ + "clean_spot", + "locate", + "pause", + "return_to_base", + "send_command", + "set_fan_speed", + "start", + "stop", + ], + context, + // @ts-expect-error its fine + domain: "vacuum", + load_config_keys: ["battery_level", "fan_speed", "fan_speed_list", "supported_features"], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/valve.extension.ts b/src/extensions/domains/valve.extension.ts new file mode 100644 index 0000000..ef95ef6 --- /dev/null +++ b/src/extensions/domains/valve.extension.ts @@ -0,0 +1,67 @@ +import { TServiceParams } from "@digital-alchemy/core"; +import { ValveDeviceClass } from "@digital-alchemy/hass"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * The current position of the valve where 0 means closed and 100 is fully open. + * This attribute is required on valves with reports_position = True, where it's used to determine state. + */ + current_valve_position?: number; + /** + * If the valve is closed or not. Used to determine state for valves that don't report position. + */ + is_closed?: boolean; + /** + * If the valve is opening or not. Used to determine state. + */ + is_opening?: boolean; + /** + * If the valve knows its position or not. + */ + reports_position: boolean; + device_class?: `${ValveDeviceClass}`; + /** + * If the valve is closing or not. Used to determine state. + */ + is_closing?: boolean; + supported_features?: number; +}; + +type EntityEvents = { + open_valve: { + // + }; + close_valve: { + // + }; + set_valve_position: { + // + }; + stop_valve: { + // + }; +}; + +export function VirtualValve({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: ["open_valve", "close_valve", "set_valve_position", "stop_valve"], + context, + // @ts-expect-error its fine + domain: "valve", + load_config_keys: [ + "current_valve_position", + "is_closed", + "is_opening", + "reports_position", + "device_class", + "is_closing", + "supported_features", + ], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/domains/water-heater.extension.ts b/src/extensions/domains/water-heater.extension.ts new file mode 100644 index 0000000..dbeeaf5 --- /dev/null +++ b/src/extensions/domains/water-heater.extension.ts @@ -0,0 +1,101 @@ +import { TServiceParams } from "@digital-alchemy/core"; + +import { AddEntityOptions } from "../.."; + +type EntityConfiguration = { + /** + * The minimum temperature that can be set. + */ + min_temp?: number; + /** + * The maximum temperature that can be set. + */ + max_temp?: number; + /** + * The current temperature. + */ + current_temperature?: number; + /** + * The temperature we are trying to reach. + */ + target_temperature?: number; + /** + * Upper bound of the temperature we are trying to reach. + */ + target_temperature_high?: number; + /** + * Lower bound of the temperature we are trying to reach. + */ + target_temperature_low?: number; + /** + * One of TEMP_CELSIUS, TEMP_FAHRENHEIT, or TEMP_KELVIN. + */ + temperature_unit?: string; + /** + * The current operation mode. + */ + current_operation?: string; + /** + * List of possible operation modes. + */ + operation_list?: string[]; + /** + * List of supported features. + */ + supported_features?: number; + is_away_mode_on?: boolean; +}; + +type EntityEvents = { + set_temperature: { + // + }; + set_operation_mode: { + // + }; + turn_away_mode_on: { + // + }; + turn_away_mode_off: { + // + }; + turn_on: { + // + }; + turn_off: { + // + }; +}; + +export function VirtualWaterHeater({ context, synapse }: TServiceParams) { + const generate = synapse.generator.create({ + bus_events: [ + "set_temperature", + "set_operation_mode", + "turn_away_mode_on", + "turn_away_mode_off", + "turn_on", + "turn_off", + ], + context, + // @ts-expect-error its fine + domain: "water_heater", + load_config_keys: [ + "min_temp", + "max_temp", + "current_temperature", + "target_temperature", + "target_temperature_high", + "target_temperature_low", + "temperature_unit", + "current_operation", + "operation_list", + "supported_features", + "is_away_mode_on", + ], + }); + + return ( + options: AddEntityOptions, + ) => generate.add_entity(options); +} diff --git a/src/extensions/generator.extension.ts b/src/extensions/generator.extension.ts new file mode 100644 index 0000000..d818a90 --- /dev/null +++ b/src/extensions/generator.extension.ts @@ -0,0 +1,186 @@ +import { is, SINGLE, START, TBlackHole, TServiceParams } from "@digital-alchemy/core"; +import { PICK_ENTITY, TEntityUpdateCallback } from "@digital-alchemy/hass"; +import { CamelCase } from "type-fest"; + +import { + AddEntityOptions, + BaseEvent, + CreateRemovableCallback, + DomainGeneratorOptions, + EntityConfigCommon, + formatObjectId, + generateHash, + LATE_READY, + RemovableCallback, + TEventMap, +} from "../helpers"; +import { ConfigMapper } from "./storage.extension"; + +export function DomainGenerator({ + logger, + internal, + synapse, + event, + lifecycle, + hass, + config, +}: TServiceParams) { + const getIdentifier = () => internal.boot.application.name; + + // #MARK: removableListener + function removableListener( + eventName: string, + callback: RemovableCallback, + ) { + const remove = () => event.removeListener(eventName, exec); + const exec = async (data: DATA) => + await internal.safeExec(async () => await callback(data, remove)); + event.on(eventName, exec); + return { remove }; + } + + const registered = new Set(); + + // #MARK: create + function create({ + domain, + context, + bus_events = [], + load_config_keys = [], + map_state, + map_config = [], + }: DomainGeneratorOptions) { + logger.trace({ bus_events, context }, "registering domain [%s]", domain); + + bus_events.forEach(name => { + // some domains have duplicates + // filter those out + if (registered.has(name)) { + return; + } + registered.add(name); + hass.socket.onEvent({ + context, + event: [config.synapse.EVENT_NAMESPACE, name, getIdentifier()].join("/"), + // 🚌🚏 Bus transfer + exec: ({ data }: BaseEvent) => event.emit(`/synapse/${name}/${data.unique_id}`, data), + }); + }); + + return { + // #MARK: add_entity + add_entity( + entity: AddEntityOptions, + ) { + // * defaults + // - unique_id - required for comms + entity.unique_id = is.empty(entity.unique_id) + ? generateHash(`${getIdentifier()}:${entity.suggested_object_id || entity.name}`) + : entity.unique_id; + // - suggested_object_id - required on python side due to the way the code is set up + entity.suggested_object_id ??= formatObjectId(entity.name); + const unique_id = entity.unique_id; + + // * initialize storage + const storage = synapse.storage.add>({ + domain, + entity, + load_config_keys, + map_config: map_config as ConfigMapper< + Extract, string> + >[], + map_state: map_state as keyof EntityConfigCommon, + }); + + // * map bus events + bus_events.forEach(bus_event => { + if (is.undefined(entity[bus_event])) { + return; + } + logger.trace({ bus_event, context, name: entity.name }, `static attach`); + removableListener(`/synapse/${bus_event}/${unique_id}`, entity[bus_event]); + }); + + // * build dynamic listeners + const dynamicAttach = Object.fromEntries( + bus_events.map(name => [ + `on${name + .split("_") + .map(i => i.charAt(START).toUpperCase() + i.slice(SINGLE)) + .join("")}`, + ((callback: RemovableCallback) => + removableListener( + `/synapse/${name}/${unique_id}`, + callback, + )) as CreateRemovableCallback, + ]), + ); + + const getEntity = () => hass.entity.byUniqueId(unique_id); + + // * final return + return { + /** + * Look up entity proxy in hass entity registry + * + * > **⚠️ REGISTRY NOT POPULATED BEFORE `onReady`** + */ + getEntity, + + /** + * Look up entity in `hass` entity registry, and pass through the `onUpdate` request + * + * Usable at any lifecycle stage + */ + onUpdate() { + return (callback: TEntityUpdateCallback) => { + let remover: { remove: () => TBlackHole }; + lifecycle.onReady(() => { + const entity = getEntity(); + if (!entity) { + logger.error( + { entity, name: "onUpdate" }, + `event attachment failed, is entity loaded in home assistant?`, + ); + return; + } + remover = entity.onUpdate(callback); + }, LATE_READY); + return { + /** + * can only be used during runtime + */ + remove() { + if (remover) { + logger.trace(`removing entity update callback`); + remover.remove(); + remover = undefined; + return; + } + // too soon / already used + logger.error(`no remover function defined`); + }, + }; + }; + }, + + /** + * internal storage + */ + storage, + + // - ... and all the callback events + ...(dynamicAttach as BuildCallbacks), + }; + }, + }; + } + return { create }; +} + +type BuildCallbacks = { + [EVENT_NAME in Extract< + keyof EVENT_MAP, + string + > as CamelCase<`on-${EVENT_NAME}`>]: CreateRemovableCallback; +}; diff --git a/src/extensions/index.ts b/src/extensions/index.ts index df74458..d87ad61 100644 --- a/src/extensions/index.ts +++ b/src/extensions/index.ts @@ -1,6 +1,8 @@ -export * from "./binary-sensor.extension"; -export * from "./button.extension"; -export * from "./registry.extension"; -export * from "./scene.extension"; -export * from "./sensor.extension"; -export * from "./switch.extension"; +export * from "./configure.extension"; +export * from "./controller.extension"; +export * from "./device.extension"; +export * from "./discovery.extension"; +export * from "./domains"; +export * from "./generator.extension"; +export * from "./socket.extension"; +export * from "./storage.extension"; diff --git a/src/extensions/registry.extension.ts b/src/extensions/registry.extension.ts deleted file mode 100644 index d2c0f32..0000000 --- a/src/extensions/registry.extension.ts +++ /dev/null @@ -1,332 +0,0 @@ -import { - InternalError, - is, - SECOND, - sleep, - START, - TBlackHole, - TContext, - TServiceParams, -} from "@digital-alchemy/core"; -import { ALL_DOMAINS } from "@digital-alchemy/hass"; -import { createHash } from "crypto"; - -type BaseEntity = { - name: string; - icon?: string; - unique_id?: string; -}; - -type SynapseSocketOptions = { - context: TContext; - domain: ALL_DOMAINS; - details?: (data: DATA) => object; -}; - -const BOOT_TIME = new Date().toISOString(); -// anecdotally, it only needs a single retry -// can't think of what a 2nd might accomplish, let alone 3rd -const RETRY = 3; - -function generateHash(input: string) { - const hash = createHash("sha256"); - hash.update(input); - return hash.digest("hex"); -} - -export function Registry({ - lifecycle, - logger, - hass, - cache, - config, - internal, - context, - scheduler, -}: TServiceParams) { - // # Common - const LOADERS = new Map object[]>(); - let initComplete = false; - const getIdentifier = () => - config.synapse.APPLICATION_IDENTIFIER || internal.boot.application.name; - - async function SendEntityList() { - logger.debug(`send entity list`); - const domains = Object.fromEntries( - [...LOADERS.keys()].map(domain => { - const data = LOADERS.get(domain)(); - return [domain, data]; - }), - ); - const hash = generateHash(JSON.stringify(domains)); - await hass.socket.fireEvent( - `digital_alchemy_application_state`, - { app: getIdentifier(), boot: BOOT_TIME, domains, hash }, - false, - ); - } - - // ## Heartbeat - lifecycle.onPostConfig(async () => { - if (!config.synapse.EMIT_HEARTBEAT) { - return; - } - logger.trace({ name: "onPostConfig" }, `starting heartbeat`); - scheduler.interval({ - exec: async () => - await hass.socket.fireEvent( - `digital_alchemy_heartbeat_${getIdentifier()}`, - {}, - false, - ), - interval: config.synapse.HEARTBEAT_INTERVAL * SECOND, - }); - }); - - lifecycle.onPreShutdown(async () => { - logger.debug( - { name: "onPreShutdown" }, - `notifying synapse extension of shutdown`, - ); - await hass.socket.fireEvent( - `digital_alchemy_application_shutdown_${getIdentifier()}`, - {}, - false, - ); - }); - - // ## Different opportunities to announce - // ### At boot - hass.socket.onConnect(async () => { - initComplete = true; - await hass.socket.fireEvent( - `digital_alchemy_heartbeat_${getIdentifier()}`, - {}, - false, - ); - if (!config.synapse.ANNOUNCE_AT_CONNECT) { - return; - } - logger.debug({ name: "onConnect" }, `[socket connect] sending entity list`); - await SendEntityList(); - }); - - // ### Targeted at this app - hass.socket.onEvent({ - context, - event: "digital_alchemy_app_reload", - exec: async ({ app }: { app: string }) => { - if (app !== getIdentifier()) { - return; - } - logger.info(`digital-alchemy.reload(%s)`, app); - await SendEntityList(); - }, - }); - - // ### Targeted at all digital-alchemy apps - hass.socket.onEvent({ - context, - event: "digital_alchemy_app_reload_all", - exec: async () => { - logger.info({ all: true }, `digital-alchemy.reload()`); - await SendEntityList(); - }, - }); - - // # Domain registry - return function ({ - domain, - context, - details, - }: SynapseSocketOptions) { - logger.trace({ name: domain }, `init domain`); - const registry = new Map(); - const CACHE_KEY = (id: string) => `${domain}_cache:${id}`; - type TCallback = (argument: unknown) => TBlackHole; - let LOAD_ME = new Set<{ - id: string; - callback: TCallback; - }>(); - const missingEntities = () => - [...LOAD_ME.values()].map(({ id }) => registry.get(id).name); - let LOADED_SYNAPSE_DATA: Record; - - // ## Export the data for hass - LOADERS.set(domain, () => { - return [...registry.entries()].map(([id, item]) => { - return { - ...(details ? details(item) : {}), - icon: is.empty(item.icon) ? undefined : `mdi:${item.icon}`, - id, - name: item.name, - }; - }); - }); - - // ## Value restoration - function loadFromHass( - id: string, - callback: (argument: T) => void, - ) { - // ? loading already occurred, acts as a flag and minor garbage collection - if (!LOAD_ME) { - if (LOADED_SYNAPSE_DATA && LOADED_SYNAPSE_DATA[id]) { - // load from the snapshot - // - // > thoughts on data desync - // - // it's not clear why this entity is being loaded later, or even how much later this is - // however, if it existed in the past, and came from this app, then it's value - // should be in the snapshot - // - // i don't believe there is a way for the data to update inside synapse if all the assumptions hold true - // snapshot should contain last known value, even if we're generating the entity 2 days after boot for some reason - // - callback(LOADED_SYNAPSE_DATA[id] as T); - return; - } - // not so lucky - logger.debug({ id, name: loadFromHass }, `value restoration failed`); - return; - } - logger.trace( - { domain, id, name: loadFromHass }, - `adding lookup for entity`, - ); - LOAD_ME.add({ callback: callback as TCallback, id }); - } - - // What is visible on the dashboard is considered the second source of truth - // If an entity wants a state, but it wasn't able to load it from cache, it will come here - // Will do a quick lookup of what the extension thinks the value is, and use that to set - // > Rebooting hass could be done to clear out the values if needed - // > Need to go through synapse based side channels to avoid retrieving an "unavailable" state - hass.socket.onConnect(async () => { - if (is.empty(LOAD_ME)) { - return; - } - logger.debug( - { domain, name: "onConnect" }, - `retrieving state from synapse`, - ); - let loaded = false; - // listen for reply - const remove = hass.socket.onEvent({ - context, - event: `digital_alchemy_respond_state_${domain}`, - exec: ({ data }: { data: Record }) => { - loaded = true; - LOADED_SYNAPSE_DATA = data; - LOAD_ME.forEach(item => { - const { id, callback } = item; - callback(data[id] as object); - LOAD_ME.delete(item); - }); - LOAD_ME = undefined; - }, - once: true, - }); - - for (let i = START; i <= RETRY; i++) { - if (i > START) { - logger.warn( - { domain, missing: missingEntities(), name: "onConnect" }, - `retrying state retrieval...`, - ); - } - // send request for data - await hass.socket.fireEvent( - `digital_alchemy_retrieve_state_${domain}`, - { app: getIdentifier() }, - false, - ); - // wait 1 second - await sleep(SECOND); - if (loaded) { - return; - } - } - // - // give up - // - // This can occur when the extension has not seen this app yet. - // Maybe this app was brought offline with no persistent cache, and hass was reset? - // - // It can call digital-alchemy.reload() to register this app to properly fulfill this request - // But it still wouldn't cause that data to be revived. - // Hopefully sane logic for value defaulting was put in - // - - logger.warn( - { - attempts: RETRY, - domain, - missing: missingEntities(), - name: "onConnect", - }, - `could not retrieve current data from synapse`, - ); - LOAD_ME = undefined; - remove(); - }); - - // ## Registry interactions - return { - // ### Add - add(data: DATA) { - const id = is.empty(data.unique_id) - ? generateHash(`${getIdentifier()}:${data.name}`) - : data.unique_id; - if (registry.has(id)) { - throw new InternalError( - context, - `ENTITY_COLLISION`, - `${domain} registry already id`, - ); - } - registry.set(id, data); - if (initComplete) { - logger.warn( - { context: context, domain, name: data.name }, - `late entity generation`, - ); - } - logger.debug({ name: data.name }, `register {%s}`, domain); - return id; - }, - // ### byId - byId(id: string) { - return registry.get(id); - }, - - // ### getCache - async getCache(id: string, defaultValue?: T): Promise { - return await cache.get(CACHE_KEY(id), defaultValue); - }, - - // ### loadFromHass - loadFromHass, - - // ### send - async send(id: string, data: object) { - if (hass.socket.connectionState !== "connected") { - logger.debug( - { name: "send" }, - `socket connection isn't active, not sending update event`, - ); - return; - } - await hass.socket.fireEvent( - `digital_alchemy_event`, - { data, id }, - false, - ); - }, - // ### setCache - async setCache(id: string, value: unknown) { - await cache.set(CACHE_KEY(id), value); - }, - }; - }; -} diff --git a/src/extensions/scene.extension.ts b/src/extensions/scene.extension.ts deleted file mode 100644 index 282f7aa..0000000 --- a/src/extensions/scene.extension.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { TBlackHole, TContext, TServiceParams } from "@digital-alchemy/core"; - -type TScene = { - exec: () => TBlackHole; - context: TContext; - icon?: string; - name: string; -}; - -type HassSceneUpdateEvent = { - event_type: "digital_alchemy_activate"; - data: { id: string }; -}; - -export function Scene({ - logger, - hass, - synapse, - context, - internal, -}: TServiceParams) { - const registry = synapse.registry({ - context, - domain: "scene", - }); - - // ### Listen for socket events - hass.socket.onEvent({ - context: context, - event: "digital_alchemy_activate", - exec({ data }: HassSceneUpdateEvent) { - const item = registry.byId(data.id); - if (!item) { - return; - } - const { exec, name } = item; - logger.trace({ name }, `scene activate service call`); - setImmediate(async () => { - await internal.safeExec(async () => await exec()); - }); - }, - }); - - /** - * ### Register a new scene - * - * Basically the same thing as a button - */ - function create(entity: TScene) { - registry.add(entity); - } - return create; -} diff --git a/src/extensions/sensor.extension.ts b/src/extensions/sensor.extension.ts deleted file mode 100644 index 343538f..0000000 --- a/src/extensions/sensor.extension.ts +++ /dev/null @@ -1,236 +0,0 @@ -import { - each, - is, - NOT_FOUND, - TBlackHole, - TContext, - TServiceParams, -} from "@digital-alchemy/core"; - -import { SensorDeviceClasses } from ".."; - -type TSensor = { - context: TContext; - defaultState?: STATE; - icon?: string; - defaultAttributes?: ATTRIBUTES; - name: string; -} & SensorDeviceClasses; - -type SensorValue = string | number; -type SwitchUpdateCallback< - STATE extends SensorValue = SensorValue, - ATTRIBUTES extends object = object, -> = (options: { state?: STATE; attributes?: ATTRIBUTES }) => TBlackHole; - -export type VirtualSensor< - STATE extends SensorValue = SensorValue, - ATTRIBUTES extends object = object, -> = { - icon: string; - attributes: ATTRIBUTES; - _rawAttributes?: ATTRIBUTES; - name: string; - onUpdate: (callback: SwitchUpdateCallback) => void; - state: STATE; -} & SensorDeviceClasses; - -export function Sensor({ - logger, - context, - internal, - lifecycle, - synapse, -}: TServiceParams) { - const registry = synapse.registry({ - context, - details: entity => ({ - attributes: entity._rawAttributes, - device_class: entity.device_class, - state: entity.state, - unit_of_measurement: entity.unit_of_measurement, - }), - domain: "sensor", - }); - - // # Sensor creation function - function create< - STATE extends SensorValue = SensorValue, - ATTRIBUTES extends object = object, - >(entity: TSensor) { - type CacheValue = { - attributes: ATTRIBUTES; - state: STATE; - }; - - const callbacks = [] as SwitchUpdateCallback[]; - let state: STATE; - let attributes: ATTRIBUTES; - - function setState(newState: STATE) { - if (state === newState) { - return; - } - logger.trace({ name: entity.name, newState }, `update sensor state`); - state = newState; - setImmediate(async () => { - await registry.setCache(id, { attributes, state }); - await registry.send(id, { state }); - - await each( - callbacks, - async callback => - await internal.safeExec(async () => await callback({ state })), - ); - }); - } - - function setAttributes(newAttributes: ATTRIBUTES) { - if (is.equal(attributes, newAttributes)) { - return; - } - attributes = newAttributes; - setImmediate(async () => { - logger.trace({ attributes, id }, `update sensor attributes (all)`); - await registry.setCache(id, { attributes, state }); - await registry.send(id, { attributes }); - - await each( - callbacks, - async callback => - await internal.safeExec(async () => await callback({ attributes })), - ); - }); - } - - async function setAttribute< - KEY extends keyof ATTRIBUTES, - VALUE extends ATTRIBUTES[KEY], - >(key: KEY, value: VALUE) { - if (is.equal(attributes[key], value)) { - return; - } - attributes[key] = value; - setImmediate(async () => { - logger.trace({ id, key, value }, `update sensor attributes (single)`); - await registry.setCache(id, { attributes, state }); - await registry.send(id, { attributes }); - - await each( - callbacks, - async callback => - await internal.safeExec(async () => await callback({ attributes })), - ); - }); - } - - // ## Wait until bootstrap to load cache - lifecycle.onBootstrap(async () => { - let data = await registry.getCache(id); - if (!data) { - data = { - attributes: entity.defaultAttributes, - state: entity.defaultState, - }; - registry.loadFromHass(id, data => { - if (is.empty(data)) { - // wat - return; - } - logger.debug({ data, id, name: entity.name }, `received value`); - state = data.state; - attributes = data.attributes; - }); - } - state = data.state; - attributes = data.attributes; - }); - - // ## Proxy object as return - const sensorOut = new Proxy({} as VirtualSensor, { - // ### Getters - get(_, property: keyof VirtualSensor) { - if (property === "state") { - return state; - } - if (property === "unit_of_measurement") { - return entity.unit_of_measurement; - } - if (property === "device_class") { - return entity.device_class; - } - if (property === "name") { - return entity.name; - } - if (property === "onUpdate") { - return (callback: SwitchUpdateCallback) => { - callbacks.push(callback); - return () => { - const index = callbacks.indexOf(callback); - if (index !== NOT_FOUND) { - callbacks.splice(callbacks.indexOf(callback)); - } - }; - }; - } - if (property === "_rawAttributes") { - return attributes; - } - if (property === "attributes") { - return new Proxy({} as ATTRIBUTES, { - get: >( - _: ATTRIBUTES, - property: KEY, - ) => { - return attributes[property]; - }, - set: < - KEY extends Extract, - VALUE extends ATTRIBUTES[KEY], - >( - _: ATTRIBUTES, - property: KEY, - value: VALUE, - ) => { - setAttribute(property, value); - return true; - }, - }); - } - if (property === "icon") { - return entity.icon; - } - return undefined; - }, - ownKeys: () => { - return [ - "state", - "unit_of_measurement", - "device_class", - "name", - "onUpdate", - "attributes", - ]; - }, - // ### Setters - set(_, property: string, value: unknown) { - if (property === "state") { - setState(value as STATE); - return true; - } - if (property === "attributes") { - setAttributes(value as ATTRIBUTES); - return true; - } - return false; - }, - }); - - // ## Validate a good id was passed, and it's the only place in code that's using it - const id = registry.add(sensorOut); - - return sensorOut; - } - - return create; -} diff --git a/src/extensions/socket.extension.ts b/src/extensions/socket.extension.ts new file mode 100644 index 0000000..6097a26 --- /dev/null +++ b/src/extensions/socket.extension.ts @@ -0,0 +1,56 @@ +import { SECOND, TServiceParams } from "@digital-alchemy/core"; + +export function SocketExtension({ + logger, + lifecycle, + hass, + scheduler, + config, + internal, +}: TServiceParams) { + const getIdentifier = () => internal.boot.application.name; + const name = (a: string) => [config.synapse.EVENT_NAMESPACE, a, getIdentifier()].join("/"); + + // * onPostConfig + lifecycle.onPostConfig(async () => { + if (!config.synapse.EMIT_HEARTBEAT) { + return; + } + logger.trace({ name: "onPostConfig" }, `starting heartbeat`); + scheduler.interval({ + exec: async () => await hass.socket.fireEvent(name("heartbeat")), + interval: config.synapse.HEARTBEAT_INTERVAL * SECOND, + }); + }); + + // * onConnect + hass.socket.onConnect(async () => { + if (!config.synapse.EMIT_HEARTBEAT) { + return; + } + logger.debug({ name: "onConnect" }, `reconnect heartbeat`); + await hass.socket.fireEvent(name("heartbeat")); + }); + + // * onPreShutdown + lifecycle.onPreShutdown(async () => { + if (!config.synapse.EMIT_HEARTBEAT) { + return; + } + logger.debug({ name: "onPreShutdown" }, `notifying synapse extension of shutdown`); + await hass.socket.fireEvent(name("shutdown")); + }); + + async function send(unique_id: string, data: object): Promise { + if (hass.socket.connectionState !== "connected") { + logger.debug({ name: "send" }, `socket connection isn't active, not sending update event`); + return; + } + await hass.socket.fireEvent(name("update"), { + data, + unique_id, + }); + } + + return { send }; +} diff --git a/src/extensions/storage.extension.ts b/src/extensions/storage.extension.ts new file mode 100644 index 0000000..3705ea2 --- /dev/null +++ b/src/extensions/storage.extension.ts @@ -0,0 +1,140 @@ +import { InternalError, is, TServiceParams } from "@digital-alchemy/core"; +import { ENTITY_STATE, PICK_ENTITY, TRawDomains } from "@digital-alchemy/hass"; + +import { AddEntityOptions, EntityConfigCommon, TSynapseId } from "../helpers"; + +type TSynapseEntityStorage = { + unique_id: TSynapseId; + set: (key: KEY, value: CONFIGURATION[KEY]) => void; + get: (key: KEY) => CONFIGURATION[KEY]; + export: () => CONFIGURATION; +}; + +const LATE_READY = -1; + +type AddStateOptions> = { + domain: TRawDomains; + entity: AddEntityOptions; + /** + * initial import from typescript defs + */ + load_config_keys: (keyof AddEntityOptions)[]; + /** + * when loading data from hass, map `state` to this config property + */ + map_state: Extract; + /** + * when loading data from hass, import these config properties from entity attributes + */ + map_config: ConfigMapper>[]; +}; + +export type ConfigMapper = + | { + key: KEY; + load(entity: ENTITY_STATE): unknown; + } + | KEY; + +export function StorageExtension({ logger, context, lifecycle, hass, synapse }: TServiceParams) { + const registry = new Map(); + const domain_lookup = new Map(); + + function dump() { + const list = [...registry.keys()]; + const out = {} as Record; + list.forEach(i => { + const storage = registry.get(i); + const section = domain_lookup.get(i); + out[section] ??= []; + out[section].push(storage.export()); + }); + return out; + } + + // #MARK: add + function add>({ + entity, + load_config_keys, + map_config = [], + domain, + map_state, + }: AddStateOptions) { + if (registry.has(entity.unique_id as TSynapseId)) { + throw new InternalError(context, `ENTITY_COLLISION`, `${domain} registry already id`); + } + domain_lookup.set(entity.unique_id, domain); + let initialized = false; + + const CURRENT_VALUE = {} as Record; + const load = [ + ...load_config_keys, + "attributes", + "entity_category", + "icon", + "name", + "suggested_object_id", + "translation_key", + "unique_id", + ] as (keyof EntityConfigCommon)[]; + load.forEach(key => (CURRENT_VALUE[key] = entity[key])); + + // * storage object + const storage = { + export: () => ({ ...CURRENT_VALUE }), + get: key => CURRENT_VALUE[key], + set: (key, value) => { + CURRENT_VALUE[key] = value; + if (initialized) { + setImmediate(async () => await synapse.socket.send(entity.unique_id, CURRENT_VALUE)); + } + }, + unique_id: entity.unique_id, + } as TSynapseEntityStorage; + registry.set(entity.unique_id as TSynapseId, storage as unknown as TSynapseEntityStorage); + + // * value loading + if (!is.empty(map_state) || !is.empty(map_config)) { + lifecycle.onReady(async () => { + const config = hass.entity.registry.current.find(i => i.unique_id === entity.unique_id); + if (!config) { + logger.warn({ options: entity }, "cannot find entity in hass registry"); + initialized = true; + return; + } + const entity_id = config.entity_id; + const reference = hass.entity.byId(entity_id); + if (reference.state === "unavailable") { + logger.trace({ name: entity_id, state: reference.state }, `waiting for initial value`); + await reference.nextState(); + logger.trace({ name: entity_id }, "received"); + } + + if (!is.empty(map_state)) { + storage.set(map_state, reference.state as CONFIGURATION[typeof map_state]); + } + + map_config.forEach(config => { + if (is.string(config)) { + storage.set( + config, + reference.attributes[ + config as keyof typeof reference.attributes + ] as CONFIGURATION[typeof map_state], + ); + return; + } + storage.set(config.key, config.load(reference) as CONFIGURATION[typeof map_state]); + }); + initialized = true; + }, LATE_READY); + } else { + initialized = true; + } + + // * done + return storage; + } + + return { add, dump, find: (id: TSynapseId) => registry.get(id) }; +} diff --git a/src/extensions/switch.extension.ts b/src/extensions/switch.extension.ts deleted file mode 100644 index 09eab82..0000000 --- a/src/extensions/switch.extension.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { - each, - TBlackHole, - TContext, - TServiceParams, -} from "@digital-alchemy/core"; - -type TSwitch = { - context: TContext; - defaultState?: LocalOnOff; - icon?: string; - name: string; -}; - -type LocalOnOff = "on" | "off"; - -export type VirtualSwitch = { - state: LocalOnOff; - on: boolean; - icon: string; - name: string; - onUpdate: (callback: SwitchUpdateCallback) => void; -}; - -type UpdateSwitchBody = { - event_type: "digital_alchemy_switch_update"; - data: { data: { switch: string; state: LocalOnOff } }; -}; - -type SwitchUpdateCallback = (state: boolean) => TBlackHole; - -export function Switch({ - logger, - context, - lifecycle, - internal, - hass, - synapse, -}: TServiceParams) { - const registry = synapse.registry({ - context, - details: entity => ({ - state: entity.state, - }), - domain: "switch", - }); - - // ### Listen for socket events - hass.socket.onEvent({ - context: context, - event: "digital_alchemy_switch_update", - exec({ data: { data } }: UpdateSwitchBody) { - const item = registry.byId(data.switch); - if (!item) { - logger.warn( - { data, id: data.switch }, - `received switch update for unknown switch`, - ); - return; - } - const state = data.state; - if (!["on", "off"].includes(state)) { - logger.warn({ state }, `received bad value for state update`); - return; - } - if (item.state === state) { - return; - } - logger.trace( - { label: item.name, state: data.state }, - `received state update`, - ); - item.state = state; - }, - }); - - /** - * ### Register a new switch - * - * Can be interacted with via return object, or standard home assistant switch services - */ - function create(entity: TSwitch) { - const callbacks = [] as SwitchUpdateCallback[]; - let state: LocalOnOff; - - function setState(newState: LocalOnOff) { - if (newState === state) { - return; - } - state = newState; - setImmediate(async () => { - logger.trace({ id, name: setState, state }, `switch state updated`); - await registry.setCache(id, state); - await registry.send(id, { state }); - await each( - callbacks, - async callback => - await internal.safeExec(async () => await callback(state === "on")), - ); - }); - } - - lifecycle.onBootstrap(async () => { - state = await registry.getCache(id, entity.defaultState ?? "off"); - }); - - const returnEntity = new Proxy({} as VirtualSwitch, { - get(_, property: keyof VirtualSwitch) { - if (property === "state") { - return state; - } - if (property === "on") { - return state === "on"; - } - if (property === "icon") { - return entity.icon; - } - if (property === "name") { - return entity.name; - } - if (property === "onUpdate") { - return (callback: SwitchUpdateCallback) => callbacks.push(callback); - } - return undefined; - }, - set(_, property: keyof VirtualSwitch, value: LocalOnOff) { - if (property === "state") { - setImmediate(async () => await setState(value)); - return true; - } - if (property === "on") { - setImmediate(async () => await setState(value ? "on" : "off")); - return true; - } - return false; - }, - }); - - const id = registry.add(returnEntity); - return returnEntity; - } - - return create; -} diff --git a/src/helpers/base-domain.helper.ts b/src/helpers/base-domain.helper.ts new file mode 100644 index 0000000..6377010 --- /dev/null +++ b/src/helpers/base-domain.helper.ts @@ -0,0 +1,88 @@ +import { TBlackHole, TContext } from "@digital-alchemy/core"; +import { TRawDomains } from "@digital-alchemy/hass"; +import { createHash } from "crypto"; + +import { ConfigMapper } from "../extensions"; +import { EntityConfigCommon } from "./common-config.helper"; +import { TSynapseId } from "./utility.helper"; + +export type RemovableCallback = ( + data: DATA, + remove: () => void, +) => TBlackHole; + +export type CreateRemovableCallback = ( + callback: RemovableCallback, +) => { remove: () => void }; + +export type DomainGeneratorOptions< + CONFIGURATION extends object, + EVENT_MAP extends Record, +> = { + /** + * The domain to map the code to on the python side + */ + domain: TRawDomains; + /** + * Context of the synapse extension generating + */ + context: TContext; + /** + * Bus Transfer events + */ + bus_events?: Extract[]; + /** + * Keys to map from `add_entity` options -> `proxy.configuration` + */ + load_config_keys?: Extract[]; + /** + * What to use instead of `undefined` / `None` + */ + default_config?: Partial; + /** + * when loading data from hass, map `state` to this config property + * + * will automatically use `state` if present in `load_config_keys` + */ + map_state?: Extract; + /** + * when loading data from hass, import these config properties from entity attributes + */ + map_config?: ConfigMapper>[]; +}; + +export type TEventMap = Record; + +export type AddEntityOptions< + CONFIGURATION extends object, + EVENT_MAP extends Record = Record, + ATTRIBUTES extends object = object, +> = { + context: TContext; +} & EntityConfigCommon & + CONFIGURATION & + Partial<{ + [EVENT in keyof EVENT_MAP]: RemovableCallback; + }>; + +export function generateHash(input: string) { + const hash = createHash("sha256"); + hash.update(input); + return hash.digest("hex"); +} + +export type BaseEvent = { + data: { + unique_id: TSynapseId; + }; +}; + +export const formatObjectId = (input: string) => + input + .trim() + .toLowerCase() + .replaceAll(/[^\d_a-z]+/g, "_") + .replaceAll(/^_+|_+$/g, "") + .replaceAll(/_+/g, "_"); + +export const LATE_READY = -1; diff --git a/src/helpers/common-config.helper.ts b/src/helpers/common-config.helper.ts new file mode 100644 index 0000000..92e336a --- /dev/null +++ b/src/helpers/common-config.helper.ts @@ -0,0 +1,35 @@ +export type EntityConfigCommon = { + /** + * Attempt to create the entity id using this string + * + * `binary_sensor.{suggested id}` + * + * Home assistant _may_ append numbers to the end in case of object_id conflicts where `unique_id` isn't the same. + * + * > **NOTE:** Default value based on `name` + */ + suggested_object_id?: string; + /** + * Provide your own unique id for this entity + * + * This ID uniquely identifies the entity, through `entity_id` renames + */ + unique_id?: string; + icon?: string; + /** + * An entity with a category will: + * - Not be exposed to cloud, Alexa, or Google Assistant components + * - Not be included in indirect service calls to devices or areas + * + * **Config**: An entity which allows changing the configuration of a device. + * + * **Diagnostic**: An entity exposing some configuration parameter, or diagnostics of a device. + */ + entity_category?: "config" | "diagnostic"; + /** + * Default name to provide for the entity + */ + name: string; + translation_key?: string; + attributes?: ATTRIBUTES; +}; diff --git a/src/helpers/device-class.helper.ts b/src/helpers/device-class.helper.ts deleted file mode 100644 index e86da8f..0000000 --- a/src/helpers/device-class.helper.ts +++ /dev/null @@ -1,472 +0,0 @@ -/** - * TODO: this tsdoc is helpful, can it be integration with the rest of the definitions? - */ -export enum DeviceClass { - /** - * Generic sensor. This is the default and doesn’t need to be set. - */ - None = "None", - /** - * Apparent power in VA. - */ - apparent_power = "apparent_power", - /** - * Air Quality Index - */ - aqi = "aqi", - /** - * Atmospheric pressure in cbar, bar, hPa, inHg, kPa, mbar, Pa, psi - */ - atmospheric_pressure = "atmospheric_pressure", - /** - * Percentage of battery that is left - */ - battery = "battery", - /** - * Carbon Dioxide in CO2 (Smoke) - */ - carbon_dioxide = "carbon_dioxide", - /** - * Carbon Monoxide in CO (Gas CNG/LPG) - */ - carbon_monoxide = "carbon_monoxide", - /** - * Current in A - */ - current = "current", - /** - * Data rate in bit/s, kbit/s, Mbit/s, Gbit/s, B/s, kB/s, MB/s, GB/s, KiB/s, MiB/s, or GiB/s - */ - data_rate = "data_rate", - /** - * Data size in bit, kbit, Mbit, Gbit, B, kB, MB, GB, TB, PB, EB, ZB, YB, KiB, MiB, GiB, TiB, PiB, EiB, ZiB, or YiB - */ - data_size = "data_size", - /** - * Date string (ISO 8601) - */ - date = "date", - /** - * Generic distance in km, m, cm, mm, mi, yd, or in - */ - distance = "distance", - /** - * Duration in days, hours, minutes or seconds - */ - duration = "duration", - /** - * Energy in Wh, kWh or MWh - */ - energy = "energy", - /** - * Has a limited set of (non-numeric) states - */ - enum = "enum", - /** - * Frequency in Hz, kHz, MHz or GHz - */ - frequency = "frequency", - /** - * Gas volume in m³ or ft³ - */ - gas = "gas", - /** - * Percentage of humidity in the air - */ - humidity = "humidity", - /** - * The current light level in lx or lm - */ - illuminance = "illuminance", - /** - * Percentage of water in a substance - */ - moisture = "moisture", - /** - * The monetary value - */ - monetary = "monetary", - /** - * Concentration of Nitrogen Dioxide in µg/m³ - */ - nitrogen_dioxide = "nitrogen_dioxide", - /** - * Concentration of Nitrogen Monoxide in µg/m³ - */ - nitrogen_monoxide = "nitrogen_monoxide", - /** - * Concentration of Nitrous Oxide in µg/m³ - */ - nitrous_oxide = "nitrous_oxide", - /** - * Concentration of Ozone in µg/m³ - */ - ozone = "ozone", - /** - * Concentration of particulate matter less than 1 micrometer in µg/m³ - */ - pm1 = "pm1", - /** - * Concentration of particulate matter less than 10 micrometers in µg/m³ - */ - pm10 = "pm10", - /** - * Concentration of particulate matter less than 2.5 micrometers in µg/m³ - */ - pm25 = "pm25", - /** - * Power factor in % - */ - power_factor = "power_factor", - /** - * Power in W or kW - */ - power = "power", - /** - * Precipitation intensity in in/d, in/h, mm/d, or mm/h - */ - precipitation_intensity = "precipitation_intensity", - /** - * Pressure in Pa, kPa, hPa, bar, cbar, mbar, mmHg, inHg, or psi - */ - pressure = "pressure", - /** - * Reactive power in var - */ - reactive_power = "reactive_power", - /** - * Signal strength in dB or dBm - */ - signal_strength = "signal_strength", - /** - * Sound pressure in dB or dBA - */ - sound_pressure = "sound_pressure", - /** - * Generic speed in ft/s, in/d, in/h, km/h, kn, m/s, mph, or mm/d - */ - speed = "speed", - /** - * Concentration of sulphur dioxide in µg/m³ - */ - sulphur_dioxide = "sulphur_dioxide", - /** - * Temperature in °C or °F - */ - temperature = "temperature", - /** - * Datetime object or timestamp string (ISO 8601) - */ - timestamp = "timestamp", - /** - * Concentration of volatile organic compounds in µg/m³ - */ - volatile_organic_compounds = "volatile_organic_compounds", - /** - * Voltage in V - */ - voltage = "voltage", - /** - * Generic volume in L, mL, gal, fl. oz., m³, or ft³ - */ - volume = "volume", - /** - * Water consumption in L, gal, m³, or ft³ - */ - water = "water", - /** - * Generic mass in kg, g, mg, µg, oz, or lb - */ - weight = "weight", - /** - * Wind speed in ft/s, km/h, kn, m/s, or mph - */ - wind_speed = "wind_speed", -} - -type DurationSensor = { - device_class: "duration"; - unit_of_measurement: "h" | "min" | "s" | "d"; -}; -type TemperatureSensor = { - device_class: "temperature"; - unit_of_measurement: "K" | "°C" | "°F"; -}; -type Precipitation = { - device_class: "precipitation"; - unit_of_measurement: "cm" | "in" | "mm"; -}; -type ApparentPowerSensor = { - device_class: "apparent_power"; - unit_of_measurement: "VA"; -}; -type WaterSensor = { - device_class: "water"; - unit_of_measurement: "L" | "gal" | "m³" | "ft³" | "CCF"; -}; -type WeightSensor = { - device_class: "weight"; - unit_of_measurement: "kg" | "g" | "mg" | "µg" | "oz" | "lb" | "st"; -}; -type WindSpeedSensor = { - device_class: "wind_speed"; - unit_of_measurement: "ft/s" | "km/h" | "kn" | "m/s" | "mph"; -}; -type SpeedSensor = { - device_class: "speed"; - unit_of_measurement: - | "ft/s" - | "in/d" - | "in/h" - | "km/h" - | "kn" - | "m/s" - | "mph" - | "mm/d"; -}; -type VoltageSensor = { - device_class: "voltage"; - unit_of_measurement: "V" | "mV"; -}; -type SignalStrengthSensor = { - device_class: "signal_strength"; - unit_of_measurement: "dB" | "dBm"; -}; -type VolumeSensor = { - device_class: "volume"; - unit_of_measurement: "L" | "mL" | "gal" | "fl. oz." | "m³" | "ft³" | "CCF"; -}; -type SoundPressureSensor = { - device_class: "sound_pressure"; - unit_of_measurement: "dB" | "dBA"; -}; -type PressureSensor = { - device_class: "pressure"; - unit_of_measurement: - | "cbar" - | "bar" - | "hPa" - | "inHg" - | "kPa" - | "mbar" - | "Pa" - | "psi"; -}; -type ReactivePowerSensor = { - device_class: "reactive_power"; - unit_of_measurement: "var"; -}; -type PrecipitationIntensitySensor = { - device_class: "precipitation_intensity"; - unit_of_measurement: "in/d" | "in/h" | "mm/d" | "mm/h"; -}; -type PowerFactorSensor = { - device_class: "power_factor"; - unit_of_measurement: "%" | "None"; -}; -type PowerSensor = { - device_class: "power"; - unit_of_measurement: "W" | "kW"; -}; -type MixedGasSensor = { - device_class: - | "nitrogen_monoxide" - | "nitrous_oxide" - | "ozone" - | "pm1" - | "pm25" - | "pm10" - | "volatile_organic_compounds"; - unit_of_measurement: "µg/m³"; -}; -type IlluminanceSensor = { - device_class: "illuminance"; - unit_of_measurement: "lx"; -}; -type IrradianceSensor = { - device_class: "irradiance"; - unit_of_measurement: "W/m²" | "BTU/(h⋅ft²)"; -}; -type GasSensor = { - device_class: "gas"; - unit_of_measurement: "m³" | "ft³" | "CCF"; -}; -type FrequencySensor = { - device_class: "frequency"; - unit_of_measurement: "Hz" | "kHz" | "MHz" | "GHz"; -}; -type EnergySensor = { - device_class: "energy"; - unit_of_measurement: "Wh" | "kWh" | "MWh" | "MJ" | "GJ"; -}; -type DistanceSensor = { - device_class: "distance"; - unit_of_measurement: "km" | "m" | "cm" | "mm" | "mi" | "yd" | "in"; -}; -type MonetarySensor = { - device_class: "monetary"; - /** - * https://en.wikipedia.org/wiki/ISO_4217#Active_codes - */ - unit_of_measurement: string; -}; -type DataRateSensor = { - device_class: "data_rate"; - unit_of_measurement: - | "bit/s" - | "kbit/s" - | "Mbit/s" - | "Gbit/s" - | "B/s" - | "kB/s" - | "MB/s" - | "GB/s" - | "KiB/s" - | "MiB/s" - | "GiB/s"; -}; -type DataSizeSensor = { - device_class: "data_size"; - unit_of_measurement: - | "bit" - | "kbit" - | "Mbit" - | "Gbit" - | "B" - | "kB" - | "MB" - | "GB" - | "TB" - | "PB" - | "EB" - | "ZB" - | "YB" - | "KiB" - | "MiB" - | "GiB" - | "TiB" - | "PiB" - | "EiB" - | "ZiB" - | "YiB"; -}; -type AtmosphericPressureSensor = { - device_class: "atmospheric_pressure"; - unit_of_measurement: - | "cbar" - | "bar" - | "hPa" - | "inHg" - | "kPa" - | "mbar" - | "Pa" - | "psi"; -}; -type CurrentSensor = { - device_class: "current"; - unit_of_measurement: "A" | "mA"; -}; -type CarbonSensor = { - device_class: "carbon_dioxide" | "carbon_monoxide"; - unit_of_measurement: "ppm"; -}; -type PercentSensor = { - device_class: "battery" | "humidity" | "moisture"; - unit_of_measurement: "%"; -}; -type DefaultSensor = { - /** - * The type/class of the sensor to set the icon in the frontend. - * - * @see https://www.hass.io/integrations/sensor/#device-class - */ - device_class?: "timestamp" | "date" | "aqi" | "enum"; - unit_of_measurement?: void; -}; - -export type SensorDeviceClasses = - | DurationSensor - | TemperatureSensor - | Precipitation - | ApparentPowerSensor - | WaterSensor - | WeightSensor - | WindSpeedSensor - | SpeedSensor - | VoltageSensor - | SignalStrengthSensor - | VolumeSensor - | SoundPressureSensor - | PressureSensor - | ReactivePowerSensor - | PowerFactorSensor - | PowerSensor - | PrecipitationIntensitySensor - | MixedGasSensor - | IlluminanceSensor - | IrradianceSensor - | PercentSensor - | GasSensor - | FrequencySensor - | EnergySensor - | DistanceSensor - | MonetarySensor - | DataRateSensor - | CurrentSensor - | CarbonSensor - | DataSizeSensor - | AtmosphericPressureSensor - | DefaultSensor; - -// type ValueTypes = "number" | "date" | "string"; - -// private valueType(deviceClass: string): ValueTypes { -// switch (deviceClass) { -// case "current": -// case "duration": -// case "temperature": -// case "precipitation": -// case "apparent_power": -// case "water": -// case "weight": -// case "wind_speed": -// case "speed": -// case "voltage": -// case "signal_strength": -// case "volume": -// case "sound_pressure": -// case "pressure": -// case "reactive_power": -// case "precipitation_intensity": -// case "power_factor": -// case "power": -// case "nitrogen_monoxide": -// case "nitrous_oxide": -// case "ozone": -// case "pm1": -// case "pm25": -// case "pm10": -// case "volatile_organic_compounds": -// case "illuminance": -// case "irradiance": -// case "gas": -// case "frequency": -// case "energy": -// case "distance": -// case "monetary": -// case "data_rate": -// case "data_size": -// case "atmospheric_pressure": -// case "carbon_dioxide": -// case "carbon_monoxide": -// case "battery": -// case "humidity": -// case "moisture": -// return "number"; -// case "timestamp": -// case "date": -// return "date"; -// default: -// return "string"; -// } -// } diff --git a/src/helpers/index.ts b/src/helpers/index.ts index 7813a97..55ca166 100644 --- a/src/helpers/index.ts +++ b/src/helpers/index.ts @@ -1,3 +1,4 @@ -export * from "./device-class.helper"; -export * from "./metrics.helper"; +export * from "./base-domain.helper"; +export * from "./common-config.helper"; +export * from "./sensor"; export * from "./utility.helper"; diff --git a/src/helpers/metrics.helper.ts b/src/helpers/metrics.helper.ts deleted file mode 100644 index aa5ad46..0000000 --- a/src/helpers/metrics.helper.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Counter, Summary } from "prom-client"; - -/** - * Tracks the number of times a button callback has been executed. - */ -export const BUTTON_EXECUTION_COUNT = new Counter({ - help: "Counts the number of times a button callback has been executed", - labelNames: ["context", "label"] as const, - name: "digital_alchemy_virtual_entity_button_callback_execution_count", -}); - -/** - * Counts the number of errors occurred during button callback executions. - */ -export const BUTTON_ERRORS = new Counter({ - help: "Counts the number of errors during button callback executions", - labelNames: ["context", "label"] as const, - name: "digital_alchemy_virtual_entity_button_callback_errors", -}); - -/** - * Summary for Execution Time - */ -export const BUTTON_EXECUTION_TIME = new Summary({ - help: "Measures the duration of button press callback execution", - labelNames: ["context", "label"] as const, - name: "digital_alchemy_virtual_entity_button_callback_execution_time", - percentiles: [0.5, 0.9, 0.99], -}); diff --git a/src/helpers/sensor.ts b/src/helpers/sensor.ts new file mode 100644 index 0000000..2432c2b --- /dev/null +++ b/src/helpers/sensor.ts @@ -0,0 +1,311 @@ +import { Dayjs } from "dayjs"; + +import { EntityConfigCommon } from "./common-config.helper"; + +type DurationSensor = { + device_class: "duration"; + unit_of_measurement: "h" | "min" | "s" | "d"; +}; + +type TemperatureSensor = { + device_class: "temperature"; + unit_of_measurement: "K" | "°C" | "°F"; +}; + +type Precipitation = { + device_class: "precipitation"; + unit_of_measurement: "cm" | "in" | "mm"; +}; + +type ApparentPowerSensor = { + device_class: "apparent_power"; + unit_of_measurement: "VA"; +}; + +type WaterSensor = { + device_class: "water"; + unit_of_measurement: "L" | "gal" | "m³" | "ft³" | "CCF"; +}; + +type WeightSensor = { + device_class: "weight"; + unit_of_measurement: "kg" | "g" | "mg" | "µg" | "oz" | "lb" | "st"; +}; + +type WindSpeedSensor = { + device_class: "wind_speed"; + unit_of_measurement: "ft/s" | "km/h" | "kn" | "m/s" | "mph"; +}; + +type SpeedSensor = { + device_class: "speed"; + unit_of_measurement: "ft/s" | "in/d" | "in/h" | "km/h" | "kn" | "m/s" | "mph" | "mm/d"; +}; + +type VoltageSensor = { + device_class: "voltage"; + unit_of_measurement: "V" | "mV"; +}; + +type SignalStrengthSensor = { + device_class: "signal_strength"; + unit_of_measurement: "dB" | "dBm"; +}; + +type VolumeSensor = { + device_class: "volume"; + unit_of_measurement: "L" | "mL" | "gal" | "fl. oz." | "m³" | "ft³" | "CCF"; +}; + +type SoundPressureSensor = { + device_class: "sound_pressure"; + unit_of_measurement: "dB" | "dBA"; +}; + +type PressureSensor = { + device_class: "pressure"; + unit_of_measurement: "cbar" | "bar" | "hPa" | "inHg" | "kPa" | "mbar" | "Pa" | "psi"; +}; + +type ReactivePowerSensor = { + device_class: "reactive_power"; + unit_of_measurement: "var"; +}; + +type PrecipitationIntensitySensor = { + device_class: "precipitation_intensity"; + unit_of_measurement: "in/d" | "in/h" | "mm/d" | "mm/h"; +}; + +type PowerFactorSensor = { + device_class: "power_factor"; + unit_of_measurement: "%" | "None"; +}; + +type PowerSensor = { + device_class: "power"; + unit_of_measurement: "W" | "kW"; +}; + +type MixedGasSensor = { + device_class: + | "nitrogen_monoxide" + | "nitrous_oxide" + | "ozone" + | "pm1" + | "pm25" + | "pm10" + | "volatile_organic_compounds"; + unit_of_measurement: "µg/m³"; +}; + +type IlluminanceSensor = { + device_class: "illuminance"; + unit_of_measurement: "lx"; +}; + +type IrradianceSensor = { + device_class: "irradiance"; + unit_of_measurement: "W/m²" | "BTU/(h⋅ft²)"; +}; + +type GasSensor = { + device_class: "gas"; + unit_of_measurement: "m³" | "ft³" | "CCF"; +}; + +type FrequencySensor = { + device_class: "frequency"; + unit_of_measurement: "Hz" | "kHz" | "MHz" | "GHz"; +}; + +type EnergySensor = { + device_class: "energy"; + unit_of_measurement: "Wh" | "kWh" | "MWh" | "MJ" | "GJ"; +}; + +type DistanceSensor = { + device_class: "distance"; + unit_of_measurement: "km" | "m" | "cm" | "mm" | "mi" | "yd" | "in"; +}; + +type MonetarySensor = { + device_class: "monetary"; + /** + * https://en.wikipedia.org/wiki/ISO_4217#Active_codes + */ + unit_of_measurement: string; +}; + +type DataRateSensor = { + device_class: "data_rate"; + unit_of_measurement: + | "bit/s" + | "kbit/s" + | "Mbit/s" + | "Gbit/s" + | "B/s" + | "kB/s" + | "MB/s" + | "GB/s" + | "KiB/s" + | "MiB/s" + | "GiB/s"; +}; + +type DataSizeSensor = { + device_class: "data_size"; + unit_of_measurement: + | "bit" + | "kbit" + | "Mbit" + | "Gbit" + | "B" + | "kB" + | "MB" + | "GB" + | "TB" + | "PB" + | "EB" + | "ZB" + | "YB" + | "KiB" + | "MiB" + | "GiB" + | "TiB" + | "PiB" + | "EiB" + | "ZiB" + | "YiB"; +}; + +type AtmosphericPressureSensor = { + device_class: "atmospheric_pressure"; + unit_of_measurement: "cbar" | "bar" | "hPa" | "inHg" | "kPa" | "mbar" | "Pa" | "psi"; +}; + +type CurrentSensor = { + device_class: "current"; + unit_of_measurement: "A" | "mA"; +}; + +type CarbonSensor = { + device_class: "carbon_dioxide" | "carbon_monoxide"; + unit_of_measurement: "ppm"; +}; +type PercentSensor = { + device_class: "battery" | "humidity" | "moisture"; + unit_of_measurement: "%"; +}; +type DefaultSensor = { + /** + * The type/class of the sensor to set the icon in the frontend. + * + * @see https://www.hass.io/integrations/sensor/#device-class + */ + device_class?: "timestamp" | "date" | "aqi" | "enum"; + unit_of_measurement?: void; +}; + +export const SENSOR_DEVICE_CLASS_CONFIG_KEYS = ["device_class", "unit_of_measurement"]; + +export enum SensorStateClass { + /** + * The state represents a measurement in present time, not a historical aggregation such as statistics or a prediction of the future. + * + * Examples of what should be classified `measurement` are: current temperature, humidity or electric power. + * + * Examples of what should not be classified as `measurement`: Forecasted temperature for tomorrow, yesterday's energy consumption or anything else that doesn't include the current measurement. + * + * For supported sensors, statistics of hourly min, max and average sensor readings is updated every 5 minutes. + */ + MEASUREMENT = "measurement", + /** + * The state represents a total amount that can both increase and decrease, e.g. a net energy meter. + * Statistics of the accumulated growth or decline of the sensor's value since it was first added is updated every 5 minutes. + * This state class should not be used for sensors where the absolute value is interesting instead of the accumulated growth or decline, for example remaining battery capacity or CPU load; in such cases state class measurement should be used instead. + */ + TOTAL = "total", + /** + * Similar to total, with the restriction that the state represents a monotonically increasing positive total which periodically restarts counting from 0, e.g. a daily amount of consumed gas, weekly water consumption or lifetime energy consumption. + * Statistics of the accumulated growth of the sensor's value since it was first added is updated every 5 minutes. + * A decreasing value is interpreted as the start of a new meter cycle or the replacement of the meter. + */ + TOTAL_INCREASING = "total_increasing", +} + +export type SensorDeviceClasses = + | DurationSensor + | TemperatureSensor + | Precipitation + | ApparentPowerSensor + | WaterSensor + | WeightSensor + | WindSpeedSensor + | SpeedSensor + | VoltageSensor + | SignalStrengthSensor + | VolumeSensor + | SoundPressureSensor + | PressureSensor + | ReactivePowerSensor + | PowerFactorSensor + | PowerSensor + | PrecipitationIntensitySensor + | MixedGasSensor + | IlluminanceSensor + | IrradianceSensor + | PercentSensor + | GasSensor + | FrequencySensor + | EnergySensor + | DistanceSensor + | MonetarySensor + | DataRateSensor + | CurrentSensor + | CarbonSensor + | DataSizeSensor + | AtmosphericPressureSensor + | DefaultSensor; + +export type SensorConfiguration = EntityConfigCommon & + SensorDeviceClasses & { + state?: string | number; + /** + * The number of decimals which should be used in the sensor's state when it's displayed. + */ + suggested_display_precision?: number; + /** + * The time when an accumulating sensor such as an electricity usage meter, gas meter, water meter etc. was initialized. + * + * If the time of initialization is unknown, set it to `None`. + * + * Note that the `datetime.datetime` returned by the `last_reset` property will be converted to an ISO 8601-formatted string when the entity's state attributes are updated. When changing `last_reset`, the `state` must be a valid number. + */ + last_reset?: Dayjs; + /** + * The unit of measurement to be used for the sensor's state. + * For sensors with a unique_id, this will be used as the initial unit of measurement, which users can then override. + * For sensors without a unique_id, this will be the unit of measurement for the sensor's state. + * This property is intended to be used by integrations to override automatic unit conversion rules, for example, + * to make a temperature sensor always display in °C regardless of whether the configured unit system prefers °C or °F, + * or to make a distance sensor always display in miles even if the configured unit system is metric. + */ + suggested_unit_of_measurement?: string; + } & ( + | { + /** + * In case this sensor provides a textual state, this property can be used to provide a list of possible states. + * Requires the enum device class to be set. + * Cannot be combined with `state_class` or `native_unit_of_measurement`. + */ + options?: string[]; + } + | { + /** + * Type of state. + * If not `None`, the sensor is assumed to be numerical and will be displayed as a line-chart in the frontend instead of as discrete values. + */ + state_class?: SensorStateClass; + } + ); diff --git a/src/helpers/utility.helper.ts b/src/helpers/utility.helper.ts index 6fdd5c4..324fe18 100644 --- a/src/helpers/utility.helper.ts +++ b/src/helpers/utility.helper.ts @@ -1 +1,59 @@ export type OnOff = "on" | "off" | "unavailable"; + +export interface ISynapseBrand { + _synapse: symbol; +} + +export type TSynapseId = string & ISynapseBrand; +export const STORAGE_BOOTSTRAP_PRIORITY = 1; + +export type SynapseDescribeResponse = { + hostname: string; + host: string; + title: string; + app: string; + device: HassDeviceMetadata; + unique_id: string; + username: string; +}; + +export type HassDeviceMetadata = { + /** + * A URL on which the device or service can be configured, linking to paths inside the Home Assistant UI can be done by using `homeassistant://`. + */ + configuration_url?: string; + /** + * The manufacturer of the device, will be overridden if `manufacturer` is set. Useful for example for an integration showing all devices on the network. + */ + manufacturer?: string; + /** + * The model of the device, will be overridden if `model` is set. Useful for example for an integration showing all devices on the network. + */ + model?: string; + /** + * Default name of this device, will be overridden if `name` is set. Useful for example for an integration showing all devices on the network. + */ + name?: string; + /** + * The hardware version of the device. + */ + hw_version?: string; + /** + * The serial number of the device. Unlike a serial number in the `identifiers` set, this does not need to be unique. + */ + serial_number?: string; + /** + * The suggested name for the area where the device is located. + * + * Use readable name, not area id ("Living Room" not "living_room") + */ + suggested_area?: string; + /** + * The firmware version of the device. + */ + sw_version?: string; +}; + +export type SynapseStateResponse = { + // +}; diff --git a/src/mock/generator.ts b/src/mock/generator.ts new file mode 100644 index 0000000..3287b53 --- /dev/null +++ b/src/mock/generator.ts @@ -0,0 +1,119 @@ +import { SECOND, TServiceParams } from "@digital-alchemy/core"; +import dayjs from "dayjs"; + +export function EntityGenerator({ scheduler, synapse, context, logger }: TServiceParams) { + try { + const sensor = synapse.sensor({ + attributes: { + destination: "saturn", + }, + context, + device_class: "speed", + // entity_category: "diagnostic", + name: "Test the sensor", + + state: 20, + suggested_object_id: "magic_the_sensor", + unit_of_measurement: "ft/s", + }); + const binary_sensor = synapse.binary_sensor({ + context, + device_class: "window", + name: "blinkey", + suggested_object_id: "blinkey_the_binary_sensor", + }); + scheduler.interval({ + exec() { + const number = Math.floor(Math.random() * 1000); + sensor.storage.set("state", number); + binary_sensor.storage.set("is_on", !binary_sensor.storage.get("is_on")); + }, + interval: SECOND, + }); + const button = synapse.button({ + context, + device_class: "identify", + name: "example button", + press() { + logger.info("press()"); + }, + suggested_object_id: "button_the_example", + }); + button.onPress(() => { + logger.info("onPress()"); + }); + const scene = synapse.scene({ + activate() { + logger.info("scene activated"); + }, + context, + name: "Dynamic Scene", + suggested_object_id: "setting_the_stage", + }); + scene.onActivate(() => { + logger.info("scene activated callback"); + }); + synapse.switch({ + context, + name: "Example switch", + }); + const acp = synapse.alarm_control_panel({ + arm_night({ code }) { + logger.info({ code }, `arm_night called with code via static attachment`); + }, + context, + name: "Example alarm panel", + }); + acp.onArmNight(({ code }) => + logger.info({ code }, `arm_night called with code via dynamic attachment`), + ); + synapse.lock({ + context, + is_locked: false, + name: "Example lock", + suggested_object_id: "example_the_lock", + }); + synapse.number({ + context, + name: "Example number", + native_max_value: 420, + native_min_value: 69, + native_value: 80, + suggested_object_id: "example_the_number", + }); + synapse.text({ + context, + name: "Example text", + native_value: "banana", + suggested_object_id: "example_the_text", + }); + synapse.select({ + context, + current_option: "a", + name: "Example select", + options: ["a", "b", "c"], + suggested_object_id: "example_the_select", + }); + synapse.datetime({ + context, + name: "Example datetime", + native_value: dayjs("2024-01-01 00:00:00"), + suggested_object_id: "example_the_datetime", + }); + synapse.date({ + context, + name: "Example date", + native_value: "2006-06-06", + suggested_object_id: "example_the_date", + }); + synapse.time({ + context, + name: "Example time", + native_value: "14:32:51", + suggested_object_id: "example_the_time", + }); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + } +} diff --git a/src/mock/main.ts b/src/mock/main.ts new file mode 100644 index 0000000..a1f59f6 --- /dev/null +++ b/src/mock/main.ts @@ -0,0 +1,49 @@ +import { CreateApplication } from "@digital-alchemy/core"; +import { LIB_FASTIFY } from "@digital-alchemy/fastify-extension"; +import { LIB_HASS } from "@digital-alchemy/hass"; +import dayjs from "dayjs"; +import advancedFormat from "dayjs/plugin/advancedFormat"; +import isBetween from "dayjs/plugin/isBetween"; +import timezone from "dayjs/plugin/timezone"; +import utc from "dayjs/plugin/utc"; +import weekOfYear from "dayjs/plugin/weekOfYear"; + +import { LIB_SYNAPSE } from "../synapse.module"; +import { EntityGenerator } from "./generator"; + +dayjs.extend(weekOfYear); +dayjs.extend(advancedFormat); +dayjs.extend(isBetween); +dayjs.extend(utc); +dayjs.extend(timezone); + +export const ENTITY_GENERATOR = CreateApplication({ + libraries: [LIB_HASS, LIB_SYNAPSE, LIB_FASTIFY], + name: "entity_generator", + services: { + generator: EntityGenerator, + }, +}); + +declare module "@digital-alchemy/core" { + export interface LoadedModules { + entity_generator: typeof ENTITY_GENERATOR; + } +} + +setImmediate( + async () => + await ENTITY_GENERATOR.bootstrap({ + configuration: { + boilerplate: { LOG_LEVEL: "debug" }, + fastify: { PORT: 3000 }, + synapse: { + METADATA: { + hw_version: "0.0.1", + suggested_area: "Living Room", + }, + METADATA_TITLE: "Synapse Mocks", + }, + }, + }), +); diff --git a/src/synapse.module.ts b/src/synapse.module.ts index 4961d9c..7fc4761 100644 --- a/src/synapse.module.ts +++ b/src/synapse.module.ts @@ -1,76 +1,156 @@ -import { CreateLibrary } from "@digital-alchemy/core"; +import { CreateLibrary, InternalConfig } from "@digital-alchemy/core"; +import { LIB_FASTIFY } from "@digital-alchemy/fastify-extension"; import { LIB_HASS } from "@digital-alchemy/hass"; import { - BinarySensor, - Button, - Registry, - Scene, - Sensor, - Switch, + Configure, + Controller, + DeviceExtension, + DiscoveryExtension, + DomainGenerator, + SocketExtension, + StorageExtension, + VirtualAlarmControlPanel, + VirtualBinarySensor, + VirtualButton, + VirtualCamera, + VirtualClimate, + VirtualCover, + VirtualDate, + VirtualDateTime, + VirtualFan, + VirtualImage, + VirtualLawnMower, + VirtualLight, + VirtualLock, + VirtualMediaPlayer, + VirtualNotify, + VirtualNumber, + VirtualRemote, + VirtualScene, + VirtualSelect, + VirtualSensor, + VirtualSiren, + VirtualSwitch, + VirtualText, + VirtualTime, + VirtualTodoList, + VirtualUpdate, + VirtualVacuum, + VirtualValve, + VirtualWaterHeater, } from "./extensions"; +import { HassDeviceMetadata } from "./helpers"; + +const DOMAINS = { + alarm_control_panel: VirtualAlarmControlPanel, + binary_sensor: VirtualBinarySensor, + button: VirtualButton, + camera: VirtualCamera, + climate: VirtualClimate, + cover: VirtualCover, + date: VirtualDate, + datetime: VirtualDateTime, + fan: VirtualFan, + image: VirtualImage, + lawn_mower: VirtualLawnMower, + light: VirtualLight, + lock: VirtualLock, + media_player: VirtualMediaPlayer, + notify: VirtualNotify, + number: VirtualNumber, + remote: VirtualRemote, + scene: VirtualScene, + select: VirtualSelect, + sensor: VirtualSensor, + siren: VirtualSiren, + switch: VirtualSwitch, + text: VirtualText, + time: VirtualTime, + todo_list: VirtualTodoList, + update: VirtualUpdate, + vacuum: VirtualVacuum, + valve: VirtualValve, + water_heater: VirtualWaterHeater, +}; export const LIB_SYNAPSE = CreateLibrary({ configuration: { - ANNOUNCE_AT_CONNECT: { - default: false, - description: [ - "Emit the entity list update every time this application is booted", - "digital-alchemy.reload() service available for manual reload", - ], + EMIT_HEARTBEAT: { + default: true, + description: ["Emit a heartbeat pulse so the extension knows the service is alive"], type: "boolean", }, - APPLICATION_IDENTIFIER: { + EVENT_NAMESPACE: { + default: "digital_alchemy", description: [ - "Used to generate unique ids in home assistant", - "Defaults to application name", + "You almost definitely do not want to change this", + "Must be matched on the python integration side", ], type: "string", }, - EMIT_HEARTBEAT: { - default: true, - description: ["Emit a pulse so the extension knows the service is alive"], - type: "boolean", - }, HEARTBEAT_INTERVAL: { default: 5, description: "Seconds between heartbeats", type: "number", }, + METADATA: { + description: [ + "A string to uniquely identify this application", + "Should be unique within home assistant, such as a uuid", + "Default value calculated from hostname + username + app_name", + ], + type: "internal", + } as InternalConfig, + METADATA_HOST: { + description: ["Host name to announce as"], + type: "string", + }, + METADATA_TITLE: { + description: ["Title for the integration provided by this app", "Defaults to app name"], + type: "string", + }, + METADATA_UNIQUE_ID: { + description: [ + "A string to uniquely identify this application", + "Should be unique within home assistant, such as a uuid", + "Default value calculated from hostname + username + app_name", + ], + type: "string", + }, + PUBLISH_BONJOUR: { + default: true, + type: "boolean", + }, }, - depends: [LIB_HASS], + depends: [LIB_HASS, LIB_FASTIFY], name: "synapse", - // everything depends registry - priorityInit: ["registry"], + priorityInit: ["generator", "storage"], services: { /** - * create `binary_sensor` domain entities + * internal */ - binary_sensor: BinarySensor, - /** - * create `button` domain entities - * - * run callback on activation - */ - button: Button, - /** - * internal tools for managing entities - */ - registry: Registry, + configure: Configure, + /** - * create `scene` domain entities - * - * run callback on activation + * fastify bindings */ - scene: Scene, + controller: Controller, + /** - * create `sensor` domain entities + * Internal tools to create the device that registers with entities */ - sensor: Sensor, + device: DeviceExtension, + /** - * create `switch` domain entities + * Zeroconf discovery */ - switch: Switch, + discovery: DiscoveryExtension, + generator: DomainGenerator, + + socket: SocketExtension, + storage: StorageExtension, + ...DOMAINS, }, });