From 46afaf893cb8f2a22efd19df3218ba70401aa7a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:10:57 +0000 Subject: [PATCH 001/104] [api]: Bump de.siegmar:fastcsv from 3.1.0 to 3.2.0 Bumps [de.siegmar:fastcsv](https://github.com/osiegmar/FastCSV) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/osiegmar/FastCSV/releases) - [Changelog](https://github.com/osiegmar/FastCSV/blob/main/CHANGELOG.md) - [Commits](https://github.com/osiegmar/FastCSV/compare/v3.1.0...v3.2.0) --- updated-dependencies: - dependency-name: de.siegmar:fastcsv dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 3e378dd64..010d02a3c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,7 +26,7 @@ dependencyResolutionManagement { library("netty-transport", "io.netty:netty-transport:4.1.110.Final") library("netty-codec", "io.netty:netty-codec:4.1.110.Final") library("xml", "com.fasterxml:aalto-xml:1.3.2") - library("csv", "de.siegmar:fastcsv:3.1.0") + library("csv", "de.siegmar:fastcsv:3.2.0") library("apache-lang3", "org.apache.commons:commons-lang3:3.14.0") library("apache-codec", "commons-codec:commons-codec:1.17.0") library("apache-collections", "org.apache.commons:commons-collections4:4.4") From 3a7dd97dd2f571f77998da8f02681391b2612e61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:10:31 +0000 Subject: [PATCH 002/104] [api]: Bump the kotest group with 2 updates Bumps the kotest group with 2 updates: [io.kotest:kotest-assertions-core](https://github.com/kotest/kotest) and [io.kotest:kotest-runner-junit5](https://github.com/kotest/kotest). Updates `io.kotest:kotest-assertions-core` from 5.9.0 to 5.9.1 - [Release notes](https://github.com/kotest/kotest/releases) - [Commits](https://github.com/kotest/kotest/compare/v5.9.0...v5.9.1) Updates `io.kotest:kotest-runner-junit5` from 5.9.0 to 5.9.1 - [Release notes](https://github.com/kotest/kotest/releases) - [Commits](https://github.com/kotest/kotest/compare/v5.9.0...v5.9.1) --- updated-dependencies: - dependency-name: io.kotest:kotest-assertions-core dependency-type: direct:production update-type: version-update:semver-patch dependency-group: kotest - dependency-name: io.kotest:kotest-runner-junit5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: kotest ... Signed-off-by: dependabot[bot] --- settings.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 010d02a3c..80a6c7fcc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -34,8 +34,8 @@ dependencyResolutionManagement { library("apache-numbers-complex", "org.apache.commons:commons-numbers-complex:1.1") library("oshi", "com.github.oshi:oshi-core:6.6.1") library("jna", "net.java.dev.jna:jna:5.14.0") - library("kotest-assertions-core", "io.kotest:kotest-assertions-core:5.9.0") - library("kotest-runner-junit5", "io.kotest:kotest-runner-junit5:5.9.0") + library("kotest-assertions-core", "io.kotest:kotest-assertions-core:5.9.1") + library("kotest-runner-junit5", "io.kotest:kotest-runner-junit5:5.9.1") bundle("kotest", listOf("kotest-assertions-core", "kotest-runner-junit5")) bundle("netty", listOf("netty-transport", "netty-codec")) bundle("jackson", listOf("jackson-core", "jackson-jsr310", "jackson-kt")) From 39e819e7783826b163a7a4c79cd026f1820875a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:10:39 +0000 Subject: [PATCH 003/104] [api]: Bump the netty group with 2 updates Bumps the netty group with 2 updates: [io.netty:netty-transport](https://github.com/netty/netty) and [io.netty:netty-codec](https://github.com/netty/netty). Updates `io.netty:netty-transport` from 4.1.110.Final to 4.1.111.Final - [Commits](https://github.com/netty/netty/compare/netty-4.1.110.Final...netty-4.1.111.Final) Updates `io.netty:netty-codec` from 4.1.110.Final to 4.1.111.Final - [Commits](https://github.com/netty/netty/compare/netty-4.1.110.Final...netty-4.1.111.Final) --- updated-dependencies: - dependency-name: io.netty:netty-transport dependency-type: direct:production update-type: version-update:semver-patch dependency-group: netty - dependency-name: io.netty:netty-codec dependency-type: direct:production update-type: version-update:semver-patch dependency-group: netty ... Signed-off-by: dependabot[bot] --- settings.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 80a6c7fcc..49317033c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,8 +23,8 @@ dependencyResolutionManagement { library("rx", "io.reactivex.rxjava3:rxjava:3.1.8") library("logback", "ch.qos.logback:logback-classic:1.5.6") library("eventbus", "org.greenrobot:eventbus-java:3.3.1") - library("netty-transport", "io.netty:netty-transport:4.1.110.Final") - library("netty-codec", "io.netty:netty-codec:4.1.110.Final") + library("netty-transport", "io.netty:netty-transport:4.1.111.Final") + library("netty-codec", "io.netty:netty-codec:4.1.111.Final") library("xml", "com.fasterxml:aalto-xml:1.3.2") library("csv", "de.siegmar:fastcsv:3.2.0") library("apache-lang3", "org.apache.commons:commons-lang3:3.14.0") From 12bfaa2bb8a827369184b75c8a3ce9b53612b686 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:11:03 +0000 Subject: [PATCH 004/104] [api]: Bump org.springframework:spring-context-indexer Bumps [org.springframework:spring-context-indexer](https://github.com/spring-projects/spring-framework) from 6.1.8 to 6.1.10. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.8...v6.1.10) --- updated-dependencies: - dependency-name: org.springframework:spring-context-indexer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- api/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 05557ac63..dd6fbe067 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -48,7 +48,7 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-undertow") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") - kapt("org.springframework:spring-context-indexer:6.1.8") + kapt("org.springframework:spring-context-indexer:6.1.10") testImplementation(project(":nebulosa-astrobin-api")) testImplementation(project(":nebulosa-skycatalog-stellarium")) testImplementation(project(":nebulosa-test")) From f4d82d45c3ba4cf1ce1e8dcbb0fad04b056796e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:11:06 +0000 Subject: [PATCH 005/104] [api]: Bump org.springframework.boot from 3.3.0 to 3.3.1 Bumps org.springframework.boot from 3.3.0 to 3.3.1. --- updated-dependencies: - dependency-name: org.springframework.boot dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- api/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/build.gradle.kts b/api/build.gradle.kts index dd6fbe067..d5547183f 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -2,7 +2,7 @@ import org.springframework.boot.gradle.tasks.bundling.BootJar plugins { kotlin("jvm") - id("org.springframework.boot") version "3.3.0" + id("org.springframework.boot") version "3.3.1" id("io.spring.dependency-management") version "1.1.5" kotlin("plugin.spring") kotlin("kapt") From f314398a59324740a6d924755d4d0bf0dafeb03f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:17:42 +0000 Subject: [PATCH 006/104] [desktop]: Bump the angular group in /desktop with 13 updates Bumps the angular group in /desktop with 13 updates: | Package | From | To | | --- | --- | --- | | [@angular/animations](https://github.com/angular/angular/tree/HEAD/packages/animations) | `18.0.3` | `18.0.5` | | [@angular/cdk](https://github.com/angular/components) | `18.0.3` | `18.0.5` | | [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `18.0.3` | `18.0.5` | | [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `18.0.3` | `18.0.5` | | [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `18.0.3` | `18.0.5` | | [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `18.0.3` | `18.0.5` | | [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `18.0.3` | `18.0.5` | | [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `18.0.3` | `18.0.5` | | [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `18.0.3` | `18.0.5` | | [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `18.0.4` | `18.0.6` | | [@angular/cli](https://github.com/angular/angular-cli) | `18.0.4` | `18.0.6` | | [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `18.0.3` | `18.0.5` | | [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) | `18.0.3` | `18.0.5` | Updates `@angular/animations` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.0.5/packages/animations) Updates `@angular/cdk` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/components/releases) - [Changelog](https://github.com/angular/components/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/components/compare/18.0.3...18.0.5) Updates `@angular/common` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.0.5/packages/common) Updates `@angular/compiler` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.0.5/packages/compiler) Updates `@angular/core` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.0.5/packages/core) Updates `@angular/forms` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.0.5/packages/forms) Updates `@angular/platform-browser` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.0.5/packages/platform-browser) Updates `@angular/platform-browser-dynamic` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.0.5/packages/platform-browser-dynamic) Updates `@angular/router` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.0.5/packages/router) Updates `@angular-devkit/build-angular` from 18.0.4 to 18.0.6 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/18.0.4...18.0.6) Updates `@angular/cli` from 18.0.4 to 18.0.6 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/18.0.4...18.0.6) Updates `@angular/compiler-cli` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.0.5/packages/compiler-cli) Updates `@angular/language-service` from 18.0.3 to 18.0.5 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.0.5/packages/language-service) --- updated-dependencies: - dependency-name: "@angular/animations" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/cdk" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/common" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/compiler" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/core" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/forms" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/platform-browser" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/platform-browser-dynamic" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/router" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular-devkit/build-angular" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/cli" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/compiler-cli" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/language-service" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 580 ++++++++++++-------------------------- desktop/package.json | 26 +- 2 files changed, 200 insertions(+), 406 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 04718c8e8..067412acd 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -10,15 +10,15 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@angular/animations": "18.0.3", - "@angular/cdk": "18.0.3", - "@angular/common": "18.0.3", - "@angular/compiler": "18.0.3", - "@angular/core": "18.0.3", - "@angular/forms": "18.0.3", - "@angular/platform-browser": "18.0.3", - "@angular/platform-browser-dynamic": "18.0.3", - "@angular/router": "18.0.3", + "@angular/animations": "18.0.5", + "@angular/cdk": "18.0.5", + "@angular/common": "18.0.5", + "@angular/compiler": "18.0.5", + "@angular/core": "18.0.5", + "@angular/forms": "18.0.5", + "@angular/platform-browser": "18.0.5", + "@angular/platform-browser-dynamic": "18.0.5", + "@angular/router": "18.0.5", "@mdi/font": "7.4.47", "chart.js": "4.4.3", "chartjs-plugin-zoom": "2.0.1", @@ -38,10 +38,10 @@ }, "devDependencies": { "@angular-builders/custom-webpack": "18.0.0", - "@angular-devkit/build-angular": "18.0.4", - "@angular/cli": "18.0.4", - "@angular/compiler-cli": "18.0.3", - "@angular/language-service": "18.0.3", + "@angular-devkit/build-angular": "18.0.6", + "@angular/cli": "18.0.6", + "@angular/compiler-cli": "18.0.5", + "@angular/language-service": "18.0.5", "@eslint/js": "9.5.0", "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", @@ -110,12 +110,12 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1800.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1800.4.tgz", - "integrity": "sha512-82TKhYnSO8aGIBo5TxPtyUQnZFcbV+qB2bIIYOAKsJgxAVxLeFD6QA6gTmHOZPXw5pBEPUO/+PUwq+Uk5xesgw==", + "version": "0.1800.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1800.6.tgz", + "integrity": "sha512-VJ08XM9XR8d3ldXEMIeaiamBSvQqX+ucIKw73zubP37yFVAuvXriDOFskcouVUT0RxWXIZVcNxrgp2t3FE4F6w==", "dev": true, "dependencies": { - "@angular-devkit/core": "18.0.4", + "@angular-devkit/core": "18.0.6", "rxjs": "7.8.1" }, "engines": { @@ -125,16 +125,16 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.0.4.tgz", - "integrity": "sha512-lFu1NDEUPIUxY+CmZJ3JspqVZDesrvdae5RbqQXCl87RfSy+ZDIa7rOtQxyBQtt2BuQIB9pWQSzCMii5kTHd6w==", + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.0.6.tgz", + "integrity": "sha512-87ynzPHHYr+iL3GsBgJWVlChMuubQgiXYWf2JLXRLNGduSOdoa18vxT1jU11b6C9G+avDSnMbtq+sk841pT1kg==", "dev": true, "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1800.4", - "@angular-devkit/build-webpack": "0.1800.4", - "@angular-devkit/core": "18.0.4", - "@angular/build": "18.0.4", + "@angular-devkit/architect": "0.1800.6", + "@angular-devkit/build-webpack": "0.1800.6", + "@angular-devkit/core": "18.0.6", + "@angular/build": "18.0.6", "@babel/core": "7.24.5", "@babel/generator": "7.24.5", "@babel/helper-annotate-as-pure": "7.22.5", @@ -145,12 +145,11 @@ "@babel/preset-env": "7.24.5", "@babel/runtime": "7.24.5", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "18.0.4", + "@ngtools/webpack": "18.0.6", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.19", "babel-loader": "9.1.3", - "babel-plugin-istanbul": "6.1.1", "browserslist": "^4.21.5", "copy-webpack-plugin": "11.0.0", "critters": "0.0.22", @@ -160,6 +159,7 @@ "http-proxy-middleware": "3.0.0", "https-proxy-agent": "7.0.4", "inquirer": "9.2.22", + "istanbul-lib-instrument": "6.0.2", "jsonc-parser": "3.2.1", "karma-source-map-support": "1.4.0", "less": "4.2.0", @@ -254,6 +254,74 @@ } } }, + "node_modules/@angular-devkit/build-angular/node_modules/@angular/build": { + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.0.6.tgz", + "integrity": "sha512-W6S1sx00D4pd7qDIyzPMNFmw8d783+/Aknl+2cUrYlJqw0Oan1Bt6mXVg48Jwxr0hVsovoNZXSRFXXI5hvW8ZA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "2.3.0", + "@angular-devkit/architect": "0.1800.6", + "@babel/core": "7.24.5", + "@babel/helper-annotate-as-pure": "7.22.5", + "@babel/helper-split-export-declaration": "7.24.5", + "@vitejs/plugin-basic-ssl": "1.1.0", + "ansi-colors": "4.1.3", + "browserslist": "^4.23.0", + "critters": "0.0.22", + "esbuild": "0.21.3", + "fast-glob": "3.3.2", + "https-proxy-agent": "7.0.4", + "inquirer": "9.2.22", + "lmdb": "3.0.8", + "magic-string": "0.30.10", + "mrmime": "2.0.0", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "picomatch": "4.0.2", + "piscina": "4.5.0", + "sass": "1.77.2", + "semver": "7.6.2", + "undici": "6.18.0", + "vite": "5.2.11", + "watchpack": "2.4.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^18.0.0", + "@angular/localize": "^18.0.0", + "@angular/platform-server": "^18.0.0", + "@angular/service-worker": "^18.0.0", + "less": "^4.2.0", + "postcss": "^8.4.0", + "tailwindcss": "^2.0.0 || ^3.0.0", + "typescript": ">=5.4 <5.5" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/platform-server": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "less": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tailwindcss": { + "optional": true + } + } + }, "node_modules/@angular-devkit/build-angular/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -363,12 +431,12 @@ } }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1800.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1800.4.tgz", - "integrity": "sha512-EtWyWH3Hb7Rh8u0Jb4cWJKRxlqiUo4qhHKjU+62E8XplWlajbuld3ltL50a3t8lkZQYYgl7nPt53E5kM/zFVrw==", + "version": "0.1800.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1800.6.tgz", + "integrity": "sha512-hIQ4FtcxsNVEHlKZVFIfFiFKNNxEdacS/Nsy/YJ0AU6EOkUd6AOVsc539GniJQOk4RBNKS9wOlJBtF/2g1sjhQ==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1800.4", + "@angular-devkit/architect": "0.1800.6", "rxjs": "7.8.1" }, "engines": { @@ -382,9 +450,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.0.4.tgz", - "integrity": "sha512-8vYvJ5FF2NjFUia00hv8KWakOjOZ+09PbnNqd+lntJBekIg1lHDOF/vNMlVHtU5LiE1aNi9P/69/VXTckPfU9g==", + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.0.6.tgz", + "integrity": "sha512-07U0S2fpUBjkg4k6uAEQQHSFfearyHGrONlgkxAlk7HWM5jfHp/8D2+ui1OFZgXpSAHF2C5gULbze/2o9ZNgag==", "dev": true, "dependencies": { "ajv": "8.13.0", @@ -409,12 +477,12 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.0.4.tgz", - "integrity": "sha512-hCHmuu/Z1teOQPx1AMJa/gcK6depk+XgU5dIpEvflC+ApW3hglNe2QKaqajDZ+34s+PKAVWa86M8IOV7o/mHuA==", + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.0.6.tgz", + "integrity": "sha512-lzjPp8qWV4p3reyKZ2QRF7rQYc17WMCR61vKldQJBuJrS30yx87x22ASn4BCAo7kKKRv8gXJmoXjCPDFlcfRsw==", "dev": true, "dependencies": { - "@angular-devkit/core": "18.0.4", + "@angular-devkit/core": "18.0.6", "jsonc-parser": "3.2.1", "magic-string": "0.30.10", "ora": "5.4.1", @@ -427,9 +495,9 @@ } }, "node_modules/@angular/animations": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.0.3.tgz", - "integrity": "sha512-Wlll6y7euIXYsOHpTh0hvVTBs7lVnbKDHiyd4Dz7kAMSeE2zyQo6OcRN+FFH3GH9BUi5UooAICNX8dJDfps6Mw==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.0.5.tgz", + "integrity": "sha512-RYwlS+4I33beAWdzFFmaDPqXZN+r66qPzzMOk9LQguwF76eBJbykHniODalSLvjrY6Iz7CULavByYNpzq2TT7A==", "dependencies": { "tslib": "^2.3.0" }, @@ -437,81 +505,13 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.0.3" - } - }, - "node_modules/@angular/build": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.0.4.tgz", - "integrity": "sha512-70HQQnbCOXFT5F3ROyWNNfS9A63Fzts5ANJKJY1MJLrn+dgNEG7jdIWjTtvohL3RZz97rlzSq3qRZnfxqf1lsQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1800.4", - "@babel/core": "7.24.5", - "@babel/helper-annotate-as-pure": "7.22.5", - "@babel/helper-split-export-declaration": "7.24.5", - "@vitejs/plugin-basic-ssl": "1.1.0", - "ansi-colors": "4.1.3", - "browserslist": "^4.23.0", - "critters": "0.0.22", - "esbuild": "0.21.3", - "fast-glob": "3.3.2", - "https-proxy-agent": "7.0.4", - "inquirer": "9.2.22", - "lmdb": "3.0.8", - "magic-string": "0.30.10", - "mrmime": "2.0.0", - "ora": "5.4.1", - "parse5-html-rewriting-stream": "7.0.0", - "picomatch": "4.0.2", - "piscina": "4.5.0", - "sass": "1.77.2", - "semver": "7.6.2", - "undici": "6.18.0", - "vite": "5.2.11", - "watchpack": "2.4.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "@angular/compiler-cli": "^18.0.0", - "@angular/localize": "^18.0.0", - "@angular/platform-server": "^18.0.0", - "@angular/service-worker": "^18.0.0", - "less": "^4.2.0", - "postcss": "^8.4.0", - "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.4 <5.5" - }, - "peerDependenciesMeta": { - "@angular/localize": { - "optional": true - }, - "@angular/platform-server": { - "optional": true - }, - "@angular/service-worker": { - "optional": true - }, - "less": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tailwindcss": { - "optional": true - } + "@angular/core": "18.0.5" } }, "node_modules/@angular/cdk": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.0.3.tgz", - "integrity": "sha512-F6kXAoIWUbvhvbSGnMxrKJZsI7rhGKDXVFFf9m+ZQAbqboSyDbbszux7Em4CEh27LaXYNFltUcKdCQ3hdp7Kig==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.0.5.tgz", + "integrity": "sha512-Yf94Udxip8xjVIJlxwh80h6fUpX5JFcBv3FCFer7DU/YzWdoTL+BTIYF8og+NjlDRt1nSbTxdyU2LVI0rTVkpg==", "dependencies": { "tslib": "^2.3.0" }, @@ -525,15 +525,15 @@ } }, "node_modules/@angular/cli": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.0.4.tgz", - "integrity": "sha512-i7DLVIc4HN0CFZZKbEeVeQSADRG1Dt2CwXh/wTUzglRLu/tE7Q+WMrqJ2+lGTT2edZp2KKysM4Gxp+ATAzP8AQ==", + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.0.6.tgz", + "integrity": "sha512-T0ii60zVqBzxtC4jusKkR5YOdubP5+n9SPd8gm9Dat4jUeePc5O5+6qmjpFXZlibxLNSVIm89hLBb7/rMJIkIg==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1800.4", - "@angular-devkit/core": "18.0.4", - "@angular-devkit/schematics": "18.0.4", - "@schematics/angular": "18.0.4", + "@angular-devkit/architect": "0.1800.6", + "@angular-devkit/core": "18.0.6", + "@angular-devkit/schematics": "18.0.6", + "@schematics/angular": "18.0.6", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.2", @@ -558,9 +558,9 @@ } }, "node_modules/@angular/common": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.0.3.tgz", - "integrity": "sha512-lmT9QbWHduqzpsB0osQFHeSwvQB1iUeNwTVUyMtcs6i46l4qOPtAt2/9DvHUWEUp01EBDxyi385ZI3vD+FHH/w==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.0.5.tgz", + "integrity": "sha512-yItVQSu+Rx8gthWJDTOHwbzItY8/lqmmmYA1RMex0u3GkJoX3/3TZSGXbbBXl8GH8vmQOfp9yj3C02JmlwldRg==", "dependencies": { "tslib": "^2.3.0" }, @@ -568,14 +568,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.0.3", + "@angular/core": "18.0.5", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.0.3.tgz", - "integrity": "sha512-wrXxgBsZX4yTrj/oZ8PDGmvhqj9S2TZfcuivaUitprNC2uBWTVb1UcOS45Qw9YlLB0sYa2AmBudICDqYpb8lfw==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.0.5.tgz", + "integrity": "sha512-U1/qjNDjxMukXwQrJZjmr87KVxQmHbD7fxVlg0+qafHLe+YDuCtyOfQSGEZrWhwktxvAYZbl3FK+m3Hnk/D3Nw==", "dependencies": { "tslib": "^2.3.0" }, @@ -583,7 +583,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.0.3" + "@angular/core": "18.0.5" }, "peerDependenciesMeta": { "@angular/core": { @@ -592,9 +592,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.0.3.tgz", - "integrity": "sha512-mxwQEeP94YBM6C9A2YfkV7ug1sHgh0fU/TSBpQcm5ni4cZiVPu6q/+Ft7hyFTKe2p3tKQme33+xVjsWhtOCx0A==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.0.5.tgz", + "integrity": "sha512-aFKDDTsRmc691EkNRj9OkrKNXDOaHdXB42MyUrj3WwJIJFMnSY/UDf6h+CRVF0U+CITszFyWhmeHQRA/3mJWNg==", "dev": true, "dependencies": { "@babel/core": "7.24.7", @@ -615,7 +615,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.0.3", + "@angular/compiler": "18.0.5", "typescript": ">=5.4 <5.5" } }, @@ -680,9 +680,9 @@ } }, "node_modules/@angular/core": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.0.3.tgz", - "integrity": "sha512-376hijhEqNpeA+qKncpVTIaZXRdBT6RctEBnFhJ2l57aHPH5S3oaSBQu1k3TEi07FlKOD4XF1+NzX9dvdup1eg==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.0.5.tgz", + "integrity": "sha512-0UuL+aMMWGYksz09YBsiHq1li7GmL8obB3IC3T5MwDqnn7FGRUBfBUOZEkM6B+pwgg+RAtNdJkbCfbh1z74bFQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -695,9 +695,9 @@ } }, "node_modules/@angular/forms": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.0.3.tgz", - "integrity": "sha512-+CjDiooUi5FkTP3YQmdO8YRbjZicgLGZonvCdz3mSucLrTY6w3oBocNs6+Kc7fLuO1NKSkFmAfYApBwK3fKBMg==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.0.5.tgz", + "integrity": "sha512-nO7bN+nO2/czgKSvPx6ewqpfb8xXOyns06uovWpAXSH4jYoiZ6CHTHhOKrOL/3SRkhUV9u+EUXTTAOSBkS+OBA==", "dependencies": { "tslib": "^2.3.0" }, @@ -705,25 +705,25 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.0.3", - "@angular/core": "18.0.3", - "@angular/platform-browser": "18.0.3", + "@angular/common": "18.0.5", + "@angular/core": "18.0.5", + "@angular/platform-browser": "18.0.5", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.0.3.tgz", - "integrity": "sha512-urENnMjhSO4Jia7CnbchqN236dOIU6TC3CazwsQoj1Odch9x+iSFkx9Y0jXsiR5r/suK4uqKpK5N8MJ1PxDG1g==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.0.5.tgz", + "integrity": "sha512-ahZnsUk8q/4k+okP9hBcfWRiOiMximSAI7Vq5M/fe9cezykt8cWEzxgRoduTvDKoQPqcRl0nHlDYju2zkXcU6g==", "dev": true, "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0" } }, "node_modules/@angular/platform-browser": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.0.3.tgz", - "integrity": "sha512-1fl/oJOca8BLxLxN0EjwxQZ3xzn3PCCN96ytM54bjdEMiELz+0AcQe5GNKcVjXlwMkibRLl1BP5GIdvnQYqJRA==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.0.5.tgz", + "integrity": "sha512-hBKaGz7dhsjNhD0aWB8G2/YZQ/MaBhzFIQSAZMPs2ccAqH1Jx772/Y11k57seA3VaPpnL8WZ1apOSJgALUJ//w==", "dependencies": { "tslib": "^2.3.0" }, @@ -731,9 +731,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "18.0.3", - "@angular/common": "18.0.3", - "@angular/core": "18.0.3" + "@angular/animations": "18.0.5", + "@angular/common": "18.0.5", + "@angular/core": "18.0.5" }, "peerDependenciesMeta": { "@angular/animations": { @@ -742,9 +742,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.0.3.tgz", - "integrity": "sha512-+kHMn7P552YKk1gkVQNO1QXzHVaIeFiVa1rV1MNvX4DvumKT3puknx1SzcmtxZTX+9ee22OuPuyLNSAKREDAQQ==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.0.5.tgz", + "integrity": "sha512-i8CXojKcjsKzD2JR2clIisqavlHCW1jw+F2hJVrf/JR9iu6kVpGpZOqb3yYHoQCsPa7hUzQnn0ewYwBvlWsDmw==", "dependencies": { "tslib": "^2.3.0" }, @@ -752,16 +752,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.0.3", - "@angular/compiler": "18.0.3", - "@angular/core": "18.0.3", - "@angular/platform-browser": "18.0.3" + "@angular/common": "18.0.5", + "@angular/compiler": "18.0.5", + "@angular/core": "18.0.5", + "@angular/platform-browser": "18.0.5" } }, "node_modules/@angular/router": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.0.3.tgz", - "integrity": "sha512-/cglLev0USxUNMc4M+EBFGrqw1EpKq87LUJL3+0Ztr012sVSeOU38ad41fs6pPcMBePBDZIw7KmSXypvUJJFMA==", + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.0.5.tgz", + "integrity": "sha512-GmdzD5FZYPKCGP6mV3AZraAU6czfGcjjCym6mIsdJr3DyMwnQSwaaHAu8qlQbPDVfsP+gKVSPh1JxI1lzzarLA==", "dependencies": { "tslib": "^2.3.0" }, @@ -769,9 +769,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.0.3", - "@angular/core": "18.0.3", - "@angular/platform-browser": "18.0.3", + "@angular/common": "18.0.5", + "@angular/core": "18.0.5", + "@angular/platform-browser": "18.0.5", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -3694,22 +3694,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -4089,9 +4073,9 @@ ] }, "node_modules/@ngtools/webpack": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.0.4.tgz", - "integrity": "sha512-eWQkAuHEnLme01Ey4Z0FoG6upJHYhnJfsCTBnyEB2LTfdyBUk+PC0gwPXInK8oltWjFfiMnCwxrUQvQsvPW7Hg==", + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.0.6.tgz", + "integrity": "sha512-chSRbPpnqTThURQqUvWAgEGkLcn5TQnUQPD1HBf4WcoO/OkaK4Q1Sa8FrEllkC6/Dlyj7myi8rskQz+V8K7GSg==", "dev": true, "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0", @@ -4660,13 +4644,13 @@ ] }, "node_modules/@schematics/angular": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.0.4.tgz", - "integrity": "sha512-fN4whuym9ZmcQFdTfwLZr4j+NcZ4LzbdLk8XYrYdxt1z8c9ujs5LqJYn0LYc3UWiYl7z2RVc9NOxzNrkiXdwlw==", + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.0.6.tgz", + "integrity": "sha512-SZ73nNhCengIOy3GCUbLL++GdpaQ5T9bh05OAdQJuUNtwz1ot8QoQjkcbumKIfTicwMiLxy+OR4sZN1VcUVYpQ==", "dev": true, "dependencies": { - "@angular-devkit/core": "18.0.4", - "@angular-devkit/schematics": "18.0.4", + "@angular-devkit/core": "18.0.6", + "@angular-devkit/schematics": "18.0.6", "jsonc-parser": "3.2.1" }, "engines": { @@ -6068,15 +6052,6 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", @@ -6290,22 +6265,6 @@ "webpack": ">=5" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", @@ -7105,15 +7064,6 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001636", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", @@ -9672,19 +9622,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -10103,19 +10040,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -10389,15 +10313,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -11788,28 +11703,19 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "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": "^6.3.0" + "semver": "^7.5.4" }, "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node": ">=10" } }, "node_modules/jackspeak": { @@ -12006,19 +11912,6 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", @@ -12411,18 +12304,6 @@ "node": ">= 12.13.0" } }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -14080,33 +13961,6 @@ "node": ">=8" } }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", @@ -14148,15 +14002,6 @@ "node": ">= 4" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/package-json-from-dist": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", @@ -15312,15 +15157,6 @@ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", "dev": true }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-url-loader": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", @@ -15446,9 +15282,9 @@ } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -16372,12 +16208,6 @@ "wbuf": "^1.7.3" } }, - "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/ssri": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", @@ -16869,42 +16699,6 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -17002,9 +16796,9 @@ } }, "node_modules/tree-dump": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.1.tgz", - "integrity": "sha512-WCkcRBVPSlHHq1dc/px9iOfqklvzCbdRwvlNfxGZsrHqf6aZttfPrd7DJTt6oR10dwUfpFFQeVTkPbBIZxX/YA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", "dev": true, "engines": { "node": ">=10.0" @@ -18673,9 +18467,9 @@ } }, "node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "dev": true, "engines": { "node": ">=12.20" diff --git a/desktop/package.json b/desktop/package.json index fbf6ba2ec..0daf73f2c 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -34,15 +34,15 @@ "prettier:json": "npx prettier '**/*.json' --write" }, "dependencies": { - "@angular/animations": "18.0.3", - "@angular/cdk": "18.0.3", - "@angular/common": "18.0.3", - "@angular/compiler": "18.0.3", - "@angular/core": "18.0.3", - "@angular/forms": "18.0.3", - "@angular/platform-browser": "18.0.3", - "@angular/platform-browser-dynamic": "18.0.3", - "@angular/router": "18.0.3", + "@angular/animations": "18.0.5", + "@angular/cdk": "18.0.5", + "@angular/common": "18.0.5", + "@angular/compiler": "18.0.5", + "@angular/core": "18.0.5", + "@angular/forms": "18.0.5", + "@angular/platform-browser": "18.0.5", + "@angular/platform-browser-dynamic": "18.0.5", + "@angular/router": "18.0.5", "@mdi/font": "7.4.47", "chart.js": "4.4.3", "chartjs-plugin-zoom": "2.0.1", @@ -62,10 +62,10 @@ }, "devDependencies": { "@angular-builders/custom-webpack": "18.0.0", - "@angular-devkit/build-angular": "18.0.4", - "@angular/cli": "18.0.4", - "@angular/compiler-cli": "18.0.3", - "@angular/language-service": "18.0.3", + "@angular-devkit/build-angular": "18.0.6", + "@angular/cli": "18.0.6", + "@angular/compiler-cli": "18.0.5", + "@angular/language-service": "18.0.5", "@eslint/js": "9.5.0", "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", From 4acdf0580ad58abca372f6927c7297c8aafc3c96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:18:29 +0000 Subject: [PATCH 007/104] [desktop]: Bump primeng from 17.18.1 to 17.18.2 in /desktop Bumps [primeng](https://github.com/primefaces/primeng) from 17.18.1 to 17.18.2. - [Release notes](https://github.com/primefaces/primeng/releases) - [Changelog](https://github.com/primefaces/primeng/blob/master/CHANGELOG.md) - [Commits](https://github.com/primefaces/primeng/compare/17.18.1...17.18.2) --- updated-dependencies: - dependency-name: primeng dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 8 ++++---- desktop/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 067412acd..0d4b6dc64 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -30,7 +30,7 @@ "panzoom": "9.4.3", "primeflex": "3.3.1", "primeicons": "7.0.0", - "primeng": "17.18.1", + "primeng": "17.18.2", "primeng-sass-theme": "github:primefaces/primeng-sass-theme#17.18.0", "rxjs": "7.8.1", "tslib": "2.6.3", @@ -14600,9 +14600,9 @@ "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==" }, "node_modules/primeng": { - "version": "17.18.1", - "resolved": "https://registry.npmjs.org/primeng/-/primeng-17.18.1.tgz", - "integrity": "sha512-pMuXOgLQw5Xz0w9d3YTp2DAlYR8svK1Jz5gSWAhk6AyH7u7akwL1JX96RXVzLS8v2YeLUCvkMM+QROOvR3yKug==", + "version": "17.18.2", + "resolved": "https://registry.npmjs.org/primeng/-/primeng-17.18.2.tgz", + "integrity": "sha512-2uux//0AOj/EwiOQHmUVFst+9dtf4duNLI+Oo6vN3HLXoQF+Eax5Mfi5eHh+EDSJMFCrzeCUma0N2Nj5pNpSHg==", "dependencies": { "tslib": "^2.3.0" }, diff --git a/desktop/package.json b/desktop/package.json index 0daf73f2c..0051429a8 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -54,7 +54,7 @@ "panzoom": "9.4.3", "primeflex": "3.3.1", "primeicons": "7.0.0", - "primeng": "17.18.1", + "primeng": "17.18.2", "primeng-sass-theme": "github:primefaces/primeng-sass-theme#17.18.0", "rxjs": "7.8.1", "tslib": "2.6.3", From b7d335ae53ded6abd9a263492d2b82691a71f584 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:19:27 +0000 Subject: [PATCH 008/104] [desktop]: Bump typescript-eslint from 7.13.1 to 7.14.1 in /desktop Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 7.13.1 to 7.14.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.14.1/packages/typescript-eslint) --- updated-dependencies: - dependency-name: typescript-eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 104 +++++++++++++++++++------------------- desktop/package.json | 2 +- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 0d4b6dc64..48231efea 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -55,7 +55,7 @@ "prettier": "3.3.2", "ts-node": "10.9.2", "typescript": "5.4.5", - "typescript-eslint": "7.13.1", + "typescript-eslint": "7.14.1", "wait-on": "7.2.0" }, "engines": { @@ -5166,16 +5166,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", - "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz", + "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/type-utils": "7.13.1", - "@typescript-eslint/utils": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/type-utils": "7.14.1", + "@typescript-eslint/utils": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -5199,15 +5199,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", - "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", + "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/typescript-estree": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/typescript-estree": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "debug": "^4.3.4" }, "engines": { @@ -5227,13 +5227,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", - "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", + "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1" + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -5244,13 +5244,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", - "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz", + "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.13.1", - "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/typescript-estree": "7.14.1", + "@typescript-eslint/utils": "7.14.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -5271,9 +5271,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", - "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", + "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -5284,13 +5284,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", - "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", + "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -5332,9 +5332,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -5356,15 +5356,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", - "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", + "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/typescript-estree": "7.13.1" + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/typescript-estree": "7.14.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -5378,12 +5378,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", - "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", + "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/types": "7.14.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -17053,14 +17053,14 @@ } }, "node_modules/typescript-eslint": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.13.1.tgz", - "integrity": "sha512-pvLEuRs8iS9s3Cnp/Wt//hpK8nKc8hVa3cLljHqzaJJQYP8oys8GUyIFqtlev+2lT/fqMPcyQko+HJ6iYK3nFA==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.14.1.tgz", + "integrity": "sha512-Eo1X+Y0JgGPspcANKjeR6nIqXl4VL5ldXLc15k4m9upq+eY5fhU2IueiEZL6jmHrKH8aCfbIvM/v3IrX5Hg99w==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "7.13.1", - "@typescript-eslint/parser": "7.13.1", - "@typescript-eslint/utils": "7.13.1" + "@typescript-eslint/eslint-plugin": "7.14.1", + "@typescript-eslint/parser": "7.14.1", + "@typescript-eslint/utils": "7.14.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" diff --git a/desktop/package.json b/desktop/package.json index 0051429a8..18d037029 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -79,7 +79,7 @@ "prettier": "3.3.2", "ts-node": "10.9.2", "typescript": "5.4.5", - "typescript-eslint": "7.13.1", + "typescript-eslint": "7.14.1", "wait-on": "7.2.0" }, "overrides": { From 2205bd3ce55319f1ba85420e04b415d22371fa6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:19:12 +0000 Subject: [PATCH 009/104] [desktop]: Bump electron from 31.0.1 to 31.1.0 in /desktop Bumps [electron](https://github.com/electron/electron) from 31.0.1 to 31.1.0. - [Release notes](https://github.com/electron/electron/releases) - [Changelog](https://github.com/electron/electron/blob/main/docs/breaking-changes.md) - [Commits](https://github.com/electron/electron/compare/v31.0.1...v31.1.0) --- updated-dependencies: - dependency-name: electron dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 8 ++++---- desktop/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 48231efea..e2314144d 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -47,7 +47,7 @@ "@types/leaflet": "1.9.12", "@types/node": "20.14.6", "@types/uuid": "9.0.8", - "electron": "31.0.1", + "electron": "31.1.0", "electron-builder": "24.13.3", "eslint": "8.57.0", "node-polyfill-webpack-plugin": "4.0.0", @@ -8573,9 +8573,9 @@ } }, "node_modules/electron": { - "version": "31.0.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-31.0.1.tgz", - "integrity": "sha512-2eBcp4iqLkTsml6mMq+iqrS5u3kJ/2mpOLP7Mj7lo0uNK3OyfNqRS9z1ArsHjBF2/HV250Te/O9nKrwQRTX/+g==", + "version": "31.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-31.1.0.tgz", + "integrity": "sha512-TBOwqLxSxnx6+pH6GMri7R3JPH2AkuGJHfWZS0p1HsmN+Qr1T9b0IRJnnehSd/3NZAmAre4ft9Ljec7zjyKFJA==", "dev": true, "hasInstallScript": true, "dependencies": { diff --git a/desktop/package.json b/desktop/package.json index 18d037029..52a7f7428 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -71,7 +71,7 @@ "@types/leaflet": "1.9.12", "@types/node": "20.14.6", "@types/uuid": "9.0.8", - "electron": "31.0.1", + "electron": "31.1.0", "electron-builder": "24.13.3", "eslint": "8.57.0", "node-polyfill-webpack-plugin": "4.0.0", From 3f589e1a95888ccbbe9987ebf93fa8ba20c9f2f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:29:01 +0000 Subject: [PATCH 010/104] [desktop]: Bump @eslint/js from 9.5.0 to 9.6.0 in /desktop Bumps [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) from 9.5.0 to 9.6.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/commits/v9.6.0/packages/js) --- updated-dependencies: - dependency-name: "@eslint/js" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 8 ++++---- desktop/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index e2314144d..8e9c0bd00 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -42,7 +42,7 @@ "@angular/cli": "18.0.6", "@angular/compiler-cli": "18.0.5", "@angular/language-service": "18.0.5", - "@eslint/js": "9.5.0", + "@eslint/js": "9.6.0", "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", "@types/node": "20.14.6", @@ -3504,9 +3504,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz", - "integrity": "sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", + "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/desktop/package.json b/desktop/package.json index 52a7f7428..4cf0cd2e5 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -66,7 +66,7 @@ "@angular/cli": "18.0.6", "@angular/compiler-cli": "18.0.5", "@angular/language-service": "18.0.5", - "@eslint/js": "9.5.0", + "@eslint/js": "9.6.0", "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", "@types/node": "20.14.6", From cfcbf874bb3616dccb1cabb1ad82508a5808a244 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Mon, 1 Jul 2024 00:55:23 -0300 Subject: [PATCH 011/104] [desktop]: Remove @types/uuid --- desktop/package-lock.json | 7 ------- desktop/package.json | 1 - 2 files changed, 8 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 8e9c0bd00..d69240315 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -46,7 +46,6 @@ "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", "@types/node": "20.14.6", - "@types/uuid": "9.0.8", "electron": "31.1.0", "electron-builder": "24.13.3", "eslint": "8.57.0", @@ -5133,12 +5132,6 @@ "@types/node": "*" } }, - "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true - }, "node_modules/@types/verror": { "version": "1.10.10", "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.10.tgz", diff --git a/desktop/package.json b/desktop/package.json index 4cf0cd2e5..6bc0230fd 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -70,7 +70,6 @@ "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", "@types/node": "20.14.6", - "@types/uuid": "9.0.8", "electron": "31.1.0", "electron-builder": "24.13.3", "eslint": "8.57.0", From 9183016f6593b1632e7155ebeafa3a1202287ce4 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Mon, 1 Jul 2024 00:57:53 -0300 Subject: [PATCH 012/104] [desktop]: Upgrade NPM dependencies --- desktop/package-lock.json | 836 +++++++++++++++++--------------------- 1 file changed, 366 insertions(+), 470 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index d69240315..3290ef877 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -253,74 +253,6 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/@angular/build": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.0.6.tgz", - "integrity": "sha512-W6S1sx00D4pd7qDIyzPMNFmw8d783+/Aknl+2cUrYlJqw0Oan1Bt6mXVg48Jwxr0hVsovoNZXSRFXXI5hvW8ZA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1800.6", - "@babel/core": "7.24.5", - "@babel/helper-annotate-as-pure": "7.22.5", - "@babel/helper-split-export-declaration": "7.24.5", - "@vitejs/plugin-basic-ssl": "1.1.0", - "ansi-colors": "4.1.3", - "browserslist": "^4.23.0", - "critters": "0.0.22", - "esbuild": "0.21.3", - "fast-glob": "3.3.2", - "https-proxy-agent": "7.0.4", - "inquirer": "9.2.22", - "lmdb": "3.0.8", - "magic-string": "0.30.10", - "mrmime": "2.0.0", - "ora": "5.4.1", - "parse5-html-rewriting-stream": "7.0.0", - "picomatch": "4.0.2", - "piscina": "4.5.0", - "sass": "1.77.2", - "semver": "7.6.2", - "undici": "6.18.0", - "vite": "5.2.11", - "watchpack": "2.4.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "@angular/compiler-cli": "^18.0.0", - "@angular/localize": "^18.0.0", - "@angular/platform-server": "^18.0.0", - "@angular/service-worker": "^18.0.0", - "less": "^4.2.0", - "postcss": "^8.4.0", - "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.4 <5.5" - }, - "peerDependenciesMeta": { - "@angular/localize": { - "optional": true - }, - "@angular/platform-server": { - "optional": true - }, - "@angular/service-worker": { - "optional": true - }, - "less": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tailwindcss": { - "optional": true - } - } - }, "node_modules/@angular-devkit/build-angular/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -346,6 +278,28 @@ "ajv": "^6.9.1" } }, + "node_modules/@angular-devkit/build-angular/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/@angular-devkit/build-angular/node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -507,6 +461,74 @@ "@angular/core": "18.0.5" } }, + "node_modules/@angular/build": { + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.0.6.tgz", + "integrity": "sha512-W6S1sx00D4pd7qDIyzPMNFmw8d783+/Aknl+2cUrYlJqw0Oan1Bt6mXVg48Jwxr0hVsovoNZXSRFXXI5hvW8ZA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "2.3.0", + "@angular-devkit/architect": "0.1800.6", + "@babel/core": "7.24.5", + "@babel/helper-annotate-as-pure": "7.22.5", + "@babel/helper-split-export-declaration": "7.24.5", + "@vitejs/plugin-basic-ssl": "1.1.0", + "ansi-colors": "4.1.3", + "browserslist": "^4.23.0", + "critters": "0.0.22", + "esbuild": "0.21.3", + "fast-glob": "3.3.2", + "https-proxy-agent": "7.0.4", + "inquirer": "9.2.22", + "lmdb": "3.0.8", + "magic-string": "0.30.10", + "mrmime": "2.0.0", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "picomatch": "4.0.2", + "piscina": "4.5.0", + "sass": "1.77.2", + "semver": "7.6.2", + "undici": "6.18.0", + "vite": "5.2.11", + "watchpack": "2.4.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^18.0.0", + "@angular/localize": "^18.0.0", + "@angular/platform-server": "^18.0.0", + "@angular/service-worker": "^18.0.0", + "less": "^4.2.0", + "postcss": "^8.4.0", + "tailwindcss": "^2.0.0 || ^3.0.0", + "typescript": ">=5.4 <5.5" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/platform-server": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "less": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tailwindcss": { + "optional": true + } + } + }, "node_modules/@angular/cdk": { "version": "18.0.5", "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.0.5.tgz", @@ -3382,9 +3404,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -3429,12 +3451,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3460,18 +3476,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -4164,9 +4168,9 @@ } }, "node_modules/@npmcli/agent/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", + "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -4213,9 +4217,9 @@ } }, "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", + "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -4315,18 +4319,18 @@ } }, "node_modules/@npmcli/package-json/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", + "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", "dev": true, "engines": { "node": "14 || >=16.14" } }, "node_modules/@npmcli/package-json/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -4833,9 +4837,9 @@ } }, "node_modules/@tufjs/models/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -5905,12 +5909,6 @@ "electron-builder-squirrel-windows": "24.13.3" } }, - "node_modules/app-builder-lib/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/app-builder-lib/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -5925,18 +5923,6 @@ "node": ">=12" } }, - "node_modules/app-builder-lib/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/app-builder-lib/node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -6045,6 +6031,12 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", @@ -6781,12 +6773,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/builder-util/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/builder-util/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6857,18 +6843,6 @@ "node": ">= 6" } }, - "node_modules/builder-util/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/builder-util/node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -6979,18 +6953,18 @@ } }, "node_modules/cacache/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", + "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", "dev": true, "engines": { "node": "14 || >=16.14" } }, "node_modules/cacache/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -7058,9 +7032,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001636", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", - "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", + "version": "1.0.30001639", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001639.tgz", + "integrity": "sha512-eFHflNTBIlFwP2AIKaYuBQN/apnUoKNhBdza8ZnW/h2di4LCZ4xFqYlxUxo+LQ76KFI1PGcC1QDxMbxTZpSCAg==", "dev": true, "funding": [ { @@ -7514,9 +7488,9 @@ } }, "node_modules/config-file-ts/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -7684,24 +7658,6 @@ } } }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/crc": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", @@ -8329,12 +8285,6 @@ "dmg-license": "^1.0.11" } }, - "node_modules/dmg-builder/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/dmg-builder/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -8349,18 +8299,6 @@ "node": ">=12" } }, - "node_modules/dmg-builder/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/dmg-builder/node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -8886,9 +8824,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.806", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.806.tgz", - "integrity": "sha512-nkoEX2QIB8kwCOtvtgwhXWy2IHVcOLQZu9Qo36uaGB835mdX/h8uLRlosL6QIhLVUnAiicXRW00PwaPZC74Nrg==", + "version": "1.4.815", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.815.tgz", + "integrity": "sha512-OvpTT2ItpOXJL7IGcYakRjHCt8L5GrrN/wHCQsRB4PQa1X9fe+X9oen245mIId7s14xvArCGSTIq644yPUKKLg==", "dev": true }, "node_modules/elliptic": { @@ -9099,9 +9037,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.3.tgz", - "integrity": "sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", "dev": true }, "node_modules/es-object-atoms": { @@ -9284,16 +9222,19 @@ } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { @@ -9348,12 +9289,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -9410,47 +9345,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -9487,39 +9381,12 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -9532,36 +9399,6 @@ "node": "*" } }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -9586,18 +9423,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -9627,15 +9452,6 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -9648,7 +9464,7 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", @@ -9657,15 +9473,6 @@ "node": ">=4.0" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -10033,6 +9840,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -10056,22 +9879,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/flatted": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", @@ -10984,9 +10791,9 @@ } }, "node_modules/ignore-walk/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -11033,15 +10840,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -11159,12 +10957,6 @@ "node": ">= 12" } }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true - }, "node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", @@ -11277,12 +11069,15 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", "dev": true, "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11905,6 +11700,18 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", @@ -12297,6 +12104,21 @@ "node": ">= 12.13.0" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -13218,9 +13040,9 @@ } }, "node_modules/node-gyp/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -13368,13 +13190,12 @@ } }, "node_modules/normalize-package-data": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.1.tgz", - "integrity": "sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", "dev": true, "dependencies": { "hosted-git-info": "^7.0.0", - "is-core-module": "^2.8.1", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" }, @@ -13395,9 +13216,9 @@ } }, "node_modules/normalize-package-data/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", + "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -13494,9 +13315,9 @@ } }, "node_modules/npm-package-arg/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", + "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -13695,10 +13516,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13954,6 +13778,36 @@ "node": ">=8" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", @@ -14213,9 +14067,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", + "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -14392,6 +14246,18 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/pkg-dir/node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/plist": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", @@ -14874,24 +14740,6 @@ "node": ">=12.0.0" } }, - "node_modules/read-config-file/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/read-config-file/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -15150,6 +14998,15 @@ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", "dev": true }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/resolve-url-loader": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", @@ -15234,56 +15091,16 @@ } }, "node_modules/rimraf": { - "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" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "glob": "^7.1.3" }, "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" + "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -15317,13 +15134,6 @@ "node": ">=8.0" } }, - "node_modules/roarr/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "optional": true - }, "node_modules/rollup": { "version": "4.18.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", @@ -16057,14 +15867,14 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", - "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "dev": true, "dependencies": { "agent-base": "^7.1.1", "debug": "^4.3.4", - "socks": "^2.7.1" + "socks": "^2.8.3" }, "engines": { "node": ">= 14" @@ -16201,6 +16011,12 @@ "wbuf": "^1.7.3" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true + }, "node_modules/ssri": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", @@ -18001,6 +17817,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/webpack-dev-server/node_modules/glob": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", + "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", @@ -18040,6 +17879,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/webpack-dev-server/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/webpack-dev-server/node_modules/open": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", @@ -18058,6 +17912,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/webpack-dev-server/node_modules/rimraf": { + "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" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", @@ -18129,6 +18001,30 @@ "ajv": "^6.9.1" } }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/webpack/node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -18460,12 +18356,12 @@ } }, "node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { - "node": ">=12.20" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" From b4a4c45722a84ef68105d4f749add37f74e4b5e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:20:56 +0000 Subject: [PATCH 013/104] [desktop]: Bump @types/node Bumps the types group with 1 update in the /desktop directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `@types/node` from 20.14.6 to 20.14.9 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: types ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 8 ++++---- desktop/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 3290ef877..618898793 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -45,7 +45,7 @@ "@eslint/js": "9.6.0", "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", - "@types/node": "20.14.6", + "@types/node": "20.14.9", "electron": "31.1.0", "electron-builder": "24.13.3", "eslint": "8.57.0", @@ -5042,9 +5042,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.14.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.6.tgz", - "integrity": "sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw==", + "version": "20.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz", + "integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" diff --git a/desktop/package.json b/desktop/package.json index 6bc0230fd..bde10becc 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -69,7 +69,7 @@ "@eslint/js": "9.6.0", "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", - "@types/node": "20.14.6", + "@types/node": "20.14.9", "electron": "31.1.0", "electron-builder": "24.13.3", "eslint": "8.57.0", From e781b48e1272236b45f5097615688feb0ebadab2 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Mon, 1 Jul 2024 11:23:53 -0300 Subject: [PATCH 014/104] [api]: Bump com.fasterxml:aalto-xml in the fasterxml group Bumps the fasterxml group with 1 update: [com.fasterxml:aalto-xml](https://github.com/FasterXML/aalto-xml). Updates `com.fasterxml:aalto-xml` from 1.3.2 to 1.3.3 - [Commits](https://github.com/FasterXML/aalto-xml/compare/aalto-xml-1.3.2...aalto-xml-1.3.3) --- updated-dependencies: - dependency-name: com.fasterxml:aalto-xml dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fasterxml ... Signed-off-by: dependabot[bot] --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 49317033c..3e9c051c9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -25,7 +25,7 @@ dependencyResolutionManagement { library("eventbus", "org.greenrobot:eventbus-java:3.3.1") library("netty-transport", "io.netty:netty-transport:4.1.111.Final") library("netty-codec", "io.netty:netty-codec:4.1.111.Final") - library("xml", "com.fasterxml:aalto-xml:1.3.2") + library("xml", "com.fasterxml:aalto-xml:1.3.3") library("csv", "de.siegmar:fastcsv:3.2.0") library("apache-lang3", "org.apache.commons:commons-lang3:3.14.0") library("apache-codec", "commons-codec:commons-codec:1.17.0") From 11bc4f8a1935edd37b5a00a1f9cd566f17cf9383 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Wed, 3 Jul 2024 08:47:32 -0300 Subject: [PATCH 015/104] [desktop]: Remove empty SCSS files --- desktop/src/app/about/about.component.scss | 0 desktop/src/app/about/about.component.ts | 3 +-- desktop/src/app/alignment/alignment.component.ts | 2 +- desktop/src/app/app.component.ts | 2 +- desktop/src/app/atlas/atlas.component.ts | 2 +- desktop/src/app/autofocus/autofocus.component.scss | 0 desktop/src/app/autofocus/autofocus.component.ts | 3 +-- .../src/app/calculator/calculator.component.scss | 0 desktop/src/app/calculator/calculator.component.ts | 3 +-- .../app/calculator/formula/formula.component.ts | 2 +- .../src/app/calibration/calibration.component.ts | 2 +- desktop/src/app/camera/camera.component.scss | 0 desktop/src/app/camera/camera.component.ts | 3 +-- .../src/app/filterwheel/filterwheel.component.ts | 4 ++-- .../src/app/flat-wizard/flat-wizard.component.scss | 0 .../src/app/flat-wizard/flat-wizard.component.ts | 3 +-- desktop/src/app/focuser/focuser.component.scss | 0 desktop/src/app/focuser/focuser.component.ts | 3 +-- desktop/src/app/framing/framing.component.scss | 0 desktop/src/app/framing/framing.component.ts | 3 +-- desktop/src/app/guider/guider.component.scss | 0 desktop/src/app/guider/guider.component.ts | 9 +-------- desktop/src/app/home/home.component.ts | 2 +- desktop/src/app/image/image.component.ts | 2 +- desktop/src/app/indi/indi.component.html | 2 +- desktop/src/app/indi/indi.component.ts | 2 +- .../app/indi/property/indi-property.component.ts | 2 +- desktop/src/app/mount/mount.component.scss | 0 desktop/src/app/mount/mount.component.ts | 3 +-- desktop/src/app/rotator/rotator.component.scss | 0 desktop/src/app/rotator/rotator.component.ts | 3 +-- desktop/src/app/sequencer/sequencer.component.ts | 2 +- desktop/src/app/settings/settings.component.scss | 0 desktop/src/app/settings/settings.component.ts | 3 +-- desktop/src/index.html | 4 ++-- desktop/src/shared/services/electron.service.ts | 14 -------------- 36 files changed, 26 insertions(+), 57 deletions(-) delete mode 100644 desktop/src/app/about/about.component.scss delete mode 100644 desktop/src/app/autofocus/autofocus.component.scss delete mode 100644 desktop/src/app/calculator/calculator.component.scss delete mode 100644 desktop/src/app/camera/camera.component.scss delete mode 100644 desktop/src/app/flat-wizard/flat-wizard.component.scss delete mode 100644 desktop/src/app/focuser/focuser.component.scss delete mode 100644 desktop/src/app/framing/framing.component.scss delete mode 100644 desktop/src/app/guider/guider.component.scss delete mode 100644 desktop/src/app/mount/mount.component.scss delete mode 100644 desktop/src/app/rotator/rotator.component.scss delete mode 100644 desktop/src/app/settings/settings.component.scss diff --git a/desktop/src/app/about/about.component.scss b/desktop/src/app/about/about.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/about/about.component.ts b/desktop/src/app/about/about.component.ts index d787abeef..81d6dd66a 100644 --- a/desktop/src/app/about/about.component.ts +++ b/desktop/src/app/about/about.component.ts @@ -2,9 +2,8 @@ import { Component } from '@angular/core' import { AppComponent } from '../app.component' @Component({ - selector: 'app-about', + selector: 'neb-about', templateUrl: './about.component.html', - styleUrls: ['./about.component.scss'], }) export class AboutComponent { constructor(app: AppComponent) { diff --git a/desktop/src/app/alignment/alignment.component.ts b/desktop/src/app/alignment/alignment.component.ts index cff2687f0..9079195ba 100644 --- a/desktop/src/app/alignment/alignment.component.ts +++ b/desktop/src/app/alignment/alignment.component.ts @@ -16,7 +16,7 @@ import { AppComponent } from '../app.component' import { CameraComponent } from '../camera/camera.component' @Component({ - selector: 'app-alignment', + selector: 'neb-alignment', templateUrl: './alignment.component.html', styleUrls: ['./alignment.component.scss'], }) diff --git a/desktop/src/app/app.component.ts b/desktop/src/app/app.component.ts index e60773700..dbfbb1ebe 100644 --- a/desktop/src/app/app.component.ts +++ b/desktop/src/app/app.component.ts @@ -6,7 +6,7 @@ import { ConfirmationService } from '../shared/services/confirmation.service' import { ElectronService } from '../shared/services/electron.service' @Component({ - selector: 'app-root', + selector: 'neb-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) diff --git a/desktop/src/app/atlas/atlas.component.ts b/desktop/src/app/atlas/atlas.component.ts index d7a4eff19..697e5cc48 100644 --- a/desktop/src/app/atlas/atlas.component.ts +++ b/desktop/src/app/atlas/atlas.component.ts @@ -40,7 +40,7 @@ import { AppComponent } from '../app.component' Chart.register(zoomPlugin) @Component({ - selector: 'app-atlas', + selector: 'neb-atlas', templateUrl: './atlas.component.html', styleUrls: ['./atlas.component.scss'], }) diff --git a/desktop/src/app/autofocus/autofocus.component.scss b/desktop/src/app/autofocus/autofocus.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/autofocus/autofocus.component.ts b/desktop/src/app/autofocus/autofocus.component.ts index 07c9e52f8..aef13702d 100644 --- a/desktop/src/app/autofocus/autofocus.component.ts +++ b/desktop/src/app/autofocus/autofocus.component.ts @@ -16,9 +16,8 @@ import { AppComponent } from '../app.component' import { CameraComponent } from '../camera/camera.component' @Component({ - selector: 'app-autofocus', + selector: 'neb-autofocus', templateUrl: './autofocus.component.html', - styleUrls: ['./autofocus.component.scss'], }) export class AutoFocusComponent implements AfterViewInit, OnDestroy, Pingable { cameras: Camera[] = [] diff --git a/desktop/src/app/calculator/calculator.component.scss b/desktop/src/app/calculator/calculator.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/calculator/calculator.component.ts b/desktop/src/app/calculator/calculator.component.ts index 437c43a71..9fada2282 100644 --- a/desktop/src/app/calculator/calculator.component.ts +++ b/desktop/src/app/calculator/calculator.component.ts @@ -4,9 +4,8 @@ import { AppComponent } from '../app.component' import { FormulaComponent } from './formula/formula.component' @Component({ - selector: 'app-calculator', + selector: 'neb-calculator', templateUrl: './calculator.component.html', - styleUrls: ['./calculator.component.scss'], }) export class CalculatorComponent { readonly formulae: { component: Type; formula: CalculatorFormula }[] = [ diff --git a/desktop/src/app/calculator/formula/formula.component.ts b/desktop/src/app/calculator/formula/formula.component.ts index e7b870b9e..b32ebe4db 100644 --- a/desktop/src/app/calculator/formula/formula.component.ts +++ b/desktop/src/app/calculator/formula/formula.component.ts @@ -2,7 +2,7 @@ import { AfterViewInit, Component, Input } from '@angular/core' import { CalculatorFormula } from '../../../shared/types/calculator.types' @Component({ - selector: 'app-formula', + selector: 'neb-formula', templateUrl: './formula.component.html', styleUrls: ['./formula.component.scss'], }) diff --git a/desktop/src/app/calibration/calibration.component.ts b/desktop/src/app/calibration/calibration.component.ts index 89a8eae79..70abd6d25 100644 --- a/desktop/src/app/calibration/calibration.component.ts +++ b/desktop/src/app/calibration/calibration.component.ts @@ -20,7 +20,7 @@ export interface CalibrationNode extends TreeNode { export type TreeNodeData = { type: 'NAME'; data: string } | { type: 'GROUP'; data: CalibrationFrameGroup } | { type: 'FRAME'; data: CalibrationFrame } @Component({ - selector: 'app-calibration', + selector: 'neb-calibration', templateUrl: './calibration.component.html', styleUrls: ['./calibration.component.scss'], providers: [TreeDragDropService], diff --git a/desktop/src/app/camera/camera.component.scss b/desktop/src/app/camera/camera.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/camera/camera.component.ts b/desktop/src/app/camera/camera.component.ts index 917255f8e..1d840b94e 100644 --- a/desktop/src/app/camera/camera.component.ts +++ b/desktop/src/app/camera/camera.component.ts @@ -19,9 +19,8 @@ import { Undefinable } from '../../shared/utils/types' import { AppComponent } from '../app.component' @Component({ - selector: 'app-camera', + selector: 'neb-camera', templateUrl: './camera.component.html', - styleUrls: ['./camera.component.scss'], }) export class CameraComponent implements AfterContentInit, OnDestroy, Pingable { readonly camera = structuredClone(EMPTY_CAMERA) diff --git a/desktop/src/app/filterwheel/filterwheel.component.ts b/desktop/src/app/filterwheel/filterwheel.component.ts index 4fd655939..eae0d4977 100644 --- a/desktop/src/app/filterwheel/filterwheel.component.ts +++ b/desktop/src/app/filterwheel/filterwheel.component.ts @@ -15,7 +15,7 @@ import { Undefinable } from '../../shared/utils/types' import { AppComponent } from '../app.component' @Component({ - selector: 'app-filterwheel', + selector: 'neb-filterwheel', templateUrl: './filterwheel.component.html', styleUrls: ['./filterwheel.component.scss'], }) @@ -115,7 +115,7 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Pingab this.subscription = this.filterChangedPublisher.pipe(debounceTime(1500)).subscribe(async (filter) => { this.savePreference() - const names = this.filters.map(e => e.name) + const names = this.filters.map((e) => e.name) await this.api.wheelSync(this.wheel, names) await this.electron.send('WHEEL.RENAMED', { wheel: this.wheel, filter }) }) diff --git a/desktop/src/app/flat-wizard/flat-wizard.component.scss b/desktop/src/app/flat-wizard/flat-wizard.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/flat-wizard/flat-wizard.component.ts b/desktop/src/app/flat-wizard/flat-wizard.component.ts index 52ab9c3bd..2456d3242 100644 --- a/desktop/src/app/flat-wizard/flat-wizard.component.ts +++ b/desktop/src/app/flat-wizard/flat-wizard.component.ts @@ -14,9 +14,8 @@ import { AppComponent } from '../app.component' import { CameraComponent } from '../camera/camera.component' @Component({ - selector: 'app-flat-wizard', + selector: 'neb-flat-wizard', templateUrl: './flat-wizard.component.html', - styleUrls: ['./flat-wizard.component.scss'], }) export class FlatWizardComponent implements AfterViewInit, OnDestroy, Pingable { cameras: Camera[] = [] diff --git a/desktop/src/app/focuser/focuser.component.scss b/desktop/src/app/focuser/focuser.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/focuser/focuser.component.ts b/desktop/src/app/focuser/focuser.component.ts index 3e5d6772b..a761d56df 100644 --- a/desktop/src/app/focuser/focuser.component.ts +++ b/desktop/src/app/focuser/focuser.component.ts @@ -9,9 +9,8 @@ import { EMPTY_FOCUSER, Focuser } from '../../shared/types/focuser.types' import { AppComponent } from '../app.component' @Component({ - selector: 'app-focuser', + selector: 'neb-focuser', templateUrl: './focuser.component.html', - styleUrls: ['./focuser.component.scss'], }) export class FocuserComponent implements AfterViewInit, OnDestroy, Pingable { readonly focuser = structuredClone(EMPTY_FOCUSER) diff --git a/desktop/src/app/framing/framing.component.scss b/desktop/src/app/framing/framing.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/framing/framing.component.ts b/desktop/src/app/framing/framing.component.ts index 016dcb5db..342845e6e 100644 --- a/desktop/src/app/framing/framing.component.ts +++ b/desktop/src/app/framing/framing.component.ts @@ -31,9 +31,8 @@ export interface FramingData { } @Component({ - selector: 'app-framing', + selector: 'neb-framing', templateUrl: './framing.component.html', - styleUrls: ['./framing.component.scss'], }) export class FramingComponent implements AfterViewInit, OnDestroy { rightAscension: Angle = '00h00m00s' diff --git a/desktop/src/app/guider/guider.component.scss b/desktop/src/app/guider/guider.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/guider/guider.component.ts b/desktop/src/app/guider/guider.component.ts index 96e9d7ebd..e58c9f05c 100644 --- a/desktop/src/app/guider/guider.component.ts +++ b/desktop/src/app/guider/guider.component.ts @@ -7,16 +7,9 @@ import { ElectronService } from '../../shared/services/electron.service' import { Pingable, Pinger } from '../../shared/services/pinger.service' import { GuideDirection, GuideOutput, GuideState, GuideStep, Guider, GuiderHistoryStep, GuiderPlotMode, GuiderYAxisUnit } from '../../shared/types/guider.types' -export interface GuiderPreference { - settleAmount?: number - settleTime?: number - settleTimeout?: number -} - @Component({ - selector: 'app-guider', + selector: 'neb-guider', templateUrl: './guider.component.html', - styleUrls: ['./guider.component.scss'], }) export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { guideOutputs: GuideOutput[] = [] diff --git a/desktop/src/app/home/home.component.ts b/desktop/src/app/home/home.component.ts index 2b655bac2..8feb404a4 100644 --- a/desktop/src/app/home/home.component.ts +++ b/desktop/src/app/home/home.component.ts @@ -31,7 +31,7 @@ function scrollPageOf(element: Element) { } @Component({ - selector: 'app-home', + selector: 'neb-home', templateUrl: './home.component.html', styleUrls: ['./home.component.scss'], }) diff --git a/desktop/src/app/image/image.component.ts b/desktop/src/app/image/image.component.ts index 4ab3031b9..3fa3510ca 100644 --- a/desktop/src/app/image/image.component.ts +++ b/desktop/src/app/image/image.component.ts @@ -49,7 +49,7 @@ import { CoordinateInterpolator, InterpolatedCoordinate } from '../../shared/uti import { AppComponent } from '../app.component' @Component({ - selector: 'app-image', + selector: 'neb-image', templateUrl: './image.component.html', styleUrls: ['./image.component.scss'], }) diff --git a/desktop/src/app/indi/indi.component.html b/desktop/src/app/indi/indi.component.html index cf3d4fe4c..ed92efcae 100644 --- a/desktop/src/app/indi/indi.component.html +++ b/desktop/src/app/indi/indi.component.html @@ -33,7 +33,7 @@
- diff --git a/desktop/src/app/indi/indi.component.ts b/desktop/src/app/indi/indi.component.ts index 776bd110d..c33d85881 100644 --- a/desktop/src/app/indi/indi.component.ts +++ b/desktop/src/app/indi/indi.component.ts @@ -9,7 +9,7 @@ import { deviceComparator, textComparator } from '../../shared/utils/comparators import { AppComponent } from '../app.component' @Component({ - selector: 'app-indi', + selector: 'neb-indi', templateUrl: './indi.component.html', styleUrls: ['./indi.component.scss'], }) diff --git a/desktop/src/app/indi/property/indi-property.component.ts b/desktop/src/app/indi/property/indi-property.component.ts index 52d9b6747..19be45587 100644 --- a/desktop/src/app/indi/property/indi-property.component.ts +++ b/desktop/src/app/indi/property/indi-property.component.ts @@ -2,7 +2,7 @@ import { AfterContentInit, Component, EventEmitter, Input, OnDestroy, Output } f import { INDIProperty, INDIPropertyItem, INDISendProperty, INDISendPropertyItem } from '../../../shared/types/device.types' @Component({ - selector: 'app-indi-property', + selector: 'neb-indi-property', templateUrl: './indi-property.component.html', styleUrls: ['./indi-property.component.scss'], }) diff --git a/desktop/src/app/mount/mount.component.scss b/desktop/src/app/mount/mount.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/mount/mount.component.ts b/desktop/src/app/mount/mount.component.ts index ce21a0ffc..a744a786f 100644 --- a/desktop/src/app/mount/mount.component.ts +++ b/desktop/src/app/mount/mount.component.ts @@ -16,9 +16,8 @@ import { AppComponent } from '../app.component' import { FramingData } from '../framing/framing.component' @Component({ - selector: 'app-mount', + selector: 'neb-mount', templateUrl: './mount.component.html', - styleUrls: ['./mount.component.scss'], }) export class MountComponent implements AfterContentInit, OnDestroy, Pingable { readonly mount = structuredClone(EMPTY_MOUNT) diff --git a/desktop/src/app/rotator/rotator.component.scss b/desktop/src/app/rotator/rotator.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/rotator/rotator.component.ts b/desktop/src/app/rotator/rotator.component.ts index b0eaecb2c..d9d3748d2 100644 --- a/desktop/src/app/rotator/rotator.component.ts +++ b/desktop/src/app/rotator/rotator.component.ts @@ -8,9 +8,8 @@ import { EMPTY_ROTATOR, Rotator } from '../../shared/types/rotator.types' import { AppComponent } from '../app.component' @Component({ - selector: 'app-rotator', + selector: 'neb-rotator', templateUrl: './rotator.component.html', - styleUrls: ['./rotator.component.scss'], }) export class RotatorComponent implements AfterViewInit, OnDestroy, Pingable { readonly rotator = structuredClone(EMPTY_ROTATOR) diff --git a/desktop/src/app/sequencer/sequencer.component.ts b/desktop/src/app/sequencer/sequencer.component.ts index 48ee6940f..ba28ccade 100644 --- a/desktop/src/app/sequencer/sequencer.component.ts +++ b/desktop/src/app/sequencer/sequencer.component.ts @@ -26,7 +26,7 @@ export const SEQUENCER_SAVED_PATH_KEY = 'sequencer.savedPath' export const SEQUENCER_PLAN_KEY = 'sequencer.plan' @Component({ - selector: 'app-sequencer', + selector: 'neb-sequencer', templateUrl: './sequencer.component.html', styleUrls: ['./sequencer.component.scss'], }) diff --git a/desktop/src/app/settings/settings.component.scss b/desktop/src/app/settings/settings.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/app/settings/settings.component.ts b/desktop/src/app/settings/settings.component.ts index f815edd99..6a5da3b99 100644 --- a/desktop/src/app/settings/settings.component.ts +++ b/desktop/src/app/settings/settings.component.ts @@ -10,9 +10,8 @@ import { PlateSolverRequest, PlateSolverType, StarDetectionRequest, StarDetector import { AppComponent } from '../app.component' @Component({ - selector: 'app-settings', + selector: 'neb-settings', templateUrl: './settings.component.html', - styleUrls: ['./settings.component.scss'], }) export class SettingsComponent { tab = 0 diff --git a/desktop/src/index.html b/desktop/src/index.html index 2c5d8fa92..7a090f0c7 100644 --- a/desktop/src/index.html +++ b/desktop/src/index.html @@ -13,7 +13,7 @@ href="assets/icons/favicon.ico" /> - - + + diff --git a/desktop/src/shared/services/electron.service.ts b/desktop/src/shared/services/electron.service.ts index 8804deec1..f54a7bf0b 100644 --- a/desktop/src/shared/services/electron.service.ts +++ b/desktop/src/shared/services/electron.service.ts @@ -199,20 +199,6 @@ export class ElectronService { return this.send('WINDOW.RESIZE', { height: Math.floor(size), windowId: window.id }) } - async autoResizeWindow(timeout: number = 500): Promise> { - if (timeout <= 0) { - const size = document.getElementsByTagName('app-root')[0].getBoundingClientRect().height - - if (size) { - await this.resizeWindow(size) - } - } else { - return setTimeout(() => this.autoResizeWindow(0), timeout) as unknown as number - } - - return undefined - } - pinWindow() { return this.send('WINDOW.PIN', { windowId: window.id }) } From c362b1c9dc051e344499bb96f438003f5da3513b Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 6 Jul 2024 01:15:42 -0300 Subject: [PATCH 016/104] [api]: Camera capture naming --- .../calibration/CalibrationFrameService.kt | 10 +- .../cameras/CameraCaptureNamingFormatter.kt | 102 +++++ .../api/cameras/CameraCaptureNamingType.kt | 27 ++ .../api/cameras/CameraExposureTask.kt | 67 +-- .../api/cameras/CameraStartCaptureRequest.kt | 4 +- .../api/livestacker/LiveStackingRequest.kt | 2 +- .../CameraCaptureNamingFormatterTest.kt | 405 ++++++++++++++++++ 7 files changed, 581 insertions(+), 36 deletions(-) create mode 100644 api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt create mode 100644 api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt create mode 100644 api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt index 012a7dbd7..4dc82f92c 100644 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt +++ b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt @@ -222,11 +222,11 @@ class CalibrationFrameService( @JvmStatic private val LOG = loggerFor() @JvmStatic val ReadableHeader.frameType - get() = frame?.uppercase()?.let { - if ("LIGHT" in it) FrameType.LIGHT - else if ("DARK" in it) FrameType.DARK - else if ("FLAT" in it) FrameType.FLAT - else if ("BIAS" in it) FrameType.BIAS + get() = frame?.let { + if (it.contains("LIGHT", true)) FrameType.LIGHT + else if (it.contains("DARK", true)) FrameType.DARK + else if (it.contains("FLAT", true)) FrameType.FLAT + else if (it.contains("BIAS", true)) FrameType.BIAS else null } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt new file mode 100644 index 000000000..e480619b3 --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt @@ -0,0 +1,102 @@ +package nebulosa.api.cameras + +import nebulosa.api.calibration.CalibrationFrameService.Companion.frameType +import nebulosa.fits.* +import nebulosa.image.format.ReadableHeader +import nebulosa.indi.device.camera.Camera +import nebulosa.indi.device.camera.FrameType +import nebulosa.indi.device.filterwheel.FilterWheel +import nebulosa.indi.device.focuser.Focuser +import nebulosa.indi.device.mount.Mount +import nebulosa.indi.device.rotator.Rotator +import nebulosa.math.AngleFormatter +import nebulosa.math.format +import java.time.Clock +import java.time.LocalDate +import java.time.LocalTime +import kotlin.math.roundToInt + +data class CameraCaptureNamingFormatter( + @JvmField internal val camera: Camera, + @JvmField internal val mount: Mount? = null, + @JvmField internal val wheel: FilterWheel? = null, + @JvmField internal val focuser: Focuser? = null, + @JvmField internal val rotator: Rotator? = null, + @JvmField internal val clock: Clock = Clock.systemDefaultZone(), +) { + + fun format(text: String, header: ReadableHeader): String { + return REGEX.replace(text) { m -> + val value = m.groups[1]!!.value + + val type = CameraCaptureNamingType.entries.firstOrNull { it.name.equals(value, true) } + + if (type == null) { + value + } else { + val groupValues = m.groups.mapNotNull { it?.value?.ifBlank { null } } + val arguments = if (groupValues.size > 2) groupValues.subList(2, groupValues.size) else emptyList() + type.replaceWith(header, arguments)?.ifBlank { null } ?: value + } + }.replace(ILLEGAL_CHARS_REGEX, "") + } + + private fun CameraCaptureNamingType.replaceWith(header: ReadableHeader, args: List): String? { + return when (this) { + CameraCaptureNamingType.TYPE -> header.frameType?.name?.ifBlank { null } ?: FrameType.LIGHT.name + CameraCaptureNamingType.YEAR -> with(LocalDate.now(clock).year) { + when (args.firstOrNull()) { + "2" -> "%02d".format(this - 2000) + else -> "$this" + } + } + CameraCaptureNamingType.MONTH -> "%02d".format(LocalDate.now(clock).monthValue) + CameraCaptureNamingType.DAY -> "%02d".format(LocalDate.now(clock).dayOfMonth) + CameraCaptureNamingType.HOUR -> "%02d".format(LocalTime.now(clock).hour) + CameraCaptureNamingType.MIN -> "%02d".format(LocalTime.now(clock).minute) + CameraCaptureNamingType.SEC -> "%02d".format(LocalTime.now(clock).second) + CameraCaptureNamingType.MS -> "%03d".format(LocalTime.now(clock).nano / 1000000) + CameraCaptureNamingType.EXP -> with(header.exposureTime) { + when (args.firstOrNull()) { + "s" -> "%ds".format(toSeconds()) + "ms" -> "%dms".format(toMillis()) + else -> (toNanos() / 1000).toString() + } + } + CameraCaptureNamingType.FILTER -> header.filter?.ifBlank { null } + CameraCaptureNamingType.GAIN -> "${header.gain.roundToInt()}" + CameraCaptureNamingType.BIN -> "${header.binX}" + CameraCaptureNamingType.TEMP -> "${header.temperature.roundToInt()}" + CameraCaptureNamingType.RA -> header.rightAscension.takeIf { it.isFinite() }?.format(RA_FORMAT) + CameraCaptureNamingType.DEC -> header.declination.takeIf { it.isFinite() }?.format(DEC_FORMAT) + CameraCaptureNamingType.WIDTH -> "${header.width}" + CameraCaptureNamingType.HEIGHT -> "${header.height}" + CameraCaptureNamingType.CAMERA -> camera.name + CameraCaptureNamingType.MOUNT -> mount?.name ?: camera.snoopedDevices.firstOrNull { it is Mount }?.name + CameraCaptureNamingType.FOCUSER -> focuser?.name ?: camera.snoopedDevices.firstOrNull { it is Focuser }?.name + CameraCaptureNamingType.WHEEL -> wheel?.name ?: camera.snoopedDevices.firstOrNull { it is FilterWheel }?.name + CameraCaptureNamingType.ROTATOR -> rotator?.name ?: camera.snoopedDevices.firstOrNull { it is Rotator }?.name + } + } + + companion object { + + @JvmStatic private val REGEX = Regex("\\[(\\w+)(?::(\\w+))*]") + @JvmStatic private val ILLEGAL_CHARS_REGEX = Regex("[/\\\\:*?\"<>|]+") + @JvmStatic private val RA_FORMAT = AngleFormatter.HMS.newBuilder().secondsDecimalPlaces(0).build() + @JvmStatic private val DEC_FORMAT = AngleFormatter.SIGNED_DMS.newBuilder().secondsDecimalPlaces(0).separators("d", "m", "s").build() + + const val FLAT = "[camera]_[type]_[filter]_[width]_[height]_[bin]" + const val DARK = "[camera]_[type]_[width]_[height]_[exp]_[bin]_[gain]" + const val BIAS = "[camera]_[type]_[width]_[height]_[bin]_[gain]" + const val LIGHT = "[camera]_[type]_[year][month][day][hour][min][sec][ms]_[width]_[height]_[exp]_[bin]_[gain]" + + @JvmStatic + fun FrameType.namingFormat() = when (this) { + FrameType.LIGHT -> LIGHT + FrameType.DARK -> DARK + FrameType.FLAT -> FLAT + FrameType.BIAS -> BIAS + } + } +} diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt new file mode 100644 index 000000000..1cff41711 --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt @@ -0,0 +1,27 @@ +package nebulosa.api.cameras + +enum class CameraCaptureNamingType { + TYPE, + YEAR, + MONTH, + DAY, + HOUR, + MIN, + SEC, + MS, + EXP, + FILTER, + GAIN, + // OFFSET, + BIN, + WIDTH, + HEIGHT, + TEMP, + RA, + DEC, + CAMERA, + MOUNT, + FOCUSER, + WHEEL, + ROTATOR, +} diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt index 018417492..ff5feb210 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt @@ -1,20 +1,24 @@ package nebulosa.api.cameras +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.namingFormat import nebulosa.api.tasks.AbstractTask import nebulosa.common.concurrency.cancel.CancellationListener import nebulosa.common.concurrency.cancel.CancellationSource import nebulosa.common.concurrency.cancel.CancellationToken import nebulosa.common.concurrency.latch.CountUpDownLatch +import nebulosa.fits.fits +import nebulosa.image.format.ReadableHeader import nebulosa.indi.device.camera.* import nebulosa.io.transferAndClose import nebulosa.log.loggerFor import okio.sink +import java.nio.file.Files import java.nio.file.Path import java.time.Duration import java.time.LocalDateTime -import java.time.format.DateTimeFormatter import java.util.concurrent.atomic.AtomicBoolean import kotlin.io.path.createParentDirectories +import kotlin.io.path.moveTo import kotlin.io.path.outputStream data class CameraExposureTask( @@ -31,6 +35,9 @@ data class CameraExposureTask( @Volatile private var progress = 0.0 @Volatile private var savedPath: Path? = null + private val outputPath = Files.createTempFile(camera.name, ".fits") + private val formatter = CameraCaptureNamingFormatter(camera) + val isAborted get() = aborted.get() @@ -114,22 +121,24 @@ data class CameraExposureTask( private fun save(event: CameraFrameCaptured) { try { - val savedPath = request.makeSavePath(event.device) - - LOG.info("saving FITS image at {}", savedPath) - - savedPath.createParentDirectories() - - if (event.stream != null) { - event.stream!!.transferAndClose(savedPath.outputStream()) + val header = if (event.stream != null) { + event.stream!!.transferAndClose(outputPath.outputStream()) + null } else if (event.image != null) { - savedPath.sink().use(event.image!!::write) + outputPath.sink().use(event.image!!::write) + event.image?.first?.header } else { LOG.warn("invalid event. event={}", event) return } - this.savedPath = savedPath + with(request.makeSavePath(header = header)) { + LOG.info("saving FITS image at {}", this) + createParentDirectories() + outputPath.moveTo(this, true) + savedPath = this + } + state = CameraExposureState.FINISHED sendEvent() @@ -145,26 +154,26 @@ data class CameraExposureTask( onNext(CameraExposureEvent(this, state, elapsedTime, remainingTime, progress, savedPath)) } + private fun CameraStartCaptureRequest.makeSavePath( + autoSave: Boolean = this.autoSave, + header: ReadableHeader? = null, + ): Path { + require(savePath != null) { "savePath is required" } + + return if (autoSave) { + val now = LocalDateTime.now(formatter.clock) + val savePath = autoSubFolderMode.pathFor(savePath, now) + val format = namingFormat.ifBlank { frameType.namingFormat() } + val fileName = formatter.format(format, header ?: outputPath.fits().use { it.first!!.header }) + Path.of("$savePath", fileName) + } else { + val fileName = "%s.fits".format(formatter.camera.name) + Path.of("$savePath", fileName) + } + } + companion object { @JvmStatic private val LOG = loggerFor() - @JvmStatic private val DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd.HHmmssSSS") - - @JvmStatic - internal fun CameraStartCaptureRequest.makeSavePath( - camera: Camera, autoSave: Boolean = this.autoSave, - ): Path { - require(savePath != null) { "savePath is required" } - - return if (autoSave) { - val now = LocalDateTime.now() - val savePath = autoSubFolderMode.pathFor(savePath, now) - val fileName = "%s-%s.fits".format(now.format(DATE_TIME_FORMAT), frameType) - Path.of("$savePath", fileName) - } else { - val fileName = "%s.fits".format(camera.name) - Path.of("$savePath", fileName) - } - } } } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraStartCaptureRequest.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraStartCaptureRequest.kt index ac243e9d7..105a9cee4 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraStartCaptureRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraStartCaptureRequest.kt @@ -36,12 +36,14 @@ data class CameraStartCaptureRequest( @JvmField val autoSubFolderMode: AutoSubFolderMode = AutoSubFolderMode.OFF, @field:Valid @JvmField val dither: DitherAfterExposureRequest = DitherAfterExposureRequest.DISABLED, @JvmField val calibrationGroup: String? = null, - @JvmField val liveStacking: LiveStackingRequest = LiveStackingRequest.EMPTY, + @JvmField val liveStacking: LiveStackingRequest = LiveStackingRequest.DISABLED, // Filter Wheel. @JvmField val filterPosition: Int = 0, @JvmField val shutterPosition: Int = 0, // Focuser. @JvmField val focusOffset: Int = 0, + // Others. + @JvmField val namingFormat: String = "", ) { inline val isLoop diff --git a/api/src/main/kotlin/nebulosa/api/livestacker/LiveStackingRequest.kt b/api/src/main/kotlin/nebulosa/api/livestacker/LiveStackingRequest.kt index f44d606ff..6f3cd31db 100644 --- a/api/src/main/kotlin/nebulosa/api/livestacker/LiveStackingRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/livestacker/LiveStackingRequest.kt @@ -43,6 +43,6 @@ data class LiveStackingRequest( companion object { - @JvmStatic val EMPTY = LiveStackingRequest() + @JvmStatic val DISABLED = LiveStackingRequest() } } diff --git a/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt b/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt new file mode 100644 index 000000000..66d20625b --- /dev/null +++ b/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt @@ -0,0 +1,405 @@ +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.shouldBe +import nebulosa.api.cameras.CameraCaptureNamingFormatter +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.BIAS +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.DARK +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.FLAT +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.LIGHT +import nebulosa.fits.FitsHeader +import nebulosa.fits.FitsKeyword +import nebulosa.image.algorithms.transformation.CfaPattern +import nebulosa.image.format.HeaderCard +import nebulosa.indi.device.Device +import nebulosa.indi.device.MessageSender +import nebulosa.indi.device.PropertyVector +import nebulosa.indi.device.camera.Camera +import nebulosa.indi.device.camera.FrameType +import nebulosa.indi.device.filterwheel.FilterWheel +import nebulosa.indi.device.focuser.Focuser +import nebulosa.indi.device.mount.* +import nebulosa.indi.device.rotator.Rotator +import nebulosa.indi.protocol.INDIProtocol +import nebulosa.indi.protocol.PropertyState +import nebulosa.math.* +import java.time.* +import java.util.* + +class CameraCaptureNamingFormatterTest : StringSpec() { + + init { + val header = FitsHeader() + val clock = Clock.fixed(Instant.ofEpochSecond(1720114656, 369000000), ZoneOffset.UTC) + val formatter = CameraCaptureNamingFormatter(CameraSim, MountSim, WheelSim, FocuserSim, RotatorSim, clock) + + header.add("FRAME", "Light") + header.add(FitsKeyword.EXPTIME, 1.5) + header.add(FitsKeyword.FILTER, "Red") + header.add(FitsKeyword.GAIN, 80) + header.add(FitsKeyword.XBINNING, 2) + header.add(FitsKeyword.NAXIS1, 1280) + header.add(FitsKeyword.NAXIS2, 1024) + header.add(FitsKeyword.CCD_TEMP, -15.0) + header.add(FitsKeyword.RA, "06 45 08.91728".hours.toDegrees) + header.add(FitsKeyword.DEC, "-16 42 58.0171".deg.toDegrees) + + "type" { + formatter.format("[type]", header) shouldBe "LIGHT" + } + "year" { + formatter.format("[year]", header) shouldBe "2024" + formatter.format("[year:2]", header) shouldBe "24" + formatter.format("[year:4]", header) shouldBe "2024" + formatter.format("[year:3]", header) shouldBe "2024" + } + "month" { + formatter.format("[month]", header) shouldBe "07" + } + "day" { + formatter.format("[day]", header) shouldBe "04" + } + "hour" { + formatter.format("[hour]", header) shouldBe "17" + } + "minute" { + formatter.format("[min]", header) shouldBe "37" + } + "second" { + formatter.format("[sec]", header) shouldBe "36" + } + "millisecond" { + formatter.format("[ms]", header) shouldBe "369" + } + "exposure time" { + formatter.format("[exp]", header) shouldBe "1500000" + formatter.format("[exp:s]", header) shouldBe "1s" + formatter.format("[exp:ms]", header) shouldBe "1500ms" + formatter.format("[exp:us]", header) shouldBe "1500000" + } + "filter" { + formatter.format("[filter]", header) shouldBe "Red" + } + "gain" { + formatter.format("[gain]", header) shouldBe "80" + } + "bin" { + formatter.format("[bin]", header) shouldBe "2" + } + "width" { + formatter.format("[width]", header) shouldBe "1280" + } + "height" { + formatter.format("[height]", header) shouldBe "1024" + } + "temperature" { + formatter.format("[temp]", header) shouldBe "-15" + } + "right ascension" { + formatter.format("[ra]", header) shouldBe "06h45m09s" + } + "declination" { + formatter.format("[dec]", header) shouldBe "-016d42m58s" + } + "camera" { + formatter.format("[camera]", header) shouldBe "Camera Simulator" + } + "mount" { + formatter.format("[mount]", header) shouldBe "Mount Simulator" + } + "focuser" { + formatter.format("[focuser]", header) shouldBe "Focuser Simulator" + } + "wheel" { + formatter.format("[wheel]", header) shouldBe "Wheel Simulator" + } + "rotator" { + formatter.format("[rotator]", header) shouldBe "Rotator Simulator" + } + "light" { + with(header.clone()) { + add("FRAME", "Light") + formatter.format(LIGHT, this) shouldBe "Camera Simulator_LIGHT_20240704173736369_1280_1024_1500000_2_80" + } + } + "dark" { + with(header.clone()) { + add("FRAME", "Dark") + formatter.format(DARK, this) shouldBe "Camera Simulator_DARK_1280_1024_1500000_2_80" + } + } + "flat" { + with(header.clone()) { + add("FRAME", "Flat") + formatter.format(FLAT, this) shouldBe "Camera Simulator_FLAT_Red_1280_1024_2" + } + } + "bias" { + with(header.clone()) { + add("FRAME", "Bias") + formatter.format(BIAS, this) shouldBe "Camera Simulator_BIAS_1280_1024_2_80" + } + } + "unknown" { + formatter.format("[abc]_[camera]_[123]", header) shouldBe "abc_Camera Simulator_123" + } + "not found" { + with(header.clone()) { + delete(FitsKeyword.RA) + formatter.format("[ra]", this) shouldBe "ra" + } + } + "illegal chars" { + formatter.format("[???]", header) shouldBe "[]" + formatter.format("[???a]", header) shouldBe "[a]" + formatter.format("[a???]", header) shouldBe "[a]" + formatter.format("[][/\\:*?\"<>|]", header) shouldBe "[][]" + } + } + + @Suppress("LeakingThis") + private abstract class Simulator(override val name: String) : Device, MessageSender { + + final override val sender = this + final override val id = UUID.randomUUID().toString() + final override val connected = true + final override val properties = emptyMap>() + final override val messages = emptyList() + final override val snoopedDevices = emptyList() + + final override fun sendMessageToServer(message: INDIProtocol) = Unit + + final override fun snoop(devices: Iterable) = Unit + + final override fun handleMessage(message: INDIProtocol) = Unit + + final override fun close() = Unit + + final override fun connect() = Unit + + final override fun disconnect() = Unit + } + + private data object CameraSim : Simulator("Camera Simulator"), Camera { + + override val exposuring = true + override val hasCoolerControl = true + override val coolerPower = 0.0 + override val cooler = true + override val hasDewHeater = true + override val dewHeater = true + override val frameFormats = listOf("RAW16") + override val canAbort = true + override val cfaOffsetX = 0 + override val cfaOffsetY = 0 + override val cfaType = CfaPattern.RGGB + override val exposureMin: Duration = Duration.ofNanos(1000) + override val exposureMax: Duration = Duration.ofMinutes(10) + override val exposureState = PropertyState.IDLE + override val exposureTime: Duration = Duration.ofSeconds(1) + override val hasCooler = true + override val canSetTemperature = true + override val canSubFrame = true + override val x = 0 + override val minX = 0 + override val maxX = 1279 + override val y = 0 + override val minY = 0 + override val maxY = 1023 + override val width = 0 + override val minWidth = 0 + override val maxWidth = 1280 + override val height = 0 + override val minHeight = 0 + override val maxHeight = 1024 + override val canBin = true + override val maxBinX = 4 + override val maxBinY = 4 + override val binX = 1 + override val binY = 1 + override val gain = 0 + override val gainMin = 0 + override val gainMax = 100 + override val offset = 0 + override val offsetMin = 0 + override val offsetMax = 100 + override val guideHead = null + override val pixelSizeX = 2.8 + override val pixelSizeY = 2.8 + override val canPulseGuide = true + override val pulseGuiding = true + override val hasThermometer = true + override val temperature = 15.0 + + override fun cooler(enabled: Boolean) = Unit + + override fun dewHeater(enabled: Boolean) = Unit + + override fun temperature(value: Double) = Unit + + override fun frameFormat(format: String?) = Unit + + override fun frameType(type: FrameType) = Unit + + override fun frame(x: Int, y: Int, width: Int, height: Int) = Unit + + override fun bin(x: Int, y: Int) = Unit + + override fun gain(value: Int) = Unit + + override fun offset(value: Int) = Unit + + override fun startCapture(exposureTime: Duration) = Unit + + override fun abortCapture() = Unit + + override fun fitsKeywords(vararg cards: HeaderCard) = Unit + + override fun guideNorth(duration: Duration) = Unit + + override fun guideSouth(duration: Duration) = Unit + + override fun guideEast(duration: Duration) = Unit + + override fun guideWest(duration: Duration) = Unit + } + + private data object MountSim : Simulator("Mount Simulator"), Mount { + + override val slewing = false + override val tracking = true + override val canSync = true + override val canGoTo = true + override val canAbort = true + override val canHome = true + override val slewRates = emptyList() + override val slewRate = null + override val mountType = MountType.EQ_GEM + override val trackModes = TrackMode.entries + override val trackMode = TrackMode.SIDEREAL + override val pierSide = PierSide.WEST + override val guideRateWE = 0.0 + override val guideRateNS = 0.0 + override val rightAscension = 0.0 + override val declination = 0.0 + override val hasGPS = true + override val longitude = 0.0 + override val latitude = 0.0 + override val elevation = 0.0 + override val dateTime: OffsetDateTime = OffsetDateTime.now() + override val canPark = true + override val parking = false + override val parked = false + override val canPulseGuide = true + override val pulseGuiding = true + + override fun tracking(enable: Boolean) = Unit + + override fun sync(ra: Angle, dec: Angle) = Unit + + override fun syncJ2000(ra: Angle, dec: Angle) = Unit + + override fun slewTo(ra: Angle, dec: Angle) = Unit + + override fun slewToJ2000(ra: Angle, dec: Angle) = Unit + + override fun goTo(ra: Angle, dec: Angle) = Unit + + override fun goToJ2000(ra: Angle, dec: Angle) = Unit + + override fun home() = Unit + + override fun abortMotion() = Unit + + override fun trackMode(mode: TrackMode) = Unit + + override fun slewRate(rate: SlewRate) = Unit + + override fun moveNorth(enabled: Boolean) = Unit + + override fun moveSouth(enabled: Boolean) = Unit + + override fun moveWest(enabled: Boolean) = Unit + + override fun moveEast(enabled: Boolean) = Unit + + override fun coordinates(longitude: Angle, latitude: Angle, elevation: Distance) = Unit + + override fun dateTime(dateTime: OffsetDateTime) = Unit + + override fun park() = Unit + + override fun unpark() = Unit + + override fun guideNorth(duration: Duration) = Unit + + override fun guideSouth(duration: Duration) = Unit + + override fun guideEast(duration: Duration) = Unit + + override fun guideWest(duration: Duration) = Unit + } + + private data object FocuserSim : Simulator("Focuser Simulator"), Focuser { + + override val moving = false + override val canSync = true + override val canAbort = true + override val position = 1 + override val canAbsoluteMove = true + override val canRelativeMove = true + override val canReverse = true + override val reversed = true + override val hasBacklash = true + override val maxPosition = 100000 + override val hasThermometer = true + override val temperature = 15.0 + + override fun moveFocusIn(steps: Int) = Unit + + override fun moveFocusOut(steps: Int) = Unit + + override fun moveFocusTo(steps: Int) = Unit + + override fun abortFocus() = Unit + + override fun reverseFocus(enable: Boolean) = Unit + + override fun syncFocusTo(steps: Int) = Unit + } + + private data object WheelSim : Simulator("Wheel Simulator"), FilterWheel { + + override val moving = false + override val count = 5 + override val names = listOf("Luminance", "Red", "Green", "Blue", "Dark") + override val position = 1 + + override fun moveTo(position: Int) = Unit + + override fun names(names: Iterable) = Unit + } + + private data object RotatorSim : Simulator("Rotator Simulator"), Rotator { + + override val moving = false + override val canSync = true + override val canAbort = true + override val canReverse = true + override val canHome = true + override val hasBacklashCompensation = false + override val backslash = 0 + override val angle = 0.0 + override val minAngle = 0.0 + override val maxAngle = 360.0 + override val reversed = false + + override fun moveRotator(angle: Double) = Unit + + override fun syncRotator(angle: Double) = Unit + + override fun homeRotator() = Unit + + override fun reverseRotator(enable: Boolean) = Unit + + override fun abortRotator() = Unit + } +} From aa9e6c5fd25f41ddf2965d2d607f77202c19326a Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 6 Jul 2024 14:16:35 -0300 Subject: [PATCH 017/104] [api][desktop]: Support Camera Capture naming --- .../api/cameras/CameraCaptureNamingFormat.kt | 28 ++++ .../cameras/CameraCaptureNamingFormatter.kt | 21 +-- .../api/cameras/CameraCaptureNamingType.kt | 22 ++- .../nebulosa/api/cameras/CameraCaptureTask.kt | 2 +- .../api/cameras/CameraExposureTask.kt | 8 +- .../api/cameras/CameraStartCaptureRequest.kt | 2 +- .../kotlin/nebulosa/api/image/ImageService.kt | 3 +- .../api/sequencer/SequencePlanRequest.kt | 2 + .../nebulosa/api/sequencer/SequencerTask.kt | 9 +- .../CameraCaptureNamingFormatterTest.kt | 20 ++- desktop/sequencer.png | Bin 37634 -> 37522 bytes desktop/src/app/camera/camera.component.html | 128 ++++++++++++---- desktop/src/app/camera/camera.component.ts | 137 ++++++++++++------ .../app/sequencer/sequencer.component.html | 72 ++++++++- .../src/app/sequencer/sequencer.component.ts | 91 +++++++----- .../src/app/settings/settings.component.html | 70 +++++++++ .../src/app/settings/settings.component.ts | 19 ++- desktop/src/shared/services/api.service.ts | 2 +- .../src/shared/services/preference.service.ts | 5 +- desktop/src/shared/types/camera.types.ts | 18 +++ desktop/src/shared/types/sequencer.types.ts | 28 ++-- desktop/src/shared/types/settings.types.ts | 33 +++++ .../AutoScreenTransformFunction.kt | 3 +- 23 files changed, 557 insertions(+), 166 deletions(-) create mode 100644 api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormat.kt diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormat.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormat.kt new file mode 100644 index 000000000..c30f8e47f --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormat.kt @@ -0,0 +1,28 @@ +package nebulosa.api.cameras + +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.BIAS_FORMAT +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.DARK_FORMAT +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.FLAT_FORMAT +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.LIGHT_FORMAT +import nebulosa.indi.device.camera.FrameType + +data class CameraCaptureNamingFormat( + @JvmField val light: String? = null, + @JvmField val dark: String? = null, + @JvmField val flat: String? = null, + @JvmField val bias: String? = null, +) { + + fun formatFor(type: FrameType) = when (type) { + FrameType.LIGHT -> light?.ifBlank { null } ?: LIGHT_FORMAT + FrameType.DARK -> dark?.ifBlank { null } ?: DARK_FORMAT + FrameType.FLAT -> flat?.ifBlank { null } ?: FLAT_FORMAT + FrameType.BIAS -> bias?.ifBlank { null } ?: BIAS_FORMAT + } + + companion object { + + @JvmStatic val EMPTY = CameraCaptureNamingFormat() + @JvmStatic val DEFAULT = CameraCaptureNamingFormat(LIGHT_FORMAT, DARK_FORMAT, FLAT_FORMAT, BIAS_FORMAT) + } +} diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt index e480619b3..d6f62c006 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt @@ -26,10 +26,9 @@ data class CameraCaptureNamingFormatter( ) { fun format(text: String, header: ReadableHeader): String { - return REGEX.replace(text) { m -> + return REGEX.replace(text.trim()) { m -> val value = m.groups[1]!!.value - - val type = CameraCaptureNamingType.entries.firstOrNull { it.name.equals(value, true) } + val type = CameraCaptureNamingType.find(value) if (type == null) { value @@ -86,17 +85,9 @@ data class CameraCaptureNamingFormatter( @JvmStatic private val RA_FORMAT = AngleFormatter.HMS.newBuilder().secondsDecimalPlaces(0).build() @JvmStatic private val DEC_FORMAT = AngleFormatter.SIGNED_DMS.newBuilder().secondsDecimalPlaces(0).separators("d", "m", "s").build() - const val FLAT = "[camera]_[type]_[filter]_[width]_[height]_[bin]" - const val DARK = "[camera]_[type]_[width]_[height]_[exp]_[bin]_[gain]" - const val BIAS = "[camera]_[type]_[width]_[height]_[bin]_[gain]" - const val LIGHT = "[camera]_[type]_[year][month][day][hour][min][sec][ms]_[width]_[height]_[exp]_[bin]_[gain]" - - @JvmStatic - fun FrameType.namingFormat() = when (this) { - FrameType.LIGHT -> LIGHT - FrameType.DARK -> DARK - FrameType.FLAT -> FLAT - FrameType.BIAS -> BIAS - } + const val FLAT_FORMAT = "[camera]_[type]_[filter]_[width]_[height]_[bin]" + const val DARK_FORMAT = "[camera]_[type]_[width]_[height]_[exp]_[bin]_[gain]" + const val BIAS_FORMAT = "[camera]_[type]_[width]_[height]_[bin]_[gain]" + const val LIGHT_FORMAT = "[camera]_[type]_[year][month][day][hour][min][sec][ms]_[width]_[height]_[exp]_[bin]_[gain]" } } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt index 1cff41711..c42520967 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt @@ -1,27 +1,35 @@ package nebulosa.api.cameras -enum class CameraCaptureNamingType { +enum class CameraCaptureNamingType(private vararg val alias: String) { TYPE, YEAR, MONTH, DAY, HOUR, - MIN, - SEC, + MIN("minute"), + SEC("second"), MS, - EXP, + EXP("exposure"), FILTER, GAIN, - // OFFSET, BIN, WIDTH, HEIGHT, - TEMP, + TEMP("temperature"), RA, DEC, CAMERA, MOUNT, FOCUSER, WHEEL, - ROTATOR, + ROTATOR; + + companion object { + + @JvmStatic + fun find(text: String): CameraCaptureNamingType? { + return entries.firstOrNull { it.name.equals(text, true) } + ?: entries.firstOrNull { e -> e.alias.isNotEmpty() && e.alias.any { it.equals(text, true) } } + } + } } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt index d8d3d4a98..bd8dad2db 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt @@ -255,7 +255,7 @@ data class CameraCaptureTask( // DITHER. if (!cancellationToken.isCancelled && !cameraExposureTask.isAborted && guider != null - && exposureCount >= 1 && exposureCount % request.dither.afterExposures == 0 + && exposureCount >= 1 && request.dither.afterExposures > 0 && exposureCount % request.dither.afterExposures == 0 ) { ditherAfterExposureTask.execute(cancellationToken) } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt index ff5feb210..b2accc61a 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt @@ -1,6 +1,5 @@ package nebulosa.api.cameras -import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.namingFormat import nebulosa.api.tasks.AbstractTask import nebulosa.common.concurrency.cancel.CancellationListener import nebulosa.common.concurrency.cancel.CancellationSource @@ -163,12 +162,11 @@ data class CameraExposureTask( return if (autoSave) { val now = LocalDateTime.now(formatter.clock) val savePath = autoSubFolderMode.pathFor(savePath, now) - val format = namingFormat.ifBlank { frameType.namingFormat() } + val format = namingFormat.formatFor(frameType) val fileName = formatter.format(format, header ?: outputPath.fits().use { it.first!!.header }) - Path.of("$savePath", fileName) + Path.of("$savePath", "$fileName.fits") } else { - val fileName = "%s.fits".format(formatter.camera.name) - Path.of("$savePath", fileName) + Path.of("$savePath", "${formatter.camera.name}.fits") } } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraStartCaptureRequest.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraStartCaptureRequest.kt index 105a9cee4..bb0ff0474 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraStartCaptureRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraStartCaptureRequest.kt @@ -43,7 +43,7 @@ data class CameraStartCaptureRequest( // Focuser. @JvmField val focusOffset: Int = 0, // Others. - @JvmField val namingFormat: String = "", + @JvmField val namingFormat: CameraCaptureNamingFormat = CameraCaptureNamingFormat.DEFAULT, ) { inline val isLoop diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageService.kt b/api/src/main/kotlin/nebulosa/api/image/ImageService.kt index 13ddb3b69..69a022f33 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageService.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageService.kt @@ -15,6 +15,7 @@ import nebulosa.image.algorithms.computation.Statistics import nebulosa.image.algorithms.transformation.* import nebulosa.image.format.ImageModifier import nebulosa.indi.device.camera.Camera +import nebulosa.log.debug import nebulosa.log.loggerFor import nebulosa.math.* import nebulosa.nova.astrometry.VSOP87E @@ -161,7 +162,7 @@ class ImageService( @Synchronized fun closeImage(path: Path) { imageBucket.remove(path) - LOG.info("image closed. path={}", path) + LOG.debug { "image closed. path=$path" } } @Synchronized diff --git a/api/src/main/kotlin/nebulosa/api/sequencer/SequencePlanRequest.kt b/api/src/main/kotlin/nebulosa/api/sequencer/SequencePlanRequest.kt index 110ab3942..6aa50874a 100644 --- a/api/src/main/kotlin/nebulosa/api/sequencer/SequencePlanRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/sequencer/SequencePlanRequest.kt @@ -3,6 +3,7 @@ package nebulosa.api.sequencer import jakarta.validation.Valid import jakarta.validation.constraints.NotEmpty import nebulosa.api.cameras.AutoSubFolderMode +import nebulosa.api.cameras.CameraCaptureNamingFormat import nebulosa.api.cameras.CameraStartCaptureRequest import nebulosa.api.guiding.DitherAfterExposureRequest import org.hibernate.validator.constraints.time.DurationMax @@ -20,4 +21,5 @@ data class SequencePlanRequest( @JvmField @field:NotEmpty val entries: List = emptyList(), @JvmField @field:Valid val dither: DitherAfterExposureRequest = DitherAfterExposureRequest.DISABLED, @JvmField @field:Valid val autoFocus: AutoFocusAfterConditions = AutoFocusAfterConditions.DISABLED, + @JvmField val namingFormat: CameraCaptureNamingFormat = CameraCaptureNamingFormat.DEFAULT, ) diff --git a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerTask.kt b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerTask.kt index a37e1ec70..ab4ce3783 100644 --- a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerTask.kt +++ b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerTask.kt @@ -64,9 +64,12 @@ data class SequencerTask( initialDelayTask.subscribe(this) tasks.add(initialDelayTask) - fun mapRequest(request: CameraStartCaptureRequest): CameraStartCaptureRequest { - return request.copy(savePath = plan.savePath, autoSave = true, autoSubFolderMode = plan.autoSubFolderMode) - } + fun mapRequest(request: CameraStartCaptureRequest) = request.copy( + savePath = plan.savePath, autoSave = true, + autoSubFolderMode = plan.autoSubFolderMode, + dither = plan.dither, + namingFormat = plan.namingFormat, + ) if (plan.captureMode == SequenceCaptureMode.FULLY || usedEntries.size == 1) { for (i in usedEntries.indices) { diff --git a/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt b/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt index 66d20625b..2bb7dee39 100644 --- a/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt +++ b/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt @@ -1,10 +1,10 @@ import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import nebulosa.api.cameras.CameraCaptureNamingFormatter -import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.BIAS -import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.DARK -import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.FLAT -import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.LIGHT +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.BIAS_FORMAT +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.DARK_FORMAT +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.FLAT_FORMAT +import nebulosa.api.cameras.CameraCaptureNamingFormatter.Companion.LIGHT_FORMAT import nebulosa.fits.FitsHeader import nebulosa.fits.FitsKeyword import nebulosa.image.algorithms.transformation.CfaPattern @@ -62,9 +62,11 @@ class CameraCaptureNamingFormatterTest : StringSpec() { } "minute" { formatter.format("[min]", header) shouldBe "37" + formatter.format("[minute]", header) shouldBe "37" } "second" { formatter.format("[sec]", header) shouldBe "36" + formatter.format("[second]", header) shouldBe "36" } "millisecond" { formatter.format("[ms]", header) shouldBe "369" @@ -74,6 +76,7 @@ class CameraCaptureNamingFormatterTest : StringSpec() { formatter.format("[exp:s]", header) shouldBe "1s" formatter.format("[exp:ms]", header) shouldBe "1500ms" formatter.format("[exp:us]", header) shouldBe "1500000" + formatter.format("[exposure]", header) shouldBe "1500000" } "filter" { formatter.format("[filter]", header) shouldBe "Red" @@ -92,6 +95,7 @@ class CameraCaptureNamingFormatterTest : StringSpec() { } "temperature" { formatter.format("[temp]", header) shouldBe "-15" + formatter.format("[temperature]", header) shouldBe "-15" } "right ascension" { formatter.format("[ra]", header) shouldBe "06h45m09s" @@ -117,25 +121,25 @@ class CameraCaptureNamingFormatterTest : StringSpec() { "light" { with(header.clone()) { add("FRAME", "Light") - formatter.format(LIGHT, this) shouldBe "Camera Simulator_LIGHT_20240704173736369_1280_1024_1500000_2_80" + formatter.format(LIGHT_FORMAT, this) shouldBe "Camera Simulator_LIGHT_20240704173736369_1280_1024_1500000_2_80" } } "dark" { with(header.clone()) { add("FRAME", "Dark") - formatter.format(DARK, this) shouldBe "Camera Simulator_DARK_1280_1024_1500000_2_80" + formatter.format(DARK_FORMAT, this) shouldBe "Camera Simulator_DARK_1280_1024_1500000_2_80" } } "flat" { with(header.clone()) { add("FRAME", "Flat") - formatter.format(FLAT, this) shouldBe "Camera Simulator_FLAT_Red_1280_1024_2" + formatter.format(FLAT_FORMAT, this) shouldBe "Camera Simulator_FLAT_Red_1280_1024_2" } } "bias" { with(header.clone()) { add("FRAME", "Bias") - formatter.format(BIAS, this) shouldBe "Camera Simulator_BIAS_1280_1024_2_80" + formatter.format(BIAS_FORMAT, this) shouldBe "Camera Simulator_BIAS_1280_1024_2_80" } } "unknown" { diff --git a/desktop/sequencer.png b/desktop/sequencer.png index 118eb9803d0a723a972d065983cf8f014d2fff25..6a1825304d9e3c3145253b31147a0806b2146063 100644 GIT binary patch literal 37522 zcmc$FbC4#@w`SX#wtITowr$(CZTH(Yrfp9f)3$Bfw(Z{jzTdq!_TP=z*nJ}^s@|-u z%u|&o&w28kC&T4s#o%GEVSs>u;3dR`6@h?2cD@fzD2VTp@RnrX?-Q7lpoB8i_s<*3 zIPCjBma~Yuvyz>uvzvjV36Pnsos9{NlaZr|iLH~lo%0oF7w>l^(tj!mIhq(aTiDtD zRJO1&0dm?g{7KLH)6&KICnG&0^G^n5P6ifE7WUO6Tm>MYpFk4A0?O{0=Nlf{i3guw zHyGpe^t(Wy?6c�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%0Dxu0ctEv|^Yu2S=r1O+Y(GEusDC=7YbwTmwc6 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⋘<=@SEG;c@-R-1*VQ078=)p)!OOvLF{HR#++t(K{P>6y`Dro~` z3HgT)zLWV1;h~|wv$Lt5Zn}A$&Ocqodmx~Fc5bxUm3jO2Em$=DcJJ46a&n=uu_F5V z-8$+pLP3OHjg8#(c8A(sfdnqsi}pL0P6r1EH~kvWw)^8|DH$0|*=$L@*1vEEbCvmm zYPWZHR{Mq3YrDH5Zf-oBb_Z`LDAFe%BO_VON1GaWUcVw%o+_5z#RG`;>%f}c>jR$l~lAQ4-z{gR`PMEqw)%e8M^ zK}6FZp9bUE?5_{eXr`v7zJ2=!Sy@}-S5#DtKKJ$YeM3#{mo6NlZE7lEVPR3fTUoDoRxqN1*9IBuCcxIO*zl9Me+)^G#U8}S6VyESzV zzZG2(L!25>g%Qj@(wXEIQFpa2AsZl&5wk8SD$i9Z2Nx_P$8g!fg?B;YthenkFfAzb zaM&rc4tECt)F>C?X3F$-_+gFi+Pr-EQd(NNg|2#mUsMzc8IL}rq$CuBLP*ni{?2)i zIyW~L8yh>OtC*dG0}~VTuZIV0^X;Jd@2)5c1_lOMvGG&^9}ZUBQ)Oud1z{~Max*hC z0PR**R&^DPiHRiSJUcegj4XCA^Ru%UApS~91oigE`g;?(C}cbd z85vQ9tHsUGy4_=t&icbi68!vsb2HB_cE?{LAe5Ug^9Tjvw_Y92Q`6CH0yN0T$cU+{ zQn6lbgL_LsQG2@;4|>IF<+OTwQ_~~E9}tW?;q2~*+4(v~Z%8G%9xR0KY1fP3zZR4kxg;gFgD|)hjK4s{@Ig(Fz)_ zmE*^P09KYk>V(DI!TxDCV45f|bN3xbrMMyV~O70(X4Bs?MD4!Tv}2H0UKHfl>!5 zxVX51B%HV{6NNJuPbaJGFehhcdp7z0nVIi~hK2(18UKRbSYp21giE#t1UfA(?ZU!> z@=L^MF;UUAta!7xEG*c7gfuvw&onyQM=!5yvVu~lS8wm(6M9AluNbYAj$4fb`XpLrE>TnApsFT@jH5;y(F@?Z<+C5 zA8?&icQHDAJ;=R&hKh*3uA3jZ(o7Q+fmjCB)zLvazxh)?1?d@G$TmZY>J^8h*)$YBzyW4xZ-c9}S<19A=f>~g;1F|mcQtQbT2{6e;{HG( z7WHuzbjipTDPO*}u~B$hy!!mUb{&5*=H=$_+vNw|_surQRq8=H{XPt&9$m|oygggx{1%Y1CJMGm`mK>T1$}wo2W2p5sZT$pkn$>?o`{n(69sUL|-&) zqy_`{Pey~-X$q#hUtHPf)aoh*Z2=)kYiMYYy#?Tjg^Sw-3Yp#I=F)wMLT*0Evi4=ucC1)yyX)S@vDeJ(G(6QUIm1{ zu;~7}`Dw8`6NBG3DZQ$k@?cfTVel0tw9+t-KFZEXB{LH#Gt>Vp;zgcy|92-g+-+%w z_eC1Mi6K}z?(VRcI6>T)=he^I@oZ>!W0963CFrkDSyan=eqZD@LkyP&I5x2(gvhx<2k?Yk)T?14RO zQK2`-0=h1aSxSV5r6@v+tgk8y--$+IifwmM_k&oaaQ_=6GS8g8xx15*mi{f7O~J`Y zL`FtNuUZ3P;XzT9ll%7L2gd5^YE50;+Qvo)X!SV-1(bAjK>!J2vt~Kmp%E@DlSP3rT|4#2Hext0|oh*91JBp~ynnEag8OISo7&ux)f-)=h*)cL>>KA5}R zM5VRP_h3dc%@xMacav;J`RJbQS8GmWo5`xSr%ht${hG+TzMfMon*QCJHxP64AV3JC|cp$pQ?@QssJ7y{@=fUf0L8R zZf|et&P?OHCDKQwf!bXiz)%qQuQ91~T#VELt#fYA&K$OSWNc@`ZMWGA1&OY%#iX+f z{-K72FNKO%NxCl-gruVi-kmlo{ymBn71U>B^@>#Fs6>GTtXmuA>;G-Cdw29M`O2Q4h=2%MpVJ)hpSkfU{jb~qISM|j z_)pz=5`<>EdOg3%K^@YW?z3N4Dtr9gMR-< zIyzt=0Z*dpyEzLXBR&d#P*)R8n$qsDwd9^WB6){qmX)2I8~oSeX?t2&FaAHGnMSAN z1*3+F&2HS()YK7RRc6e3|Gjf?b`DQUGE?5#+UgQO+(xG0X<2KmcuQZdTSY{Qj9Q&j?%&kTZ1;qy~U4fXo3rdoZfLrl!PblE&?BHyd}; z6iJfu>yD#oqP4`ffU7Gv9=$3=^K@<1g6i`nzU@0v2twKV zz0l0$ynfG2BeTp|siULAVy)vr~Bnsh=?f}8J>sp)v^i-)4MJ-G&ByonbBWB zCFjc*wsm!7scilV0L1-SOJ5%?(oNxDV}~Xr3{2$8&M!38cMDe(HtHC$5WYf2h9&f< z7#SH+M;^;C1A#;lQdm5kk2R}CAa#HwN_K~m3jn#im1w`D1*9*aswty}zq{n4fq1h9 zeeb-w`7sEvQ~iOMKdqW8{S3{NfF-&aiZ@|~+k7h9F@Ws&8 z*FQV$CW{}-m!paLsKgIcCAie(VpO<5vGlK}=Sx7=x;3C@cva@hlB%l25CC03B&1C5 z6L8vne8zs7NdL$CYwML37{FT;8=Y7|6JF%uNi&|~%u+6lA{X!maQ(ZyoEgB{#KZ(d z)7ZHGY_tFL{G5W8Ho$bgDpe-8X1}O@#1PmtEYdPEe=93(1J1K6i(GS6fEVrYBbik# zA}Z=^$@!SkW=9(6aq<3Yvqhv9KrbZ7N2te(>6Dk32kadK zK(PVPp55&i>*(mTZ}f&s?5e7&LZ0I@vVZw(k=4|E`TO@TKD!mAPYZ|D&_g}um;LyrTtE!@~z$e0cq{`}HHx}pew70b(zJC3Vhi8eU zt95cR5-1{3F)X_`0RF~ZDP5A``ULheFSv!LwPEV%*q6q{pG$O(?Kc5yDY!BPKPp$3k9-xTa zF7q{DKG_{8f+c=lbHz#{oRKef44^%ShN8=g>4uMu$&7z#TUpU;x>-X8p{d!7Qu$)F z;k)a%3_`f{h07x;)9dwRU0i-&I<3?dO{6F$7M4<-4fW5TKXnZZ;;Z_Hhp9e%Km<<# zl_jt9tS^VIT~dR4M7IdtFsdU^ zqe~y{0YFrv$HSZ;a`M?g|!}5F9&;h z!GQt+dfpqA#2?%)m|hGrp;kdwm-I9)6oG1<#m3J37l$LJEN>EBZSGW7O}o3lzYlUQ z3)J0g9k9+op0`tkaPiyOeFi}nN|k<=yI4|OT6yhLL&>z+w-~S*qEQ_< zTNA^ihXfoW{plh#x~bhuC%c20R$w`(6r5jO2^CLUAIy|Ceb`Fb${-LmYLa1LO{PmOCMCOH6kzW!3$B|{hozJ!Kp7=HJ z^NpK%%1}>38C543`~)3RP-}?Rl-RmkkwGiQ^JF6GCye4IN!pEpdgfpM~#NU!gz zdp)#c!?O83Cqq*4by2q_zUtsI=$W4EV2_K9lGPoI-O&>Q+u$v;Y}axx30t$ImI%BC z^aKyZyY+G-99=C_`oo5Th9~-BR;hLO;Oz3naMxVvaQ_<$Kf&n9iO5o$)&K`*Psobq zF?e<3P*XZlZhrAWG?tQY)7sI|(6|)u;8dZ?Y?&T1DJdzau77cH{;irj$7`(C+lls= zxVZ2vL&jB4WZM&*^FAlS5@#$mc zCVQ5i5DE*64U})8NQRx0lNZ+JS5e%M_+^>hp)#rS0V6Jhy11yQ|L(PAXA2wS#g*MO znk7+C*HGgu6LKZ%AGh%mX_e~w!_%6=!=h#xgKV6$tE;V9gXDKiO#hV1^%;$)J~A;e z)jUD(fpMIYm368h6vd!n7B_R>bbmzgx$3rK{CdF}t+KKb6kLjYzT?%bfnPuXvjoHy zJk;9OmJs-gUh>(|;3kLw#ft%Qmc)L64|HJy0)mFCIpddbaF#1Ae@MxmoLFUzgGe}| zfEHeIe{uz83o`CUVC__OKC0)+ojsfnhsVbH$>i!T)L4Q^)U{CneFtlC{xxoMDh3J} z;iyThm)Gl5nDbbCr+K}nsMWPE2@}W&&Sf=Ov#?H?o900Ed=nBX1GE4%6NfcFs%O#c ztfRmmqpPQP+DBV_q38y>)xm7J55V&>+kN?jgakxX)GZLY!%|n@)?YU#s}Qb}7FbZn zAe7xe?sq~T?^RszDc`+2ZGlC*n2$i`NDKy^+p{bOZ)9m}3mErrV6JF>!oNA|X8^1c zL31+irwjCU`vW%8QSCM_o0G0DvcR zf52!|mohS<0fx zPmVejZE9-5M}Y^t=H%jHqaBS`_u=MrAePxDh=}cM!FssV@mycFzvbDm2qa*R;c_ek zbZ%PLFCC#_|AiyFuYH}8y&zvSuG#t+3%LA zDx!wCto%Vxehs-lkA{G`pctSrMwM}ioc1zGO2EN<1%{c=L~N2_6L?4s4O~{%)&xwt z-+3dHeU0O*h4IaXC^*Cw)KtdS|Bzj*!jdteCG41j$L6}6ko~HIcLJ=F5sKTcj*gRq z^5HUIkI_G32Jh67aM}SpYVpURooR4n?(OZ(nKYUzQVR$OKqg`{%c!ZTX%3jpqg8=$ zb8+3(ehUJ<3#>V?5Qq~ced6PZfQ7UPn!6I35iJXzDAPf}7*l>@9e zJ3A{WEp0VqvAQ}?0-!N4t>L~Hl8MvCb>m=5f73t2J5GCl9Jz7~29OJG_lFIjbijP< zhnyVc`s26eo}M1fwGKZZwYAL6rM`ZJfSXWMseY0x+tC2cDhrI4>W}IIz+LcR+_2Vi zK|l#p9335zn2b8}KyTJ@`@zr*j0}v}4gv4~(o#;5;0R^#bo) zIoSQ^RU_tuT7yFvAfM$R0YUPBQG~YnfsijMc%)M>hKMsra)kG2eNIdPFw6o2tDBpf zlL6-8n6W0{Y=2$1p_eH10KOcoRbVW;ub*FPK|$cfg$+pbyZSF`Wx%ckA-P_5=LNw$ zI9@{}hxc78L#E3TH5RjTQ!Ng>hLyg#zbE=bAEZ~;KqR5+e57_ISiIS|+8j_9p+3Yq zisj@K7YTTw7g!e5@ka2W2g}XLK+6N?s;-jZKTWL8+I)1TR!8sGvKe9e=vNUXTyN5( zqt3oQq)?3;^hN0(xq^jNMyFz=oq9?&U+%7Cb3J!BhqS&ms{<<ixdzL(Xo4Ui6!`WOs2%WA|H}^YJt+NGcS{r-Dow$cW~)s(1p`-~E)ZSSV7;iyzdVgv z_Q@d4Nzit?u7uwa-*Bi1%kVx*6=na)rnR*ylzGm47~s+0)qiyDVjM}NE`AWDFCxt< zHeTsT*Qju0?6o9Q&EP?3y4w4`XP_Cj|7&G8N3!TYJ9J|0?%@l3Ly-&catbD17Wf)k zHxggB3hr627#9a;xWVJrCc!5K?`Dt;S6*l}4`f+6!M zm>zG@De7MQ=)rqyH|adbS!K0=K$biFr?}85^p3z`!->#g;IbxO?|<%`FZy50w>7&o zi-27{eA#iR2{UN_8(9}G zGZ`ek_4|N-$jHwLM!j_z`Ui&K1T~StE7se=cL|P12u4=@FeO%{o%TQQ+oJVnV4BQyPiHiL+Z+>*caz3^LSNS>o!az;uhSZ$= z)q4anJe3zm{w+Fjyg0uEiJf=c1MmB}7T$WZI;&YwhA(hai#r;>suCcfhEm7NN*(I1 zA+uSop)FT@@R2Q{!qRA{EnbGQQmtw*(hXfJ%`0FunlS${rqbEfZJ$+0i>=y4Em%1C zz~%O5eE7&HEM&RtbRv4nW`C}C28y+t{LoP_EI%r(H2g=yocyMhz~M<7+aPIK!c~No z2U#F4vOR~b&2eaD1u2aJdLT?N~NJN|L*eXI54 z*pPk)^C5E%p`j#fY*9EKWDkPVeZLgL`=yx6pIp7iBwAD1`O-=%EY7AZU&p*Xu!$Rg zkMa9WFZ_5}6f52qPd6MgG?80d_uwQmud>SX3!iVlNcdN-*=5s?QzF`EwW(Q{)cE6| zbn$kJe~1O~VXJ2|z2Ws85eT7`+xPdb^CC8zl{IQ?fho)40;UGP>dZYR6g0wCilZ~! z915IFPSP}fpYd$L0wElm0qavPns;AWinR- z+w$FS;0*slf+7X$vZ&x)w~>M@c%{hc_iwzmqq!y;@mPgpU_6H{^lmjI@OJ%mmL3u^ zj?U8sG6Zw!%kOqWH18#RPp_`L?WMrj`ZE^=#fn9(RrH;q8Q#agcmIqq*@(4o{*``# zchu&b2t(HBvb~*y840xMlwSTSVaCqthy#hp#$I_0_#vnEp;fPKM6wZWxl`+lk0Xrc zrjgi{y`O26LCGsO3l3aDV+adOQHD9E;8gYYi3SghfGO;5azY!wj@NNo$>-ys!`_<> zY&c;if?Apvu0g>Qbi8S&_HcD>ye#$--TCjU6CxypOD`?kj;kySm+*?6^(^bJtJA{q zMyGc^`1K1a{FpwvRIqyQ&g27zNSg&^)8N&*@4kfswlG6$4a1E_K z6}`+Zy#{+7r_8a5e+GwIAK%f(NY*cmzt<1mc8wxUKBUe8HTT$?^OsE{g? z79^4VQRM!dDf7iObx=3+t|{y1B*JmyQD(U*+`-`7ALfS4g_+^6k7T{$l`)84EXJG8 zPZ}e9#ae;?I_V`t!yNEKIp>2EbxX>)Y`98r`2l8znT^BsBN=I|KdBuuYcYq*9K{!jz z_+EW;FKF>pOd3f(_zfS*C&rcc7iTAs5r&AVTz57!QU}(tVH!R{v$$it&lS!4WRXU? zvY0QrQa%?qUzlc>5TucBtP*@(w{?L&>g@Cx!{in>y>HcEFwB`s&Cg+mvw`sKyFvAp zqhh4gv~VbrVx^SQa1Q}iKLN&M7Ve$OoiK|3Kr+-~I%YvHl*nwV5w4(R98VoPDoVnXT{pNAF)c}j-upA%tE2nypeqsZv){e;vj4^;{h;V&RPsik2qI@ z@G+NsVKm3~tE*I!TC=Ek;G}b~C!!}bc^5h>mX?OS)?{Z7mx#)n{LPu&m*WMfzx-=W zt>)IoH>!->q1i97s%#${ty`=>icDL)y!9C?wJUF*8${iY9WjIRzNS+KbHlf>z6&YHfdWh)k^7(geJ{)29^2Q-2TFb~SUrpe-kirjP zfJW&@iGO8#&@Wgy{3X?iD+*;R=R`lMnf%C`M}U2f`SV>lV?msSPty z#s`mmI6b}jVoH2%ru`}XWX7uqSItIN!VT^|+8vR_twv+%aOtO7tsQ;#D~oiRa!>z= z7yRzPFr|pyIFu6nmD@Hn-HZJY9B}C`HmxXp-Bo4yVj-sN^mADgkJu5K$i|V#`?biq^ z7oVdwq)^ir2<-OpMTfU4#b;VwOLP0DsdW({y~o6S3hDt~0z})Vk=IMKXKX%qgx@J| zjD1E8H`ds;YfkjID(AY)rdJRQq~kUIG$tdHjz6d@N&@5<8_iNuFddsORji#^v!8cB zLd}#_QPiu0tZw5{Lk1BQeesjNl;93j9YZ_$nerJb9!kFI*Qw=9~hA# zM8{p`;gJNLhC(&k6GS<6ivHVy7+Gdiu4*3CWRS|BOlouR;obu%D{DiZ>W=QyH0euU z-NXrR5yo=payr_Ukg^%oQ4+~KBLht9=ap+`Fz@Qc$c{{1OKfBmiW2+T18p|fs$cEU z7+E6Pbd!%HHtd|w+}E0b~eq^NNMB_eAv3suur8mCsyFP)o5l4 zYVNflE1mtrk)y`Zv0iw?1}MP5 zoqa;-oX8J!av82JFE}-*UdRi6dQi||uW_QSb(Z;kG`(BdB0c?etxEushzf}>%FcN0 z1Nv-QRk_J^(+uumrsck{`+etdKdM2+?47~>;a5jdJ{|O&-+6)B(!U2oyIkW1TwhaS zK2)~mut`V$6zy{ljx*bc!zh}${qpam7*_M;vUO_KDZ0X09eL=%F(zmbBho*IJ9DgG zKG|{Ti6|Q(=i}R&Q(n2zYqFe;-yM&Via*_Yvi-e}Sk-lp_C0QAR(1*9F}B4f?qz8- zyYtrF)DBST_|&lV(rPu|0RV59`={4~-`QRqC!u@=TMExmGf?Y_mcg8UtU5{e;!&3U z@qoU;43WiEQMK3b(;Dfn@L01>sa>@&){6I!<(ta!q3&1Nq2w86Ji$#>zf!E|me>N@ zoP6Pp?VXu;IX!-uQ`*}z8F7joJgR9f58sBUvSS>kUdR(+2#VGDbF3vT2k{qnI2N#Z zbu+BsGNKroFe15{MD5xdKUZ|OL#%o=t|CriouSdCC6Xy;%wAt*dKvWgDhHHnQ$g27 z=YVAeLMN}@I^$qrxG+qgEbnY4YwwsAKbw>1FNP)XUTAo+SC9q);(2Ro0U@CJ3{2qbMwFgdLftydjZh1*d?8q zY8+*p!SWIn>8lsENZb*-x)%B3#X_GyL{H&t@Zyex`*ox(zO560iCnsZJ-b9yeb!r? zjEC(H;K_btV6u_&n;Q6S2ZoWD&D(I_(h&^<9!o7Xw)SZ*eehn}m~fv3>sTXDyXW95 z1W?T>v+3gNhS81g49la-M?;~yFlaCJ!u!{3ml z0o&^d5izc6?7oD4kP}^aUulw>&yc%1V9gr?oiwD4FT7Ua2nL;q>B-*vA9HPuFsk{& zG(JPaR*q;QV;1df9BQRO4C`vEOdh`|r^_&@6(>}7blmX7Seb`C)4))*`G z_77rs7k=w!5N$8>3JDrvXf-E$yl;8!#oszZwVftSEApU#a+%2rsH5tHUDRMz_0EB|lWj6yRuLj)<3y&WZ*q`li+bM1 zK9E0)$8U`0oY3CjMryO{WzGq;7jM~)CRe?oNjgY;h0<(F+!Vn7r|LM!jz<#YPsrsn^wAP|wE;=4XwehDEGJ*)Q-dD_5Mw}w4Un#R|)sg^{@k6W;Eb1^~izJu@L znf=oAWBu5_|E7x^PGJaj6n8k5qV&}2jp;mf$|1-De<}5hRAnEa9kPaTufOw(4sFDc zuGIVkVEvN!i^snjRj{(bfbsA%a6eeq8W%Rf|JSCZl%gVQs)0())gs%&qGH;jt&zof z>Aauc8p>j@q+Ei|znCvjp;4U{3Ji`Zb0{-!9?s8^c<7s@Z8c8rodpLwBMbRDTZZI1 z!w@1o4Bsv*Up?-*W|=6`c>KL@nVc{H{g>+Lf=-^^jzw-#XH`?8ur3R2O_#Hx3k^d~D8B_t`s~TrbFuu?_em?(`^6BNNaw z<;>x#+)!%CgYH+ZAt7ciNDSAED{??q4jJ8$?^Q+c>l&^Bz9|E zDtz3`f@J2EMBj{gJQId9P9K<_V9^$!!5tA~UMb?VhQ`8}qH^HDJ~LIET|w0u3@Hh- z{$CVj_V1-tq-Xo0(s*?beYbga5r3fSxa@hFH_60_Veo=z%u}Opt8Z zhe=*Eu~Mr_ovUqQ>F-hzJHHdi3k|Q{cw)#bacevM8reMsnkmz3uj~R-;QD2HYY*r) zfOw`>$Z2ir`)m({If$QAogL2OGl{)uZtWWDtvii=xx~pYP+8P@2SPy2VTn=9{^wDe z!}6Wa*X!gbR10&e%pEjb)G2%-l!@rciaK?T{Phm3W$FA#2Dvm>%*u+i%3Ug}Ysz)} z4ZqKyVOYCPIrH$l+vDw+ICJ-Hei5O^3~Ls??ixEf_FOVZZrh6<(d0>^cp)R z>SMA@79PCFpm$YEs6ZE#DOo64u#{WAkfW%PAnYnp=?-nWq)cKK{v7|YlKBiRLq0wD*P|opA40b`{;Bc;I&|%+ga{90PHq(P-D6JZALw+A4L8X)S*5OwT!y~`+%Ltwv zlZga1%bbPk>*DM>OO}_h!vA`BlLf=wj}hpS_xy}iH012$qmq7Kz$p*8R440)EXnM} zHeWox>Ts(>@cDY~+LLY0>~b&v(Dh4#X5Rr zPji15jBa6TsYtT@iH?7yX^08n&rP{qU$ijU8*0UKH~!=rmaJZeSA5hOY4l?EMtI&3 z+;%0|gnKBZyIzS^#p=PC0CqN>D#4bnKu5j3#Zfm!OrTJm8_VB~W^GGE3%c??HoH+X zej&S#%t|zB&UFz*EQy{R$%H#Ayu@Xa;JH!n@Z?7cc^f88sEqY7{@1l*s_%-{6&=y5 zvztCUcc+NhH1D1UZm~k>`8>I>f2_~D*0!5J@zEK(%to#*G5$^p5Kb%mna(g`b#~r7 zs*m@xPK0oKOWnpn=TokGa^{IPy+pB-ZzDPTeY;j1w-d5tDk7!r(;1|}oUT4`z}PG3$iy)m<3lBPH}9O#PCG`V+r`>g z)fZJ|M=X{!5=YD3gj*+uL-jq4!j9s%ui3*OJ-qQEchHw&XW7!!r-#!89W373BqHt! zZ!T65KdgJ9B`>9V2JOmFoknFgtSb=_ww;>X>PiIiFJw`@VdTEz2$=o=ii*50+Zu+f(yCJwbW$XKzg6qGBNWN5=vAbFx;@Dc4@ZNWgJ z5q2W=6+pgkv;;Iqeh2>*2@TVeNEgN1(5qsUZ>e&MqQygnTz~r{B}Oy3RF&^jL>N-u zFvgGgye+x3d~3OAsVs5S**RE>U+IlG7}Y^P2d+~Ue{Tq#p^L&(0xytGi0iIRhJsr~ zzx!^WI)77Ua5g;S#PR%Fg35$s~f>u{|TvzEQ zJg$D4?WRvFkr}<4UD`peB)-=~mefiz96S5PUCAIX`MG0YIXLyZk8F&AAA_(l8|T$vKMz$sjrBoFubJ`|W){&wHlM ze3&{@Gau%|v5Kl)c8VTYEUP>^^E1;boi=qvlSugFPK7T3(w5gMU*aH-=&%tiO2CsxcH z@uGCBsmBAl%q0Cv8@->`Eri!$2F&yd_>FU|M7_lp?4alGe9)s;9z?$*v( z=7+Po1>u4T;WY`twN(|(!Asi}n&xM&7k5MEujfs4`75TB=Wp`YM2a>fw2HwLCfq*A zw~IBtU@vXG%TS56xP%pZrsS$87m`@(clt<5+4LmS_kNGAwvp0)UURN%vXn*U zc|WtwGjeOBw9nt4b2(Sl!3jfq>1yi%q7hsk!|^qD~Tp$056h-1_6as@Rp| z8Evgm*Jdr}B;}r2|IJ~PP^26BmeEd!uE4m^<(_jDdvfbw`3YOA#ileb%`lwbqF+Bq zMbh(Ms)!Ik427AwJe@EzbYrN*ksmt=JH!p~5+)^brkyYqf#`RT6vSh-B?7KaaI6FwP}jUdE)df% zJP(VJ%HaDnJ2*M@$C~!h>5h1D%y@u;z3;cb?MetXOCj+Vb#K#i2`BD5KJdbCSn8Aq zDOlsvEGaXC#bc7|Nbl49b;Tv0X33ND@ZI!qV-WAl;~Va}ID|u#OMeEroFy*(u^qgD z8*0~MpvCm`x<@M4@kLfQda%qY=rA+--!-8wqM==WQcI8SPu|f>|h5EqJ=g#i}Xn%x9;% zF0&DvOTRnt%!^*ly#`Edi;F30`~rN;e=o%PX6;2tQP zO(|jG>GwxgPg>MaT=Cj)ba(a9>t9~^d%TfJY03Dk+*9)-TsEaKK~n3)hV%%PRNslv z>!qzH;E-r@g@QGuyac<*KGY-@EeKchmR2qfPKL~e2_MLx_;~brKDJk}l-g+yU5`Du zCS_#ZSQ5`Z*k#D~H?EK-n1+kb#$XY94;91NU1FY>QfNRW-GCHFXp5E;g(EA+&C7nY z6bTLyDQ`IsHtkWX^McWxG8TsU!1eD~k$?-{$ApZ5$oAeyDKa zh`{2FDYEW?+Tk11elo_&uz->P%Hva(4JNaq&kyg&M!X~4ZziPEq7S_aS>Mq*ZiKwi zy za^@-)fB(_JA6=td{R?JS$onprc=NoOt4v0h^&S0a6HAo#bjOAhH~h6OvyQw)ALC~8 zp5-JPb!0_>HX%2YBFA{}n4J5vA13WyD86uPR3|%iz}=tBtiqd~ zWhVZ_r^l0*iYuB-iUM-SbL8k_LbfD_m%HLl-AN)#Tf&zY|Ex}ZdsC89vM>_A7H@8I zHg|RLMO=GbJ*D_KQ>DSC+}SGohtbr+lKTb*3=qEj*r|@B_RsWVQxsQ{p^}=K2=r$e zbF@sXzz(89|75*NI{rB|h(VypfITVXZE2vIZV8$_QtnmNsCwlYOGrtT2*)+Y@7+UT zKR&R@wH44_23IuSl%~I6@N(-6CCIaz+P%YJ7<|ozG5JMEgmtHP(bXkar)u9U=v0LZBv{R;xqi&*+P|bCmasUyy6AfGxklE55?MAiI@=+A zNF}l9>Z1~Vi-ZQ-b18xYg^)6HBj=$R9x?q=SY>zgUh|7FinnT2ge^JM<~MS^LYQS* ze_6jnp*q@kwcNZ)_Z=l-UrH>_(2mpOax12`vo?=5b)8Z!&phhG5wcrt*It-de5eN?ylkM zLL9apcnK4^ZygL7d+eMCB`Z5>h+u?Je9+2M{-ylLFuSz+O;-Cr*fKN2Nh2M%`qN_9 zbQ0s*31h0v=dU?QAz=+R(69A%VT=(?oF?Xr|s0FP;H(#VPqL8w=K=Cib6Y z!uE7-qt6~=%;SIvDa^yv4P-g-GUqOjVXbFSlbQ^>JU!8pr|^?9#Z9`o>B|t4)e2uk zoIFz7=`xB*^g4wkl+mrp->Q7C4CBp*bfk1dVk0W~3@K~;bkU3a+_w5tVLZjrqZ$1r zZl>)kFV@T%Te#3aY6Hoc53gTHm5ir5sb*xn&*6CgaRNVe;_8wjnrV5Z!s?Pcq)Gz`M8~^(azJ?)dx~ zq(;Lre)QYvz_-N^r@8qCMmb3uW^$HMxef0pX{o3qO+QaJBHVDojE4l{4QJ29zC0TL za~7xVLh9xfNvJ{wbNs`WRdOQ4%@sR{rXm*>0@n(59UC%x?ZL+4X^7OS?Vl`z zkNRLAP2qXw1mS92gRrgDX6trH>CB(D*y$6Ym_!%um@DLJ$H>B1pO;Y#s$He0yNi;< zX17?+Jti;Twa`*icrg6FtqV8uw$7!gsSDy?gK3I*U-y%mp!SgEPPliC&K<+d=pYWa z!QHPP?0ZjB#P^|9VvOWCsgo%g0%(j0;H~llf1l)7Om8%K{e@F}Q`<-cglNUWvIAyz z?7?2;w|r#$pCD5=ifauhWODisoG1T$^v=uq)z+KdNIqjosYp)Xh8t>MUc7+^W-vzR z9p8JW?sNx@CrV@Eqo|u))d zJfdHw?5bUR7GrywVmVwsrrU*uc+N=7@8fFocfkREp?Mtdc*SmEZ&u`E@aB__4;!f) zq5(lwSn|}%&;I!COns=04tL1)3EtG26=YtUoWHT$(As^D?SpEW+RvTH4tEd^_$FJ% zq#h9?oWLYBYvnvOz>6N!v{?<%rtq92c=$Nrs^L~&;ikO|i%OOyTVv!b%&O{sv*xg1Y2@?daZkLZfbcE> zJo7jDReDQn%A03uQPPK2$;|_=4z2k7KQvkp4pOA;7uBo@g=zE-2QPJIR!&s;S27H} z{MAQV+f^XBQG$#8MMf^e=%FQ@Bhb#AWl?vW(}K?$Iw_= z;gq$goiKUrPOvvcqOVkLhHpl}=AmTtX&QCq^KFS_jodP8!@4Q=d1qet1xg$NQTz}s zMSMm5i7hyb5K#pzJ5NelzxUeH+j&*Y!I4^+BZq_}?cB+r)`TqKb8xFybX#Yqn?`mD8R0_l>xZ%46y3ggoGs6S z6@T4@dwe;fzoVO~8hdhJ5*8$U4O0!o&HLwf5$2vHXlPsiVLD3C-2Z>|Lvn7bPnI$> zKtSZ#USLX?l9jlk!cVgX%%o5Md4Xn8Pm&%Xb1QZ#$raA!=!s;~`lybj~@K{RrVLgw3X4C|I?~uB4L*Luj;5L{k5)n2jPwX;4PD_CQQ!h z25K>7U^jyNX#a)7{9k=|7Id(|g1MGn(qg<7#j?Kz!=wCa=I46yY;Gx$cB|_VWWhOl zFLwTcW-2}9`*w5z4(MZbx4@TFcKP>}Dfb4^dh%2Ru9|!qsD)xtBj|m^qu~Ft(wCtR zT`EAHd2=W4Ipgwp1sA3yUO+&gBbG03Qm~7@;^a!WR0V z=ilQ{)ejAkymMF^9B^^R_4)8!XpGQZksq?<2#UlyN+D{7oi4*KgTfU}g7CLZb(i)&C z1E35VzAeqo(A@AzAtNO-GgCpYz)h5ng_hK5yPULOsA@$W3G4114~IEP}E zn$li=iIN{<@_2mVs%5b4PJ11TPK1nfJ45B1SUw##GU3`DTV8XL znF?ev2vKVX53&CIuKcBRNh|ybeq{>ldvT4TlV}yh-pLyZ22pgZ>{xfte3#?V)a17m zdp`TMNE+1IW)mbsm|4+Wdw&HoixIclNz&$fE>1{8R)r9~wv{GP>geq#{H$^jbh88K!9!I-5lF^!4wEy7TvC zDCX^wY6flvgXg-orf0&LOo_;-9hJ|P7MYnc&u{f}B&IdAe>1VY#>O)LKG@me+F}oR zUCMKom80X=xNHWYgetOhpK!lNRO(x~>Pp1~nsld8+F~4$_11H6WYVW1zV-KzSKLys zHLYBxwG>vLDGU_EQVPk-cOP6N*6*jJ6}xw>th6>_MyHG$@s4BBDd;OQTQLurh z;a`)-1+Kch^kC-C0T;h-c_?|TMiY|ciC<-CXk-V$T4M9-p5(rvtvN~PmcGx(m^ls= zw)-!MZa>_nvGCT=XZ+2?qp+|nqcr}8?LnMY21oqospiEA^xSz8b-#HQHFy5J^+cru zri&iP4DT>)ywINmg{siekBw=~q7d^u`}l)*#Cf=HKDd)i6q4DS3DRm%1d5=gI7=}Z+`5mncJHo=H$BTSXw;`w}}pH zjK86URkE&U1@v8$aktu^N5<*85qs2DxY8UY*j)TndI1xuoqiTCj_sumQFuR}*m?KZ zyOS|Y#+8-oY4Z#%xB6v@6C0LyhHjJ>wQWr|pPr*0Xlb4xrio`C&-xNY?3a4vvg?S% ze5+i0&>}ked9>?Czw2kVgUHawJNAwf)`#7!=|%oiCJh6v+}1o6#`~vBXRc zy&tA?^Vcr?6ribCw4am~r&Bq#CP#&%eNumNg=vaKf3}RM z_>jE2b2fyX&2LNOUP69va%t%G+JYYp>x1s2Td>}J@2#o7U?DqZT6S}{j*=pw=6(Jr zA^oi_y#)4@cQn>#E)#}ok!~%Bw*pP;q$eU*%|m8M*Ri7#gWlpf&h32@S&udg9%=4N zYFJ=GD&xI6BMO8|?lNvw4ylUIv=KiNa#HCR-#+ly>cUd-RN$*27R zOO%othqN*%w*GOSi{X7^m>1*Vd~)yNfD?bvWK%zB>E>A=&L>a5SlQS9wk?X*2D_U+ z<3gD;w4OchzKID53GrHv8la$?NKEs53c9fr#m=~)H*f!D%u|0HG}`0mo2kH(cNN9V zR;b6-m6ubBUqojNX`wrlXN%p}Pvd6tQT9D`Ds9ZlPdj9envQMwhD<#z% zT=YnaKoWRraw>VImn}@yCm~tN)|q>ZNRpIUOa+qG)s`nlQ8R;GAsx#GpZj)LbiTJr zys=wZ;%1KW8MZ#K^Xv?_pSR00R=3lCc@=!xU{@(5Sn1b}=sx(C(ebfSh9<@RaD6(m zX39}3v~ohkFYG2Bu6O&1-)hfFz>&wv`tkLY$FjQU%Q1~FGqtOqYm6n!XV*yCYJA+g zC$dJt;^p=J>o3tl+INdTCVj@aOs>DL-7vR28|Z!g!-IzmKa^fx588nmo0~aJ|Ih+_ z=xDQQD~j8c(6}ouYwL#exXp*TYo(g!-_8Yn&>O4;1UC1;e7T=|41b23n=AUDy$NY- z;%dzgj|Ntv86#1-%h!ruK`Kg_1?(kvU9U#&x2K;fGWwophFzK(y71|dT7xc?-)NG- zRpo_9ZI@`N(7Y3i6eaV!4u=BCQzzMygU0H)U4B6sSgOIi29)yjCeGxLj=-dK=xK7j zk`@}%XU4|^)}v$*1}$0*O#LYh`l^Gjg~4=ly#iMbgD;eqZl@uYPjK&Ro6!1r)zt|Tun%@&W!<_&eD)X zDB&%|(kc<1i4QBHXr01fdi@POwZ+q++L^pgw%KKzSW}K995^rib_nU7&nRIZtrfpg zmZ6#tYGY~c(v&vmjLgvnDMQ^+)!^hqg^^o|8GODyd+&oA^Y}j^BWWgzS7y2DweMJ6#aDtS3!zVxkI))BBZSEzxO*FZs%p>7BrR&1XMn`flO*0w ziG~ipf%e^F-uJA%OQ}cXTS@DEZuW?hnloV$%f^sf}f z++Uq^es}Axhih~tQ*R;vxRz+JLI9~@DLgtnjKI&F-zo%bo!vv%!%gkYw{@pG*WgE1 z`=j!c<|K)8mo>#vk*N?cD|U(*y{lQ8taB5iM}$SMrLqXi(1IzGzrPBQZ*NU~sDEQ= zgXbu2Xs$B#1_=FLFJ{wd_9-tSAS{B;#hJxLRWpp&t*Obp^KeGIu+&}gpewP*kT#{f z(zQB*y!pDdgA|gjj-I=Ge#_`f-KjbN{uho0Vi# zHp@9{c+MzWH)O_1+M^YSrN3XfS#7cIXKh^`-vkRZ*&$JlG?(+xf3NrW8Vq_;q;n=b z2M#6K(=?BU%^2P_#b_N!vLk0QnWbc)0SMNGR)joCJ43HW|AoA`QKI+_lQ?+dCn@n? z_>ej|hTQ;w4FXgj3N})X&&zIc1zYx~Fm(5DZ4DSS443>@# zt3r2sc(_W5PF~*i(AJL%8QBH9&$E>E3{^_l4$V&DvQ`CN^qr*s_)$dA4n7yampp|z zy$O2 zJ;KrRO8oGmYxMCE$uAk6IWIX7Gv7+ut-bF!E+YPJB0^0YiZsS8E zdSu??$h@E5dtsNKQK3C!g3ALIA)Qk%J(HKJPksx*g-nS zRz^`{UU^XKZpd!`guG3@%G~Vtbaa1>`}Pwd*HU}^DSr$44iOoJpFv_}dVh$O;@^{D}Uy0{ZvCPT!aAkkl-aa4S{PA*&E+JPkwfxk{r4)bynb;STg!;wq@HfxS zlBwr~hu;!$-J1^Lo1BK0>&BLrB6pM>;O|0&cdh`F_UG$|e<6KPV85hr`@ySvm?o`& zhWH?vlH{_x2+imm5WIahXG{;K6oMZ7W|&dZ0K>u{;DA=dEdJ@bA-LEmIr;?GRVEBT zLjwt%P=RV_^RGTT7z2vc4)nir*)Pf+A8vIQoAv?ZwIflC+Su55w9Hy@tke=%QEyHT zHh2iFpK_L{rlD34iI9ZM7^;+mj)2bWZOe=Dy_ zWYYH=+LH7L$2a#rcDa6yYDp*wwC3!Li~3Y87#?-C?{BR!Kb7}Ml598an{$%#z2(p5 zd7F$I7XBx7PQA4BL+y@NdT;Qo-w*bpvla`|ghlz8mW}nA)Xo7Hf|Og3S8RvXhs6G> zTRvA3fyDHU>4t-=?FEj-_l|-cdB|GQLn?2cc<73{_uIJp^|q>4N7x$y$ZOjuoe!!;$N7SXEab z1?${Yh|wQEdhY$Al&OA^azPCaBb!G-Rmk}&#>=&uy#g!VaDs)$pgq#!1_2h&a z3Z8s9AdVZA>bT}%yJy|`eq7VC?9wRLF}t2c}5BSl*jei^zQI zp@QbYwdG~M7g@A4G~Pfi%{T6*IzQc21dhvD#L+TE}_A`J)3N1zo1!YeWx1YK*ZYF3^&b48f9iON<_=XM8+`SZ^QgE?bJ^>^FWW+vU|hb*Jjiq7bo|rWm4` z(wV|rx|`DTm-AA;8$u4Xgc2M}U&VFS!`q1PlFnuqWwv*35Vq$*jW{jplTdtIiud+U zM2Vs}GX8qZUqBEKs?xe2F^z^5QXAh)E~sSsR+pns(ra+*&q0=s$u75nB*TU8ojj2@ z7UQIUO%B~@xyxrELb1$oNM%tIpTGY$=XI+J*W!j3=|fBQqB68KqG`kS?lJac zt|)4a?zSPN93H!M3#!MHjxa9f>a!>a`#z6&2nR&SQ@pC=xEep%7>ssk8I}2&wk9m( zy!@7}*VcubAirg((>KvbYI@7mJJAhwRo~%N1q$)KTe@XX3@_ua=tl)Kc4+z)^KKUZ zbovE~gL@lSqjxSd5@%XawoaB&MFyYQZuaCo79%RBWBzLU5-pLXY{Ppma$O5wGUX~e z!0d%5I;3?aRXf9E1|m{JrWS{%H|IBk8qg~wGC@PM^v@|s0+g~Jn`+woTY!bZ_P#(s zKmaU+_T}D1gGRs!Y|lOghxHgZ$^~U*>^#=MpaLedWJ)gpp)~b542_LbRI_az9kDxF z0Uwe!EvPb`t(FJ0m?FCcnH(fiDN7l+gq&96{0Z(m($HoG!;I&)zDhL}SE%$ShN9(h zy^HIo{;eX9KhuXV$E9$W5R}T5(ReTjR8kXPw{QLbLWP}Y|h>oV?Q zakNhelECqY?^(*C29wzNll5Ke8|Y@YTMFhxuNB_L%6VZgvBf{His{C&lp#a4DC+%L zG2>CaXT{6+bjO%88Ult-TgW$Bqb|)mj^Bf-L=I}Z%FA|B{_0&vU5z#=#2wjhFguSv zAu(2^$n51W7Nj9V-V7(~m!VU{Be=h)C7ObB`L(gWr*HGvfbU&vO)JxdHk9nsMjgiQ z_SZ-*)>y2JbOrU1;NBT-3LOw)<8VF}rMg4<=#xe7s*<`@2K=DRfImj2Dlj(s%H;B#o#7cV`6f}+it1}C)C!8v}! zipQoaSt#(2F2k)svSs81UEj<=I`+;8Ul7H@_@`j4{;4Bn`R_S`lC=D1-3KDla?Yu& zmYU^U3;w}ca;(#Tw|%u`zT4R}wzcD=1zE<6wxu5ir;F4blA$hjaLiB_cK=-uE2>dhCX<)#wN&zwL{W0DT*{NA zYcJLNDBiZ+j1Q64p-_)Z!nN(IVEQIj|6(Av`mES6s!g&Jd2O?$c_4vHjDmJE;}`6| z^c`k@GDVs2<;0oie!TGd>_pq|Je{w1YH!hB=;F3*+2SNxNaAt9`wU6$3-w)+t$AB- zfA$T0_A&3;Zpyowx?nQ0E$tMBd)eO0&v>Zd0Tm_TZ(VAqxsV!DilFYfDtu|Y&DB=p zzR~1?@blSYy$zS(#7^V(Q>zYVMq<8<7}M1L{fIZku3L(7*py4RMX~CAtaV#PeNnUes3-WyT@d6Ihu~9GCK3zwmY>i-%Cn^7x>I2ycTr zFtH4)Z%IN)In{WB&xx?NE8r>@Z^{r~+`&-W?BU*SaiCT}cnEdmZT6f#hq{x^Dqw*Y z0n{5K#{gV6|KMOFfZVz7v@*P1?zzCgkRce50hnJ%jNAYg@HaZy-(6isz)c*AUjqK{ zxEJ~i!{YHcaZFB0!C=2Jyba(}rdew4Ub_SVhW>I-60oB(*m%>zRHU<8{}>kV&&q}| z9Nyy{#f~Pt5p~FLjlvn%yYUBscQrvCJ!v0q=wa4B~K-jqhAQG^8 z1JB}AfUf@wR$qRBfd&wUlvhN@%4DvWPG&-Sj|jd83r}NHvpF-vjk0VPXXl5Wr_Mkk zG`^Fr%p5K1AqeM!4bre+%FY_?Vw2tvKwpo6IEc`rPt}-mp=mN#Td4N@*t`~f?xy2) zw*O*41B1}FuGv=&KTs+%>cnvJnAfdKOGDJvPm-#482}pvwESH1V2vsK>mEDhWm%k(I{17O05u|KWe_4uL>3AT?D-h1%>O;(b2@WZrvmz5{EemDQiP8yYDK<9{`KD zos*3r57wH`kd_3GfXg&oWK4j-fSjOG;nB#L8C)q$l~;gS2L|+IPft(2;!Q}?VsN0a zNCgODc|}Dy<2`2UI&Dh;NuL6V6S7lubOqos5QIcTtkN$ZKfd7T=m z>n;FH*lQb#t_KJmDR*u}PcnhH43*b3O!;9wy5TZyP^K zR&%L4u^TK(3uM7Caj}yI@W0@dVO(i6pLGIV0ub*B!Ri3*NqcGO#|?+9pA24*KugWY zh%|9E+?uS>0`ZTBYBQ|5wc|T#y2x!^b171($$TVcIB6bfYJs?C7J{Z;?hugj6Rrf#JY?sPspGNK+c!34Df z1BCO1FoHN7R+WL^%K%!s0#Kdgv!rP`TjjJ9FF=1WY=?K)8S`#7KcY z4uQzt4Z!1qXapzl^B|AX3Th^5Yhw>2JWOF)zQ`)B?zI!>)r27dCKU^Sh7q5rJ%@M7 z0QGo`NAl2XrmC_M^y<=ZGioY>eu1@)1u33`tto;iS($W&cp3Eh8RnfaK6sE*5|up* zQPIbbA0NJHxCAD#1t4^0?v%Gm&R&I=-qS2L`3VTxSMX*L7*?2dEsCB-G7#9yktaS{ z69)`=30s((2C^w|-*6zEvst~X06yu&jJ50mV3A+LIt|QZWm}s6eiGZ*-le1SlP#C+ zCKAjB7eH|{;NJId55cH)0mqp)mi|U%a{6WV046N}bMYn+~bfXp%?(3 zovetsMz4DbaA>K3$_AOY!r<p0l>0s>U`glcA|6ic!5z^rS%ohOO7hx>o_~PApk*xa%p#4PvJOr%})NBB|S&8Kj z;D5_n1P2Gt&(DVmS%Uly5S(e**n+`ta2WjlLauRGa?;e*l`GNOv45cX6i)2CKcEId zY(yGaF_4Wh6g+OSky1-?00rh82$_#5FNSMfk^XF+-MfCJMA1yIg zOG8;nIDBjUOsEH~{>HP_(>;^0mQ*VTN^{f&VPeaQXA$6 zZX=r_;|5;}U};Uf4IBZ}7PmF#|lth$R=O zdc$xmONNwm)*+L67hEH38@x)_E;7Q00;9VaLA0&v-Rl_iB-mtRTP`yl(48S+wFCH5 zm807>mdsnHS#2&VF&o*pFlY3IlP2eU?gg7rZ9n`l<;1Uc#dXS?w@v9 zIXMZWDwp%$*Rs-sh7e*+`!ghf78ACcn;QsP{Q_+iSvh@fGWGn|kNubMSh%Kwez&zj zvDB3k4f);0PIHS2@K}I02cHI}bIpOM8C<_c@Gk&>NAcU({@?A{K@`gW>U*rhG(E|hVyW0c&uj5?;561|#DxC@=Obb!PQr6RAjKWW?pmjF9n z>gwug&DyoSp0G9t4k?6ak3m5TG!!smB@%siKyYsfERjA$5B&W6`QY|tRA|(O;0`c0 z9fDnOL|iaj>@p@mh!28YL0G&2-ufZb36N_zfhr74S$H5&?xKPnpgy=~cbg;5^_sga{e}NVN z2D=Jd{6AE(+j740gXjm`R^E<#_^ms4OqmQ%;4fng5;&7|Ac9NEeqd*J0uClfhOJkY zh_k5XOoNCL4X|{>!ibGJW1d2a4D(zd)p=nWD5lv3!yipdQa^=|-KL-j1XwzlSLD`n zsEob2&+KDVq8)t|~C&kAbi&*d2MEt`N#b}+jDqr-$tS6$P>Vk=^ zqUQ{nU)bL7`}>sz-!9jK;KVAe<3BsKu}U>`UR2)HEynZhh$uYQ=ZyI~cz1372!BIb zwoa-S&h5Z=V0l=(=@AG* zPHBn9$}IVXg_z1lBfdwNg5_Cy6|sR@+^7B_>SJDvu*SZrrltnkTnLa>tTO7wJv}?C zfX$Q(&$9<$M`qwr&p)pVbl;`VKX*y$|1o|3Y9vfx^7$9>ZJ*GEE>KU%t8xe0e_J?< zH6xT;z%DmB*){8chj{)=>48^7_a;`$?4Mn#_ND$rvBuP)2q7=n8ig{|cNN5c&FDk@ zf$t8n>D5OdQ3VlrR_ot?G$E`s_76&}kGFL79i~U>jYs;Al9{WkAe^kEl=5F!PxSQJGry~kQhJqLjQ%5S za(t6fW%%flK4)}KdK^yQe)ijc{xTU0QZ)c7#%()Kh{9oY?Kz&SL+*lIZ}P~Vqqa5$ zv%UY(gm|^ijSq9PSCowZWBjhBjUJwsb*}1{@YPI9bw6A_l-{S53_7wOjx1KUtE~N% zslqWAJLGf)P9eec?{e>6zkc*JYW#W}F&(|mT#FoKT+syLXOXwB8!8;0Mv_Evj|W7& zFI7o6GeyOC)b3gt zyBnUR!cC@=u5i-Cd=6|Ob_Ofm1Jd)FSli=ISS5Eneb|ub&*C9v3yH>Vf4hrB_;=ot zD0DGZW!KNn^A{4FJ*^@ryK&rs=0|s;2W*Qm59jPyG5j>XCUquZ#Fl%TvrH%|E=xR{ zFL@xgXH~A8Kl9a@B0Gi9jgzXou0ZFj z;y8JHd;gRf_oW?^Ol!(O`6d*0Nr=?p`n-^?w`7$GTfJZqUoNqv=8KpfqxqOa6!~|9 z>V=;BBlPXX?Fn)Iy`PB=WgH7voTo3#VPp9$1Q2xS7=suOIX50^%+2f)!4Wjks>h<1e<(=mb*F zw^s7S_VJDTpHs#?>*@)QVi3{|37rU^cx|0RoALea)tQ*OqVl{*&5}i=b@2P#?}$$b zl06@dBH~g%so-16Bet**EQss$$k{ehYliFd#vcgrHM95t$G~a z6+5yZFTDx+{@zCBE-gnZ8AGFhfG9` z)Tf7}t^RQ`CwtH^n=`E$``uUc!=y#Q@>7VCK zd7Wd)q?zcPnD_1vt0iwNy3PIgRC|YKA*72Z5MgtVEt|%R!DF*;S5NYn|J{|1yv84N zT(eDO$9m3tdq4b5On(GSo)hRW4e{~cwkI=JM0NDVhBPA+O%nP`BR{;5XEHPHZ%Stu zxtZckQ*ds*8GJlKP3U=3iLXeM`B%zK+u6~2UjZ%!l-sYkI~;$UW*y$qv~-`Iyd@p2 z6IzWKOD@ot$6Ft{&EdI-c94*mSa;zVojN)1*7x>M8X6`J5IaeG<%&*hdVZMeJjYVj z;%qpdGlo?!HDP$iE8}Ej>}-2S=u9bBX!pthJ`35LR31gZ*EZ+sQn$Oei~AF8J0}l$ zDgCET=f|Zj-Iy}*f*Y^tdUE=@;pqRGnxw?hS^vCcc`9jf)?8$K=H4E2usr#8Hr#E3 zef_gb_L#oAg|P4SLn(>IYMzaPEtJ#!`+8H?gi;LUPx{@z64Jdkw{M95x3j_1Vl`FUeJWV4!L)oZX!>Ca+GQP3=KK;XYQqGP8rDW3ZG29zMSI-)7M3;DA*r zKK@ee?M-ymE9)cvL0$hT)aWLEzuQ49+ak|EGauSunz!^gx5^ z=1qO?Go?H00V)J&^Lx7t?c|~e#!=Ai36n{a*0$DVODvyXE3BN+SJ1aS9s5K(eQX?MSpCv%ty}6Bp z_~Lhjg?J`$dI3Ru{~Y3-oB#PRm8K~J9cDa4{k+PUt_n4ZC0qvfWq(j&A?h!IHp@Mn zNnC*q7Wg7tZnA53zWF)mc=hNXBj z^cD?V!$SN9Cihc$d3jKgl7xlqe6jVwHp%wS1`zE02v_-D0b5szZ}c{y*G*$Kxl0!j za+6K2KV;r)I|+uozkn#;bN?{7 z{X+5^@Df#akGb>WsO9649N9GjMr;i>Roa(T>&+tq2mv3CP!_V>XV zhr7Y+w!v4c>+2LDexzh%F@^CL5n2iwLu|pQHNj-djc+Czldg})4mQ{Qy)_RS-*;;F z78!0m)p#ROp%r`uOyWaRdo@!>2G$%F1>XW^-?M<${mZRlYZ|oJDbuDFO+i7mz z43|mEpFtoZv*Dz+`)6x<3s`j&3lYr?OOcvn`sbCwnUX+Y<*858d`Hb@Gyh%Hi#!0FJlib@>%k`(W%7A|_A;Ojqkd1+D7X zA}00=o)~`ybHAHEKgd(C-nEwDUe~@^E*ddjnV#v$f+YBxLXU(l~t#gTdGAu znOMOKzhp5;fScq0bP%i77@^-+mZLU_8&&k{q2^`+<|_apEezeH}t` z%)BCsno#cuy8V<c&X2>_31w0R&g!GO`tc}Qp zUil{>(YMe=6$g#%WE%P-zsedLBA8yauWr0LS!dmw|GHrQ+O_BV;;ZDz=`(*`1z?6j{S04Kb^-@FATh)tG5cI$ z;{G7UnbO<*O%v&@aywQ$JJ{Ux_h#S7at;3H_@0^bWlyW6x9l{PiDP%fKb>SJ(7+eE z-b^VvHWpBB$&a0fY&f$YoEb>nD*}IAFF>&+NUW_`b2~h#mubq$(1g1(!Id@G>6Xo$ zH0IIn7A{5e=^Z+iDWE)^#430Wgm)$1>|(y@GJ4j?(z}1AmSN$gJ>|vYD29?r;xgCN z(4g}7%T#9exsHt}A6Lefn*F0+wZY)+7;n^lE~ZgyWr=O#eso%=Ym+c z^m2qgP5AQ2aUF-d^Iany4xu*IAfK+Si2))ZDlZO4Ph;7@Th2i;71=RmsNflL5s~V9Y%)_pRX4-)y_wTW#mb?NHjBbFdgykq_&FK`99d z!`HOfm2N54Q@zV@eNtuAeweBC_v`zBT3-0_m*1^NyO|{an*q^(Hg&0+^I~laJ8yHb i5bv0#e`5kGG>+R1Tgj%+qe=+)C;e1GBKOJb5C0#=dvUD* diff --git a/desktop/src/app/camera/camera.component.html b/desktop/src/app/camera/camera.component.html index 8f218de17..26b83fe48 100644 --- a/desktop/src/app/camera/camera.component.html +++ b/desktop/src/app/camera/camera.component.html @@ -36,7 +36,7 @@ [text]="true" [rounded]="true" icon="mdi mdi-image-multiple" - (click)="openCameraImage()" + (onClick)="openCameraImage()" pTooltip="View image" tooltipPosition="bottom" size="small" /> @@ -45,7 +45,7 @@ [text]="true" [rounded]="true" icon="mdi mdi-wrench" - (click)="calibrationMenu.show()" + (onClick)="calibrationMenu.show()" pTooltip="CALIBRATION: {{ this.request.calibrationGroup ?? 'None' }}" tooltipPosition="bottom" size="small" /> @@ -55,7 +55,7 @@ [text]="true" [rounded]="true" icon="mdi mdi-dots-vertical" - (click)="cameraMenu.show()" + (onClick)="cameraMenu.show()" size="small" />
- + (onClick)="exposureTimeMenu.toggle($event)" + [label]="exposureTimeUnit" />
@@ -514,7 +512,7 @@
@@ -522,25 +520,25 @@ Enabled
RA only
@@ -569,7 +567,7 @@ @@ -578,7 +576,7 @@
Enabled
@@ -587,9 +585,9 @@
32-bit (slower)
+ + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+
diff --git a/desktop/src/app/camera/camera.component.ts b/desktop/src/app/camera/camera.component.ts index 1d840b94e..668fac8f5 100644 --- a/desktop/src/app/camera/camera.component.ts +++ b/desktop/src/app/camera/camera.component.ts @@ -8,12 +8,28 @@ import { BrowserWindowService } from '../../shared/services/browser-window.servi import { ElectronService } from '../../shared/services/electron.service' import { Pingable, Pinger } from '../../shared/services/pinger.service' import { PreferenceService } from '../../shared/services/preference.service' -import { Camera, CameraDialogInput, CameraDialogMode, CameraPreference, CameraStartCapture, EMPTY_CAMERA, EMPTY_CAMERA_START_CAPTURE, ExposureMode, ExposureTimeUnit, updateCameraStartCaptureFromCamera } from '../../shared/types/camera.types' +import { + Camera, + CameraDialogInput, + CameraDialogMode, + CameraDitherDialog, + CameraLiveStackingDialog, + CameraNamingFormatDialog, + CameraPreference, + CameraStartCapture, + EMPTY_CAMERA, + EMPTY_CAMERA_START_CAPTURE, + ExposureMode, + ExposureTimeUnit, + FrameType, + updateCameraStartCaptureFromCamera, +} from '../../shared/types/camera.types' import { Device } from '../../shared/types/device.types' import { Focuser } from '../../shared/types/focuser.types' import { Equipment } from '../../shared/types/home.types' import { Mount } from '../../shared/types/mount.types' import { Rotator } from '../../shared/types/rotator.types' +import { resetCameraCaptureNamingFormat } from '../../shared/types/settings.types' import { FilterWheel } from '../../shared/types/wheel.types' import { Undefinable } from '../../shared/utils/types' import { AppComponent } from '../app.component' @@ -72,9 +88,6 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Pingable { return this.mode !== 'CAPTURE' } - showDitherDialog = false - showLiveStackingDialog = false - calibrationModel: SlideMenuItem[] = [] private readonly ditherMenuItem: SlideMenuItem = { @@ -82,7 +95,7 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Pingable { label: 'Dither', slideMenu: [], command: () => { - this.showDitherDialog = true + this.dither.showDialog = true }, } @@ -91,7 +104,16 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Pingable { label: 'Live Stacking', slideMenu: [], command: () => { - this.showLiveStackingDialog = true + this.liveStacking.showDialog = true + }, + } + + private readonly namingFormatMenuItem: SlideMenuItem = { + icon: 'mdi mdi-rename', + label: 'Naming Format', + slideMenu: [], + command: () => { + this.namingFormat.showDialog = true }, } @@ -122,8 +144,9 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Pingable { ], } - readonly cameraModel: SlideMenuItem[] = [this.ditherMenuItem, this.liveStackingMenuItem, this.snoopDevicesMenuItem] + readonly cameraModel: SlideMenuItem[] = [this.ditherMenuItem, this.liveStackingMenuItem, this.namingFormatMenuItem, this.snoopDevicesMenuItem] + running = false hasDewHeater = false setpointTemperature = 0.0 exposureTimeMin = 1 @@ -133,7 +156,21 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Pingable { subFrame = false readonly request = structuredClone(EMPTY_CAMERA_START_CAPTURE) - running = false + + readonly dither: CameraDitherDialog = { + showDialog: false, + request: this.request.dither, + } + + readonly liveStacking: CameraLiveStackingDialog = { + showDialog: false, + request: this.request.liveStacking, + } + + readonly namingFormat: CameraNamingFormatDialog = { + showDialog: false, + format: this.request.namingFormat, + } readonly exposureTimeUnitModel: MenuItem[] = [ { @@ -669,47 +706,61 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Pingable { this.savePreference() } + resetCameraCaptureNamingFormat(type: FrameType) { + const namingFormatPreference = this.preference.cameraCaptureNamingFormatPreference.get() + resetCameraCaptureNamingFormat(type, this.namingFormat.format, namingFormatPreference) + this.savePreference() + } + apply() { return this.app.close(this.makeCameraStartCapture()) } private loadPreference() { if (this.mode === 'CAPTURE' && this.camera.name) { - const preference: Partial = this.preference.cameraPreference(this.camera).get() - - this.request.autoSave = preference.autoSave ?? false - this.savePath = preference.savePath ?? '' - this.request.autoSubFolderMode = preference.autoSubFolderMode ?? 'OFF' - this.setpointTemperature = preference.setpointTemperature ?? 0 - this.request.exposureTime = preference.exposureTime ?? this.camera.exposureMin - this.exposureTimeUnit = preference.exposureTimeUnit ?? ExposureTimeUnit.MICROSECOND - this.exposureMode = preference.exposureMode ?? 'SINGLE' - this.request.exposureDelay = preference.exposureDelay ?? 0 - this.request.exposureAmount = preference.exposureAmount ?? 1 - this.request.x = preference.x ?? this.camera.minX - this.request.y = preference.y ?? this.camera.minY - this.request.width = preference.width ?? this.camera.maxWidth - this.request.height = preference.height ?? this.camera.maxHeight - this.subFrame = preference.subFrame ?? false - this.request.binX = preference.binX ?? 1 - this.request.binY = preference.binY ?? 1 - this.request.frameType = preference.frameType ?? 'LIGHT' - this.request.gain = preference.gain ?? 0 - this.request.offset = preference.offset ?? 0 - this.request.frameFormat = preference.frameFormat ?? (this.camera.frameFormats[0] || '') - this.request.calibrationGroup = preference.calibrationGroup - this.request.dither.enabled = preference.dither?.enabled ?? false - this.request.dither.amount = preference.dither?.amount ?? 1.5 - this.request.dither.raOnly = preference.dither?.raOnly ?? false - this.request.dither.afterExposures = preference.dither?.afterExposures ?? 1 - this.request.liveStacking.enabled = preference.liveStacking?.enabled ?? false - this.request.liveStacking.type = preference.liveStacking?.type ?? 'SIRIL' - this.request.liveStacking.executablePath = preference.liveStacking?.executablePath ?? '' - this.request.liveStacking.dark = preference.liveStacking?.dark - this.request.liveStacking.flat = preference.liveStacking?.flat - this.request.liveStacking.bias = preference.liveStacking?.bias - this.request.liveStacking.use32Bits = preference.liveStacking?.use32Bits ?? false - this.request.liveStacking.slot = preference.liveStacking?.slot ?? 1 + const cameraPreference: Partial = this.preference.cameraPreference(this.camera).get() + + this.request.autoSave = cameraPreference.autoSave ?? false + this.savePath = cameraPreference.savePath ?? '' + this.request.autoSubFolderMode = cameraPreference.autoSubFolderMode ?? 'OFF' + this.setpointTemperature = cameraPreference.setpointTemperature ?? 0 + this.request.exposureTime = cameraPreference.exposureTime ?? this.camera.exposureMin + this.exposureTimeUnit = cameraPreference.exposureTimeUnit ?? ExposureTimeUnit.MICROSECOND + this.exposureMode = cameraPreference.exposureMode ?? 'SINGLE' + this.request.exposureDelay = cameraPreference.exposureDelay ?? 0 + this.request.exposureAmount = cameraPreference.exposureAmount ?? 1 + this.request.x = cameraPreference.x ?? this.camera.minX + this.request.y = cameraPreference.y ?? this.camera.minY + this.request.width = cameraPreference.width ?? this.camera.maxWidth + this.request.height = cameraPreference.height ?? this.camera.maxHeight + this.subFrame = cameraPreference.subFrame ?? false + this.request.binX = cameraPreference.binX ?? 1 + this.request.binY = cameraPreference.binY ?? 1 + this.request.frameType = cameraPreference.frameType ?? 'LIGHT' + this.request.gain = cameraPreference.gain ?? 0 + this.request.offset = cameraPreference.offset ?? 0 + this.request.frameFormat = cameraPreference.frameFormat ?? (this.camera.frameFormats[0] || '') + this.request.calibrationGroup = cameraPreference.calibrationGroup + + this.request.dither.enabled = cameraPreference.dither?.enabled ?? false + this.request.dither.amount = cameraPreference.dither?.amount ?? 1.5 + this.request.dither.raOnly = cameraPreference.dither?.raOnly ?? false + this.request.dither.afterExposures = cameraPreference.dither?.afterExposures ?? 1 + + this.request.liveStacking.enabled = cameraPreference.liveStacking?.enabled ?? false + this.request.liveStacking.type = cameraPreference.liveStacking?.type ?? 'SIRIL' + this.request.liveStacking.executablePath = cameraPreference.liveStacking?.executablePath ?? '' + this.request.liveStacking.dark = cameraPreference.liveStacking?.dark + this.request.liveStacking.flat = cameraPreference.liveStacking?.flat + this.request.liveStacking.bias = cameraPreference.liveStacking?.bias + this.request.liveStacking.use32Bits = cameraPreference.liveStacking?.use32Bits ?? false + this.request.liveStacking.slot = cameraPreference.liveStacking?.slot ?? 1 + + const cameraCaptureNamingFormatPreference = this.preference.cameraCaptureNamingFormatPreference.get() + this.request.namingFormat.light = cameraPreference.namingFormat?.light ?? cameraCaptureNamingFormatPreference.light + this.request.namingFormat.dark = cameraPreference.namingFormat?.dark ?? cameraCaptureNamingFormatPreference.dark + this.request.namingFormat.flat = cameraPreference.namingFormat?.flat ?? cameraCaptureNamingFormatPreference.flat + this.request.namingFormat.bias = cameraPreference.namingFormat?.bias ?? cameraCaptureNamingFormatPreference.bias Object.assign(this.equipment, this.preference.equipmentForDevice(this.camera).get()) } diff --git a/desktop/src/app/sequencer/sequencer.component.html b/desktop/src/app/sequencer/sequencer.component.html index 815df01fb..87220a175 100644 --- a/desktop/src/app/sequencer/sequencer.component.html +++ b/desktop/src/app/sequencer/sequencer.component.html @@ -229,10 +229,80 @@
+ +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+
-
+
{ - this.savedPath = undefined - this.savedPathWasModified = false - this.storage.delete(SEQUENCER_SAVED_PATH_KEY) + this.updateSavedPath() Object.assign(this.plan, structuredClone(EMPTY_SEQUENCE_PLAN)) this.add() @@ -324,6 +314,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable use32Bits: false, slot: 1, }, + namingFormat: this.plan.namingFormat, }) this.savePlan() @@ -335,9 +326,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable private afterSavedJsonFile(file: JsonFile) { if (file.path) { - this.savedPath = file.path - this.storage.set(SEQUENCER_SAVED_PATH_KEY, this.savedPath) - this.savedPathWasModified = false + this.updateSavedPath(file.path) } } @@ -352,19 +341,20 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable } private async loadSavedJsonFileFromPathOrAddDefault() { - const savedPath = this.storage.get>(SEQUENCER_SAVED_PATH_KEY, undefined) + const sequencerPreference = this.preference.sequencerPreference.get() - if (savedPath) { - const file = await this.electron.readJson(savedPath) + if (sequencerPreference.savedPath) { + const file = await this.electron.readJson(sequencerPreference.savedPath) if (file !== false) { this.loadSavedJsonFile(file) return } - this.prime.message(`Failed to load the saved Sequence at: ${savedPath}`, 'error') + this.prime.message(`Failed to load the saved Sequence at: ${sequencerPreference.savedPath}`, 'error') - this.storage.delete(SEQUENCER_SAVED_PATH_KEY) + sequencerPreference.savedPath = undefined + this.preference.sequencerPreference.set(sequencerPreference) } if (!this.loadPlan()) { @@ -372,18 +362,41 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable } } + private updateSavedPath(savedPath?: string) { + this.savedPath = savedPath + const sequencerPreference = this.preference.sequencerPreference.get() + sequencerPreference.savedPath = savedPath + this.preference.sequencerPreference.set(sequencerPreference) + } + private loadPlan(plan?: SequencePlan) { - plan ??= this.storage.get(SEQUENCER_PLAN_KEY, this.plan) + const sequencerPreference = this.preference.sequencerPreference.get() - Object.assign(this.plan, structuredClone(plan)) + plan ??= sequencerPreference.plan - this.camera = this.cameras.find((e) => e.name === this.plan.camera?.name) ?? this.cameras[0] - this.mount = this.mounts.find((e) => e.name === this.plan.mount?.name) ?? this.mounts[0] - this.wheel = this.wheels.find((e) => e.name === this.plan.wheel?.name) ?? this.wheels[0] - this.focuser = this.focusers.find((e) => e.name === this.plan.focuser?.name) ?? this.focusers[0] - this.rotator = this.rotators.find((e) => e.name === this.plan.rotator?.name) ?? this.rotators[0] + if (this.plan !== plan) { + Object.assign(this.plan, structuredClone(plan)) + } + + this.camera = this.cameras.find((e) => e.id === this.plan.camera) ?? this.cameras[0] + this.mount = this.mounts.find((e) => e.id === this.plan.mount) ?? this.mounts[0] + this.wheel = this.wheels.find((e) => e.id === this.plan.wheel) ?? this.wheels[0] + this.focuser = this.focusers.find((e) => e.id === this.plan.focuser) ?? this.focusers[0] + this.rotator = this.rotators.find((e) => e.id === this.plan.rotator) ?? this.rotators[0] + + const cameraCaptureNamingFormatPreference = this.preference.cameraCaptureNamingFormatPreference.get() + this.plan.namingFormat.light ??= cameraCaptureNamingFormatPreference.light ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.light + this.plan.namingFormat.dark ??= cameraCaptureNamingFormatPreference.dark ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.dark + this.plan.namingFormat.flat ??= cameraCaptureNamingFormatPreference.flat ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.flat + this.plan.namingFormat.bias ??= cameraCaptureNamingFormatPreference.bias ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.bias - return plan.entries.length + return this.plan.entries.length + } + + resetCameraCaptureNamingFormat(type: FrameType) { + const namingFormatPreference = this.preference.cameraCaptureNamingFormatPreference.get() + resetCameraCaptureNamingFormat(type, this.plan.namingFormat, namingFormatPreference) + this.savePlan() } toggleAutoSubFolder() { @@ -447,13 +460,15 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable } savePlan() { - this.plan.camera = this.camera - this.plan.mount = this.mount - this.plan.wheel = this.wheel - this.plan.focuser = this.focuser - this.plan.rotator = this.rotator - this.storage.set(SEQUENCER_PLAN_KEY, this.plan) - this.savedPathWasModified = !!this.savedPath + const sequencerPreference = this.preference.sequencerPreference.get() + sequencerPreference.savedPath = this.savedPath + Object.assign(sequencerPreference.plan, this.plan) + sequencerPreference.plan.camera = this.camera?.id + sequencerPreference.plan.mount = this.mount?.id + sequencerPreference.plan.wheel = this.wheel?.id + sequencerPreference.plan.focuser = this.focuser?.id + sequencerPreference.plan.rotator = this.rotator?.id + this.preference.sequencerPreference.set(sequencerPreference) } showEntryMenu(entry: CameraStartCapture, dialogMenu: DialogMenuComponent) { diff --git a/desktop/src/app/settings/settings.component.html b/desktop/src/app/settings/settings.component.html index 29212fcab..95f91e293 100644 --- a/desktop/src/app/settings/settings.component.html +++ b/desktop/src/app/settings/settings.component.html @@ -280,4 +280,74 @@
+
+
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+
diff --git a/desktop/src/app/settings/settings.component.ts b/desktop/src/app/settings/settings.component.ts index 6a5da3b99..d164128f5 100644 --- a/desktop/src/app/settings/settings.component.ts +++ b/desktop/src/app/settings/settings.component.ts @@ -5,8 +5,8 @@ import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' import { PrimeService } from '../../shared/services/prime.service' import { EMPTY_LOCATION, Location } from '../../shared/types/atlas.types' -import { LiveStackerType, LiveStackingRequest } from '../../shared/types/camera.types' -import { PlateSolverRequest, PlateSolverType, StarDetectionRequest, StarDetectorType } from '../../shared/types/settings.types' +import { FrameType, LiveStackerType, LiveStackingRequest } from '../../shared/types/camera.types' +import { DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, PlateSolverRequest, PlateSolverType, resetCameraCaptureNamingFormat, StarDetectionRequest, StarDetectorType } from '../../shared/types/settings.types' import { AppComponent } from '../app.component' @Component({ @@ -32,6 +32,10 @@ export class SettingsComponent { id: 3, name: 'Live Stacking', }, + { + id: 4, + name: 'Capture Naming Format', + }, ] readonly locations: Location[] @@ -46,6 +50,8 @@ export class SettingsComponent { liveStackerType: LiveStackerType = 'SIRIL' readonly liveStackers = new Map() + readonly cameraCaptureNamingFormat = structuredClone(DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT) + constructor( app: AppComponent, private readonly preference: PreferenceService, @@ -67,6 +73,8 @@ export class SettingsComponent { for (const type of dropdownOptions.transform('LIVE_STACKER')) { this.liveStackers.set(type, preference.liveStackingRequest(type).get()) } + + Object.assign(this.cameraCaptureNamingFormat, preference.cameraCaptureNamingFormatPreference.get(this.cameraCaptureNamingFormat)) } addLocation() { @@ -123,6 +131,11 @@ export class SettingsComponent { return this.electron.send('LOCATION.CHANGED', this.location) } + resetCameraCaptureNamingFormat(type: FrameType) { + resetCameraCaptureNamingFormat(type, this.cameraCaptureNamingFormat, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT) + this.save() + } + save() { for (const type of this.dropdownOptions.transform('PLATE_SOLVER')) { this.preference.plateSolverRequest(type).set(this.plateSolvers.get(type)) @@ -133,5 +146,7 @@ export class SettingsComponent { for (const type of this.dropdownOptions.transform('LIVE_STACKER')) { this.preference.liveStackingRequest(type).set(this.liveStackers.get(type)) } + + this.preference.cameraCaptureNamingFormatPreference.set(this.cameraCaptureNamingFormat) } } diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts index 74e32b42f..5e2366079 100644 --- a/desktop/src/shared/services/api.service.ts +++ b/desktop/src/shared/services/api.service.ts @@ -645,7 +645,7 @@ export class ApiService { sequencerStart(camera: Camera, plan: SequencePlan) { const body: SequencePlan = { ...plan, mount: undefined, camera: undefined, wheel: undefined, focuser: undefined } - const query = this.http.query({ mount: plan.mount?.id, focuser: plan.focuser?.id, wheel: plan.wheel?.id }) + const query = this.http.query({ mount: plan.mount, focuser: plan.focuser, wheel: plan.wheel }) return this.http.put(`sequencer/${camera.id}/start?${query}`, body) } diff --git a/desktop/src/shared/services/preference.service.ts b/desktop/src/shared/services/preference.service.ts index 320a7c3fb..a346fb1a5 100644 --- a/desktop/src/shared/services/preference.service.ts +++ b/desktop/src/shared/services/preference.service.ts @@ -10,7 +10,8 @@ import { ConnectionDetails, Equipment, HomePreference } from '../types/home.type import { EMPTY_IMAGE_PREFERENCE, FOV, ImagePreference } from '../types/image.types' import { EMPTY_MOUNT_PREFERENCE, Mount, MountPreference } from '../types/mount.types' import { Rotator, RotatorPreference } from '../types/rotator.types' -import { EMPTY_PLATE_SOLVER_REQUEST, EMPTY_STAR_DETECTION_REQUEST, PlateSolverRequest, PlateSolverType, StarDetectionRequest, StarDetectorType } from '../types/settings.types' +import { EMPTY_SEQUENCER_PREFERENCE, SequencerPreference } from '../types/sequencer.types' +import { CameraCaptureNamingFormat, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, EMPTY_PLATE_SOLVER_REQUEST, EMPTY_STAR_DETECTION_REQUEST, PlateSolverRequest, PlateSolverType, StarDetectionRequest, StarDetectorType } from '../types/settings.types' import { FilterWheel, WheelPreference } from '../types/wheel.types' import { Undefinable } from '../utils/types' import { LocalStorageService } from './local-storage.service' @@ -109,4 +110,6 @@ export class PreferenceService { readonly imageFOVs = new PreferenceData(this.storage, 'image.fovs', () => []) readonly calibrationPreference = new PreferenceData(this.storage, 'calibration', () => ({}) as CalibrationPreference) readonly autoFocusPreference = new PreferenceData(this.storage, 'autoFocus', () => structuredClone(EMPTY_AUTO_FOCUS_PREFERENCE)) + readonly sequencerPreference = new PreferenceData(this.storage, 'sequencer', () => structuredClone(EMPTY_SEQUENCER_PREFERENCE)) + readonly cameraCaptureNamingFormatPreference = new PreferenceData(this.storage, 'camera.namingFormat', () => structuredClone(DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT)) } diff --git a/desktop/src/shared/types/camera.types.ts b/desktop/src/shared/types/camera.types.ts index 8df82172f..e0bd4123d 100644 --- a/desktop/src/shared/types/camera.types.ts +++ b/desktop/src/shared/types/camera.types.ts @@ -3,6 +3,7 @@ import type { Thermometer } from './auxiliary.types' import type { CompanionDevice, Device, PropertyState } from './device.types' import { isCompanionDevice } from './device.types' import type { GuideOutput } from './guider.types' +import { type CameraCaptureNamingFormat } from './settings.types' export type CameraDialogMode = 'CAPTURE' | 'SEQUENCER' | 'FLAT_WIZARD' | 'TPPA' | 'DARV' | 'AUTO_FOCUS' @@ -169,6 +170,7 @@ export interface CameraStartCapture { focusOffset?: number calibrationGroup?: string liveStacking: LiveStackingRequest + namingFormat: CameraCaptureNamingFormat } export const EMPTY_CAMERA_START_CAPTURE: CameraStartCapture = { @@ -199,6 +201,7 @@ export const EMPTY_CAMERA_START_CAPTURE: CameraStartCapture = { use32Bits: false, slot: 1, }, + namingFormat: {}, } export function updateCameraStartCaptureFromCamera(request: CameraStartCapture, camera: Camera) { @@ -304,3 +307,18 @@ export const EMPTY_LIVE_STACKING_REQUEST: LiveStackingRequest = { use32Bits: false, slot: 1, } + +export interface CameraDitherDialog { + showDialog: boolean + request: Dither +} + +export interface CameraLiveStackingDialog { + showDialog: boolean + request: LiveStackingRequest +} + +export interface CameraNamingFormatDialog { + showDialog: boolean + format: CameraCaptureNamingFormat +} diff --git a/desktop/src/shared/types/sequencer.types.ts b/desktop/src/shared/types/sequencer.types.ts index 7672dcce3..b7f69d19f 100644 --- a/desktop/src/shared/types/sequencer.types.ts +++ b/desktop/src/shared/types/sequencer.types.ts @@ -1,8 +1,5 @@ -import type { AutoSubFolderMode, Camera, CameraCaptureEvent, CameraStartCapture, Dither } from './camera.types' -import type { Focuser } from './focuser.types' -import type { Mount } from './mount.types' -import type { Rotator } from './rotator.types' -import type { FilterWheel } from './wheel.types' +import type { AutoSubFolderMode, CameraCaptureEvent, CameraStartCapture, Dither } from './camera.types' +import type { CameraCaptureNamingFormat } from './settings.types' export type SequenceCaptureMode = 'FULLY' | 'INTERLEAVED' @@ -32,11 +29,12 @@ export interface SequencePlan { entries: CameraStartCapture[] dither: Dither autoFocus: AutoFocusAfterConditions - camera?: Camera - mount?: Mount - wheel?: FilterWheel - focuser?: Focuser - rotator?: Rotator + namingFormat: CameraCaptureNamingFormat + camera?: string + mount?: string + wheel?: string + focuser?: string + rotator?: string } export const EMPTY_SEQUENCE_PLAN: SequencePlan = { @@ -63,6 +61,7 @@ export const EMPTY_SEQUENCE_PLAN: SequencePlan = { afterTemperatureChangeEnabled: false, afterHFDIncreaseEnabled: false, }, + namingFormat: {}, } export interface SequencerEvent extends MessageEvent { @@ -72,3 +71,12 @@ export interface SequencerEvent extends MessageEvent { progress: number capture?: CameraCaptureEvent } + +export interface SequencerPreference { + savedPath?: string + plan: SequencePlan +} + +export const EMPTY_SEQUENCER_PREFERENCE: SequencerPreference = { + plan: structuredClone(EMPTY_SEQUENCE_PLAN), +} diff --git a/desktop/src/shared/types/settings.types.ts b/desktop/src/shared/types/settings.types.ts index 278504800..076cabfc0 100644 --- a/desktop/src/shared/types/settings.types.ts +++ b/desktop/src/shared/types/settings.types.ts @@ -1,3 +1,5 @@ +import type { FrameType } from './camera.types' + export type PlateSolverType = 'ASTROMETRY_NET' | 'ASTROMETRY_NET_ONLINE' | 'ASTAP' | 'SIRIL' export interface PlateSolverRequest { @@ -37,3 +39,34 @@ export const EMPTY_STAR_DETECTION_REQUEST: StarDetectionRequest = { maxStars: 0, slot: 1, } + +export interface CameraCaptureNamingFormat { + light?: string + dark?: string + flat?: string + bias?: string +} + +export const DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT: CameraCaptureNamingFormat = { + light: '[camera]_[type]_[year][month][day][hour][min][sec][ms]_[width]_[height]_[exp]_[bin]_[gain]', + dark: '[camera]_[type]_[width]_[height]_[exp]_[bin]_[gain]', + flat: '[camera]_[type]_[filter]_[width]_[height]_[bin]', + bias: '[camera]_[type]_[width]_[height]_[bin]_[gain]', +} + +export function resetCameraCaptureNamingFormat(type: FrameType, format: CameraCaptureNamingFormat, defaultValue?: CameraCaptureNamingFormat) { + switch (type) { + case 'LIGHT': + format.light = defaultValue?.light ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.light + break + case 'DARK': + format.dark = defaultValue?.dark ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.dark + break + case 'FLAT': + format.flat = defaultValue?.flat ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.flat + break + case 'BIAS': + format.bias = defaultValue?.bias ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.bias + break + } +} diff --git a/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/transformation/AutoScreenTransformFunction.kt b/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/transformation/AutoScreenTransformFunction.kt index ddd031f63..4376998ff 100644 --- a/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/transformation/AutoScreenTransformFunction.kt +++ b/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/transformation/AutoScreenTransformFunction.kt @@ -5,6 +5,7 @@ import nebulosa.image.algorithms.ComputationAlgorithm import nebulosa.image.algorithms.TransformAlgorithm import nebulosa.image.algorithms.computation.Median import nebulosa.image.algorithms.computation.MedianAbsoluteDeviation +import nebulosa.log.debug import nebulosa.log.loggerFor import kotlin.math.max import kotlin.math.min @@ -35,7 +36,7 @@ data object AutoScreenTransformFunction : ComputationAlgorithm ((m - 1) * x) / ((2 * m - 1) * x - m) } - LOG.info("STF auto stretch. midtone={}, shadow={}, highlight={}", midtone, shadow, highlight) + LOG.debug { "STF auto stretch. midtone=$midtone, shadow=$shadow, highlight=$highlight" } return ScreenTransformFunction.Parameters(midtone, shadow, highlight) } From c59de95233580a469342da4a630f3a1d4da9ee17 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 6 Jul 2024 17:55:42 -0300 Subject: [PATCH 018/104] [api]: Add exposure counter to Camera Capture Naming parameters --- .../api/cameras/CameraCaptureNamingFormatter.kt | 7 +++++++ .../nebulosa/api/cameras/CameraCaptureNamingType.kt | 3 ++- .../test/kotlin/CameraCaptureNamingFormatterTest.kt | 7 +++++++ .../nebulosa/common/concurrency/atomic/Incrementer.kt | 11 ++++++++--- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt index d6f62c006..fcd7da3eb 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt @@ -1,6 +1,7 @@ package nebulosa.api.cameras import nebulosa.api.calibration.CalibrationFrameService.Companion.frameType +import nebulosa.common.concurrency.atomic.Incrementer import nebulosa.fits.* import nebulosa.image.format.ReadableHeader import nebulosa.indi.device.camera.Camera @@ -14,6 +15,7 @@ import nebulosa.math.format import java.time.Clock import java.time.LocalDate import java.time.LocalTime +import kotlin.math.absoluteValue import kotlin.math.roundToInt data class CameraCaptureNamingFormatter( @@ -23,6 +25,7 @@ data class CameraCaptureNamingFormatter( @JvmField internal val focuser: Focuser? = null, @JvmField internal val rotator: Rotator? = null, @JvmField internal val clock: Clock = Clock.systemDefaultZone(), + @JvmField internal val incrementer: Incrementer = Incrementer(), ) { fun format(text: String, header: ReadableHeader): String { @@ -75,6 +78,10 @@ data class CameraCaptureNamingFormatter( CameraCaptureNamingType.FOCUSER -> focuser?.name ?: camera.snoopedDevices.firstOrNull { it is Focuser }?.name CameraCaptureNamingType.WHEEL -> wheel?.name ?: camera.snoopedDevices.firstOrNull { it is FilterWheel }?.name CameraCaptureNamingType.ROTATOR -> rotator?.name ?: camera.snoopedDevices.firstOrNull { it is Rotator }?.name + CameraCaptureNamingType.N -> with(incrementer.increment()) { + val format = args.firstOrNull()?.toIntOrNull()?.absoluteValue ?: 4 + "%0${format}d".format(this) + } } } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt index c42520967..3ca357e7c 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt @@ -22,7 +22,8 @@ enum class CameraCaptureNamingType(private vararg val alias: String) { MOUNT, FOCUSER, WHEEL, - ROTATOR; + ROTATOR, + N; companion object { diff --git a/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt b/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt index 2bb7dee39..2f604e987 100644 --- a/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt +++ b/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt @@ -118,6 +118,13 @@ class CameraCaptureNamingFormatterTest : StringSpec() { "rotator" { formatter.format("[rotator]", header) shouldBe "Rotator Simulator" } + "n" { + formatter.format("[n]", header) shouldBe "0001" + formatter.format("[n:1]", header) shouldBe "2" + formatter.format("[n:2]", header) shouldBe "03" + formatter.format("[n:3]", header) shouldBe "004" + formatter.format("[n:6]", header) shouldBe "000005" + } "light" { with(header.clone()) { add("FRAME", "Light") diff --git a/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/atomic/Incrementer.kt b/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/atomic/Incrementer.kt index 981bd1d65..b79f9cb25 100644 --- a/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/atomic/Incrementer.kt +++ b/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/atomic/Incrementer.kt @@ -2,16 +2,19 @@ package nebulosa.common.concurrency.atomic import nebulosa.common.Resettable import java.util.concurrent.atomic.AtomicLong +import java.util.function.Supplier -class Incrementer(initialValue: Long = 0L) : Number(), Resettable { +class Incrementer(private val initialValue: Long = 0L) : Number(), Supplier, Resettable { private val incrementer = AtomicLong(initialValue) fun increment() = incrementer.incrementAndGet() - override fun reset() = incrementer.set(0) + override fun reset() = reset(initialValue) - fun get() = incrementer.get() + fun reset(value: Long) = incrementer.set(value) + + override fun get() = incrementer.get() override fun toByte() = toLong().toByte() @@ -24,4 +27,6 @@ class Incrementer(initialValue: Long = 0L) : Number(), Resettable { override fun toLong() = get() override fun toShort() = toLong().toShort() + + override fun toString() = "Incrementer(value=${get()})" } From 164b8dea05c6ad4113207c5349b6a5308336ddd5 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 6 Jul 2024 19:42:20 -0300 Subject: [PATCH 019/104] [api][desktop]: Fix Camera Capture naming --- .../nebulosa/api/cameras/CameraCaptureNamingFormatter.kt | 4 ++-- .../kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt | 4 ++-- api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt | 7 +++++-- desktop/src/app/camera/camera.component.html | 6 +++--- desktop/src/shared/types/settings.types.ts | 2 +- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt index fcd7da3eb..6b8a8a0a7 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt @@ -38,7 +38,7 @@ data class CameraCaptureNamingFormatter( } else { val groupValues = m.groups.mapNotNull { it?.value?.ifBlank { null } } val arguments = if (groupValues.size > 2) groupValues.subList(2, groupValues.size) else emptyList() - type.replaceWith(header, arguments)?.ifBlank { null } ?: value + type.replaceWith(header, arguments)?.ifBlank { null } ?: "" } }.replace(ILLEGAL_CHARS_REGEX, "") } @@ -95,6 +95,6 @@ data class CameraCaptureNamingFormatter( const val FLAT_FORMAT = "[camera]_[type]_[filter]_[width]_[height]_[bin]" const val DARK_FORMAT = "[camera]_[type]_[width]_[height]_[exp]_[bin]_[gain]" const val BIAS_FORMAT = "[camera]_[type]_[width]_[height]_[bin]_[gain]" - const val LIGHT_FORMAT = "[camera]_[type]_[year][month][day][hour][min][sec][ms]_[width]_[height]_[exp]_[bin]_[gain]" + const val LIGHT_FORMAT = "[camera]_[type]_[year:2][month][day][hour][min][sec][ms]_[filter]_[width]_[height]_[exp]_[bin]_[gain]" } } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt index 3ca357e7c..eb018cc9d 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingType.kt @@ -13,8 +13,8 @@ enum class CameraCaptureNamingType(private vararg val alias: String) { FILTER, GAIN, BIN, - WIDTH, - HEIGHT, + WIDTH("w"), + HEIGHT("h"), TEMP("temperature"), RA, DEC, diff --git a/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt b/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt index 2f604e987..645d7a7f0 100644 --- a/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt +++ b/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt @@ -89,9 +89,11 @@ class CameraCaptureNamingFormatterTest : StringSpec() { } "width" { formatter.format("[width]", header) shouldBe "1280" + formatter.format("[w]", header) shouldBe "1280" } "height" { formatter.format("[height]", header) shouldBe "1024" + formatter.format("[h]", header) shouldBe "1024" } "temperature" { formatter.format("[temp]", header) shouldBe "-15" @@ -128,7 +130,7 @@ class CameraCaptureNamingFormatterTest : StringSpec() { "light" { with(header.clone()) { add("FRAME", "Light") - formatter.format(LIGHT_FORMAT, this) shouldBe "Camera Simulator_LIGHT_20240704173736369_1280_1024_1500000_2_80" + formatter.format(LIGHT_FORMAT, this) shouldBe "Camera Simulator_LIGHT_240704173736369_Red_1280_1024_1500000_2_80" } } "dark" { @@ -155,7 +157,8 @@ class CameraCaptureNamingFormatterTest : StringSpec() { "not found" { with(header.clone()) { delete(FitsKeyword.RA) - formatter.format("[ra]", this) shouldBe "ra" + formatter.format("[ra]", this) shouldBe "" + formatter.format("[ra]_[ra]", this) shouldBe "_" } } "illegal chars" { diff --git a/desktop/src/app/camera/camera.component.html b/desktop/src/app/camera/camera.component.html index 26b83fe48..3fdeabac0 100644 --- a/desktop/src/app/camera/camera.component.html +++ b/desktop/src/app/camera/camera.component.html @@ -514,7 +514,7 @@ [draggable]="true" [(visible)]="dither.showDialog" [modal]="true" - [style]="{ width: '80vw', maxWidth: '260px' }"> + [style]="{ width: '80vw', maxWidth: '320px' }">
Enabled @@ -569,7 +569,7 @@ [draggable]="true" [(visible)]="liveStacking.showDialog" [modal]="true" - [style]="{ width: '80vw', maxWidth: '280px' }"> + [style]="{ width: '80vw', maxWidth: '320px' }">
Live Stacking @@ -641,7 +641,7 @@ [(visible)]="namingFormat.showDialog" [modal]="true" header="Naming Format" - [style]="{ width: '80vw', maxWidth: '280px' }"> + [style]="{ width: '80vw', maxWidth: '320px' }">
diff --git a/desktop/src/shared/types/settings.types.ts b/desktop/src/shared/types/settings.types.ts index 076cabfc0..2a0d19960 100644 --- a/desktop/src/shared/types/settings.types.ts +++ b/desktop/src/shared/types/settings.types.ts @@ -48,7 +48,7 @@ export interface CameraCaptureNamingFormat { } export const DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT: CameraCaptureNamingFormat = { - light: '[camera]_[type]_[year][month][day][hour][min][sec][ms]_[width]_[height]_[exp]_[bin]_[gain]', + light: '[camera]_[type]_[year:2][month][day][hour][min][sec][ms]_[filter]_[width]_[height]_[exp]_[bin]_[gain]', dark: '[camera]_[type]_[width]_[height]_[exp]_[bin]_[gain]', flat: '[camera]_[type]_[filter]_[width]_[height]_[bin]', bias: '[camera]_[type]_[width]_[height]_[bin]_[gain]', From 7df0ef13750e95cdc7dd217cf1894428dda22fc9 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 6 Jul 2024 19:42:46 -0300 Subject: [PATCH 020/104] [desktop]: Update Camera Capture request on camera update --- desktop/src/app/sequencer/sequencer.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop/src/app/sequencer/sequencer.component.ts b/desktop/src/app/sequencer/sequencer.component.ts index 60f08f787..df65d070b 100644 --- a/desktop/src/app/sequencer/sequencer.component.ts +++ b/desktop/src/app/sequencer/sequencer.component.ts @@ -180,6 +180,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable if (camera) { ngZone.run(() => { Object.assign(camera, event.device) + this.updateEntriesFromCamera(this.camera) }) } }) From 0d70f6e0e7a24c25de5b121c4241ec135e020abd Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 6 Jul 2024 20:03:04 -0300 Subject: [PATCH 021/104] [desktop]: Fix snoop devices sent on Sequencer --- desktop/src/app/sequencer/sequencer.component.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/src/app/sequencer/sequencer.component.ts b/desktop/src/app/sequencer/sequencer.component.ts index df65d070b..e9fef167b 100644 --- a/desktop/src/app/sequencer/sequencer.component.ts +++ b/desktop/src/app/sequencer/sequencer.component.ts @@ -463,12 +463,12 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable savePlan() { const sequencerPreference = this.preference.sequencerPreference.get() sequencerPreference.savedPath = this.savedPath + this.plan.camera = this.camera?.id + this.plan.mount = this.mount?.id + this.plan.wheel = this.wheel?.id + this.plan.focuser = this.focuser?.id + this.plan.rotator = this.rotator?.id Object.assign(sequencerPreference.plan, this.plan) - sequencerPreference.plan.camera = this.camera?.id - sequencerPreference.plan.mount = this.mount?.id - sequencerPreference.plan.wheel = this.wheel?.id - sequencerPreference.plan.focuser = this.focuser?.id - sequencerPreference.plan.rotator = this.rotator?.id this.preference.sequencerPreference.set(sequencerPreference) } From 488eac7abdcae150084ea4b811fe16248d18dff8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:13:59 +0000 Subject: [PATCH 022/104] [desktop]: Bump @types/node in /desktop in the types group Bumps the types group in /desktop with 1 update: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `@types/node` from 20.14.9 to 20.14.10 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: types ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 8 ++++---- desktop/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 618898793..2d0b6ef9e 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -45,7 +45,7 @@ "@eslint/js": "9.6.0", "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", - "@types/node": "20.14.9", + "@types/node": "20.14.10", "electron": "31.1.0", "electron-builder": "24.13.3", "eslint": "8.57.0", @@ -5042,9 +5042,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.14.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz", - "integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==", + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" diff --git a/desktop/package.json b/desktop/package.json index bde10becc..85a10d154 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -69,7 +69,7 @@ "@eslint/js": "9.6.0", "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", - "@types/node": "20.14.9", + "@types/node": "20.14.10", "electron": "31.1.0", "electron-builder": "24.13.3", "eslint": "8.57.0", From 15ecd4b5d4ec50cdcfe5a29057707b7084dd27e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:13:44 +0000 Subject: [PATCH 023/104] [desktop]: Bump the angular group in /desktop with 13 updates Bumps the angular group in /desktop with 13 updates: | Package | From | To | | --- | --- | --- | | [@angular/animations](https://github.com/angular/angular/tree/HEAD/packages/animations) | `18.0.5` | `18.1.0` | | [@angular/cdk](https://github.com/angular/components) | `18.0.5` | `18.1.0` | | [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `18.0.5` | `18.1.0` | | [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `18.0.5` | `18.1.0` | | [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `18.0.5` | `18.1.0` | | [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `18.0.5` | `18.1.0` | | [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `18.0.5` | `18.1.0` | | [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `18.0.5` | `18.1.0` | | [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `18.0.5` | `18.1.0` | | [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `18.0.6` | `18.1.0` | | [@angular/cli](https://github.com/angular/angular-cli) | `18.0.6` | `18.1.0` | | [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `18.0.5` | `18.1.0` | | [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) | `18.0.5` | `18.1.0` | Updates `@angular/animations` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.1.0/packages/animations) Updates `@angular/cdk` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/components/releases) - [Changelog](https://github.com/angular/components/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/components/compare/18.0.5...18.1.0) Updates `@angular/common` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.1.0/packages/common) Updates `@angular/compiler` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.1.0/packages/compiler) Updates `@angular/core` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.1.0/packages/core) Updates `@angular/forms` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.1.0/packages/forms) Updates `@angular/platform-browser` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.1.0/packages/platform-browser) Updates `@angular/platform-browser-dynamic` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.1.0/packages/platform-browser-dynamic) Updates `@angular/router` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.1.0/packages/router) Updates `@angular-devkit/build-angular` from 18.0.6 to 18.1.0 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/18.0.6...18.1.0) Updates `@angular/cli` from 18.0.6 to 18.1.0 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/18.0.6...18.1.0) Updates `@angular/compiler-cli` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.1.0/packages/compiler-cli) Updates `@angular/language-service` from 18.0.5 to 18.1.0 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/18.1.0/packages/language-service) --- updated-dependencies: - dependency-name: "@angular/animations" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/cdk" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/common" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/compiler" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/core" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/forms" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/platform-browser" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/platform-browser-dynamic" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/router" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-devkit/build-angular" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/cli" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/compiler-cli" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/language-service" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 10551 ++++++++++++++++++------------------ desktop/package.json | 26 +- 2 files changed, 5413 insertions(+), 5164 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 2d0b6ef9e..beb2973e1 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -10,15 +10,15 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@angular/animations": "18.0.5", - "@angular/cdk": "18.0.5", - "@angular/common": "18.0.5", - "@angular/compiler": "18.0.5", - "@angular/core": "18.0.5", - "@angular/forms": "18.0.5", - "@angular/platform-browser": "18.0.5", - "@angular/platform-browser-dynamic": "18.0.5", - "@angular/router": "18.0.5", + "@angular/animations": "18.1.0", + "@angular/cdk": "18.1.0", + "@angular/common": "18.1.0", + "@angular/compiler": "18.1.0", + "@angular/core": "18.1.0", + "@angular/forms": "18.1.0", + "@angular/platform-browser": "18.1.0", + "@angular/platform-browser-dynamic": "18.1.0", + "@angular/router": "18.1.0", "@mdi/font": "7.4.47", "chart.js": "4.4.3", "chartjs-plugin-zoom": "2.0.1", @@ -38,10 +38,10 @@ }, "devDependencies": { "@angular-builders/custom-webpack": "18.0.0", - "@angular-devkit/build-angular": "18.0.6", - "@angular/cli": "18.0.6", - "@angular/compiler-cli": "18.0.5", - "@angular/language-service": "18.0.5", + "@angular-devkit/build-angular": "18.1.0", + "@angular/cli": "18.1.0", + "@angular/compiler-cli": "18.1.0", + "@angular/language-service": "18.1.0", "@eslint/js": "9.6.0", "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", @@ -109,12 +109,12 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1800.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1800.6.tgz", - "integrity": "sha512-VJ08XM9XR8d3ldXEMIeaiamBSvQqX+ucIKw73zubP37yFVAuvXriDOFskcouVUT0RxWXIZVcNxrgp2t3FE4F6w==", + "version": "0.1801.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1801.0.tgz", + "integrity": "sha512-iZa3J3CrZT6MKiHPw8ijgVwMyCMewCsP4xc75SetUwF/yuqRUHygALs5jJVZQFQjSFUrkg9gqXa1cCjFDwpT8A==", "dev": true, "dependencies": { - "@angular-devkit/core": "18.0.6", + "@angular-devkit/core": "18.1.0", "rxjs": "7.8.1" }, "engines": { @@ -124,71 +124,70 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.0.6.tgz", - "integrity": "sha512-87ynzPHHYr+iL3GsBgJWVlChMuubQgiXYWf2JLXRLNGduSOdoa18vxT1jU11b6C9G+avDSnMbtq+sk841pT1kg==", + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.1.0.tgz", + "integrity": "sha512-j/YrEFuEX90Pcyzjew6EcCoxT+Va0AlGjgWyVIuStNTEsCx9Vp7T2tS7w6LL1t6leM7gzf8f/ZKtvRPnAsWdQg==", "dev": true, "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1800.6", - "@angular-devkit/build-webpack": "0.1800.6", - "@angular-devkit/core": "18.0.6", - "@angular/build": "18.0.6", - "@babel/core": "7.24.5", - "@babel/generator": "7.24.5", - "@babel/helper-annotate-as-pure": "7.22.5", - "@babel/helper-split-export-declaration": "7.24.5", - "@babel/plugin-transform-async-generator-functions": "7.24.3", - "@babel/plugin-transform-async-to-generator": "7.24.1", - "@babel/plugin-transform-runtime": "7.24.3", - "@babel/preset-env": "7.24.5", - "@babel/runtime": "7.24.5", + "@angular-devkit/architect": "0.1801.0", + "@angular-devkit/build-webpack": "0.1801.0", + "@angular-devkit/core": "18.1.0", + "@angular/build": "18.1.0", + "@babel/core": "7.24.7", + "@babel/generator": "7.24.7", + "@babel/helper-annotate-as-pure": "7.24.7", + "@babel/helper-split-export-declaration": "7.24.7", + "@babel/plugin-transform-async-generator-functions": "7.24.7", + "@babel/plugin-transform-async-to-generator": "7.24.7", + "@babel/plugin-transform-runtime": "7.24.7", + "@babel/preset-env": "7.24.7", + "@babel/runtime": "7.24.7", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "18.0.6", + "@ngtools/webpack": "18.1.0", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.19", "babel-loader": "9.1.3", "browserslist": "^4.21.5", - "copy-webpack-plugin": "11.0.0", - "critters": "0.0.22", - "css-loader": "7.1.1", - "esbuild-wasm": "0.21.3", + "copy-webpack-plugin": "12.0.2", + "critters": "0.0.24", + "css-loader": "7.1.2", + "esbuild-wasm": "0.21.5", "fast-glob": "3.3.2", "http-proxy-middleware": "3.0.0", - "https-proxy-agent": "7.0.4", - "inquirer": "9.2.22", + "https-proxy-agent": "7.0.5", "istanbul-lib-instrument": "6.0.2", - "jsonc-parser": "3.2.1", + "jsonc-parser": "3.3.1", "karma-source-map-support": "1.4.0", "less": "4.2.0", "less-loader": "12.2.0", "license-webpack-plugin": "4.0.2", - "loader-utils": "3.2.1", + "loader-utils": "3.3.1", "magic-string": "0.30.10", "mini-css-extract-plugin": "2.9.0", "mrmime": "2.0.0", - "open": "8.4.2", + "open": "10.1.0", "ora": "5.4.1", "parse5-html-rewriting-stream": "7.0.0", "picomatch": "4.0.2", - "piscina": "4.5.0", + "piscina": "4.6.1", "postcss": "8.4.38", "postcss-loader": "8.1.1", "resolve-url-loader": "5.0.0", "rxjs": "7.8.1", - "sass": "1.77.2", + "sass": "1.77.6", "sass-loader": "14.2.1", "semver": "7.6.2", "source-map-loader": "5.0.0", "source-map-support": "0.5.21", - "terser": "5.31.0", + "terser": "5.29.2", "tree-kill": "1.2.2", - "tslib": "2.6.2", - "undici": "6.18.0", - "vite": "5.2.11", + "tslib": "2.6.3", + "undici": "6.19.2", + "vite": "5.3.2", "watchpack": "2.4.1", - "webpack": "5.91.0", + "webpack": "5.92.1", "webpack-dev-middleware": "7.2.1", "webpack-dev-server": "5.0.4", "webpack-merge": "5.10.0", @@ -200,7 +199,7 @@ "yarn": ">= 1.13.0" }, "optionalDependencies": { - "esbuild": "0.21.3" + "esbuild": "0.21.5" }, "peerDependencies": { "@angular/compiler-cli": "^18.0.0", @@ -215,7 +214,7 @@ "ng-packagr": "^18.0.0", "protractor": "^7.0.0", "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.4 <5.5" + "typescript": ">=5.4 <5.6" }, "peerDependenciesMeta": { "@angular/localize": { @@ -253,244 +252,38 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/webpack": { - "version": "5.91.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", - "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.16.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/build-webpack": { - "version": "0.1800.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1800.6.tgz", - "integrity": "sha512-hIQ4FtcxsNVEHlKZVFIfFiFKNNxEdacS/Nsy/YJ0AU6EOkUd6AOVsc539GniJQOk4RBNKS9wOlJBtF/2g1sjhQ==", - "dev": true, - "dependencies": { - "@angular-devkit/architect": "0.1800.6", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "webpack": "^5.30.0", - "webpack-dev-server": "^5.0.2" - } - }, - "node_modules/@angular-devkit/core": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.0.6.tgz", - "integrity": "sha512-07U0S2fpUBjkg4k6uAEQQHSFfearyHGrONlgkxAlk7HWM5jfHp/8D2+ui1OFZgXpSAHF2C5gULbze/2o9ZNgag==", - "dev": true, - "dependencies": { - "ajv": "8.13.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.2.1", - "picomatch": "4.0.2", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/schematics": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.0.6.tgz", - "integrity": "sha512-lzjPp8qWV4p3reyKZ2QRF7rQYc17WMCR61vKldQJBuJrS30yx87x22ASn4BCAo7kKKRv8gXJmoXjCPDFlcfRsw==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "18.0.6", - "jsonc-parser": "3.2.1", - "magic-string": "0.30.10", - "ora": "5.4.1", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/animations": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.0.5.tgz", - "integrity": "sha512-RYwlS+4I33beAWdzFFmaDPqXZN+r66qPzzMOk9LQguwF76eBJbykHniODalSLvjrY6Iz7CULavByYNpzq2TT7A==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/core": "18.0.5" - } - }, - "node_modules/@angular/build": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.0.6.tgz", - "integrity": "sha512-W6S1sx00D4pd7qDIyzPMNFmw8d783+/Aknl+2cUrYlJqw0Oan1Bt6mXVg48Jwxr0hVsovoNZXSRFXXI5hvW8ZA==", + "node_modules/@angular-devkit/build-angular/node_modules/@angular/build": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.1.0.tgz", + "integrity": "sha512-4yLrGqMDoNBis2Z4s8F3wSqlB2XLtwy/10tREBk9xVaCojERiwDvtHqzbMeHqD6ZMGDFtdhI12q8FT5jZVUmAw==", "dev": true, "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1800.6", - "@babel/core": "7.24.5", - "@babel/helper-annotate-as-pure": "7.22.5", - "@babel/helper-split-export-declaration": "7.24.5", + "@angular-devkit/architect": "0.1801.0", + "@babel/core": "7.24.7", + "@babel/helper-annotate-as-pure": "7.24.7", + "@babel/helper-split-export-declaration": "7.24.7", + "@babel/plugin-syntax-import-attributes": "7.24.7", + "@inquirer/confirm": "3.1.11", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "browserslist": "^4.23.0", - "critters": "0.0.22", - "esbuild": "0.21.3", + "critters": "0.0.24", + "esbuild": "0.21.5", "fast-glob": "3.3.2", - "https-proxy-agent": "7.0.4", - "inquirer": "9.2.22", - "lmdb": "3.0.8", + "https-proxy-agent": "7.0.5", + "lmdb": "3.0.12", "magic-string": "0.30.10", "mrmime": "2.0.0", "ora": "5.4.1", "parse5-html-rewriting-stream": "7.0.0", "picomatch": "4.0.2", - "piscina": "4.5.0", - "sass": "1.77.2", + "piscina": "4.6.1", + "rollup": "4.18.0", + "sass": "1.77.6", "semver": "7.6.2", - "undici": "6.18.0", - "vite": "5.2.11", + "undici": "6.19.2", + "vite": "5.3.2", "watchpack": "2.4.1" }, "engines": { @@ -506,7 +299,7 @@ "less": "^4.2.0", "postcss": "^8.4.0", "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.4 <5.5" + "typescript": ">=5.4 <5.6" }, "peerDependenciesMeta": { "@angular/localize": { @@ -529,181 +322,466 @@ } } }, - "node_modules/@angular/cdk": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.0.5.tgz", - "integrity": "sha512-Yf94Udxip8xjVIJlxwh80h6fUpX5JFcBv3FCFer7DU/YzWdoTL+BTIYF8og+NjlDRt1nSbTxdyU2LVI0rTVkpg==", - "dependencies": { - "tslib": "^2.3.0" - }, - "optionalDependencies": { - "parse5": "^7.1.2" - }, - "peerDependencies": { - "@angular/common": "^18.0.0 || ^19.0.0", - "@angular/core": "^18.0.0 || ^19.0.0", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/cli": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.0.6.tgz", - "integrity": "sha512-T0ii60zVqBzxtC4jusKkR5YOdubP5+n9SPd8gm9Dat4jUeePc5O5+6qmjpFXZlibxLNSVIm89hLBb7/rMJIkIg==", + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@angular-devkit/architect": "0.1800.6", - "@angular-devkit/core": "18.0.6", - "@angular-devkit/schematics": "18.0.6", - "@schematics/angular": "18.0.6", - "@yarnpkg/lockfile": "1.1.0", - "ansi-colors": "4.1.3", - "ini": "4.1.2", - "inquirer": "9.2.22", - "jsonc-parser": "3.2.1", - "npm-package-arg": "11.0.2", - "npm-pick-manifest": "9.0.1", - "ora": "5.4.1", - "pacote": "18.0.6", - "resolve": "1.22.8", - "semver": "7.6.2", - "symbol-observable": "4.0.0", - "yargs": "17.7.2" - }, - "bin": { - "ng": "bin/ng.js" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@angular/common": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.0.5.tgz", - "integrity": "sha512-yItVQSu+Rx8gthWJDTOHwbzItY8/lqmmmYA1RMex0u3GkJoX3/3TZSGXbbBXl8GH8vmQOfp9yj3C02JmlwldRg==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/core": "18.0.5", - "rxjs": "^6.5.3 || ^7.4.0" - } + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@angular/compiler": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.0.5.tgz", - "integrity": "sha512-U1/qjNDjxMukXwQrJZjmr87KVxQmHbD7fxVlg0+qafHLe+YDuCtyOfQSGEZrWhwktxvAYZbl3FK+m3Hnk/D3Nw==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/core": "18.0.5" - }, - "peerDependenciesMeta": { - "@angular/core": { - "optional": true - } + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" } }, - "node_modules/@angular/compiler-cli": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.0.5.tgz", - "integrity": "sha512-aFKDDTsRmc691EkNRj9OkrKNXDOaHdXB42MyUrj3WwJIJFMnSY/UDf6h+CRVF0U+CITszFyWhmeHQRA/3mJWNg==", + "node_modules/@angular-devkit/build-angular/node_modules/terser": { + "version": "5.29.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz", + "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==", "dev": true, "dependencies": { - "@babel/core": "7.24.7", - "@jridgewell/sourcemap-codec": "^1.4.14", - "chokidar": "^3.0.0", - "convert-source-map": "^1.5.1", - "reflect-metadata": "^0.2.0", - "semver": "^7.0.0", - "tslib": "^2.3.0", - "yargs": "^17.2.1" + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" }, "bin": { - "ng-xi18n": "bundles/src/bin/ng_xi18n.js", - "ngc": "bundles/src/bin/ngc.js", - "ngcc": "bundles/ngcc/index.js" + "terser": "bin/terser" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=10" + } + }, + "node_modules/@angular-devkit/build-webpack": { + "version": "0.1801.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1801.0.tgz", + "integrity": "sha512-EnkkhE4tVOk3lU5/bt8hNCQCJMefcpU5E4jChRmFu+m0OtKK2kax3hjPTUVwcpbjwpG5rO7J/U5yIhCY9afXKw==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1801.0", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" }, "peerDependencies": { - "@angular/compiler": "18.0.5", - "typescript": ">=5.4 <5.5" + "webpack": "^5.30.0", + "webpack-dev-server": "^5.0.2" } }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", - "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", + "node_modules/@angular-devkit/core": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.1.0.tgz", + "integrity": "sha512-6eXQDzHZCbpSMLv9Ohl+1QyLVDmGEXpuuHz3y64LfUTP0aEiBaxk96FjLXIxzJ4f2pbbW2XHzc+yuboGToRA0w==", "dev": true, "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helpers": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" + "ajv": "8.16.0", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } } }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "node_modules/@angular-devkit/schematics": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.1.0.tgz", + "integrity": "sha512-BjrYutLfYFiPOSEcLBWCj3ENkwDn8gMfBSJesaBz7OrZBZGK5j0dVgBLIsGTP96TKo4o4vszJQOvS4AtV6xMGg==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "18.1.0", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.10", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@angular/animations": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.1.0.tgz", + "integrity": "sha512-K0BhvZ/SIVoGXZVuh1KOJDdgcGlHfFGMGrs58utndndAb+gYXReMfz4GR5cQs2OObH6TKmIOY2EH7Og1CY2tsw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/core": "18.1.0" + } + }, + "node_modules/@angular/cdk": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.1.0.tgz", + "integrity": "sha512-GWUyJQ7KdOS0WwQPp7UKnRd7lUKvOrMvktqNWfSxBy/VEdyEeKlXfghk6GQ4u1RXFZ2RU0m1KhX8rY9srYJOwA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "optionalDependencies": { + "parse5": "^7.1.2" + }, + "peerDependencies": { + "@angular/common": "^18.0.0 || ^19.0.0", + "@angular/core": "^18.0.0 || ^19.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/cli": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.1.0.tgz", + "integrity": "sha512-2E+b7S/736AOmxf5je9OWoPpgPY240TfJfFXwQiVvq/4KyC+ZR9lBrqRx72Xghn8nu3z8Q2BPZIXVGZppl0USQ==", "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1801.0", + "@angular-devkit/core": "18.1.0", + "@angular-devkit/schematics": "18.1.0", + "@inquirer/prompts": "5.0.7", + "@listr2/prompt-adapter-inquirer": "2.0.13", + "@schematics/angular": "18.1.0", + "@yarnpkg/lockfile": "1.1.0", + "ini": "4.1.3", + "jsonc-parser": "3.3.1", + "listr2": "8.2.3", + "npm-package-arg": "11.0.2", + "npm-pick-manifest": "9.0.1", + "pacote": "18.0.6", + "resolve": "1.22.8", + "semver": "7.6.2", + "symbol-observable": "4.0.0", + "yargs": "17.7.2" + }, "bin": { - "semver": "bin/semver.js" + "ng": "bin/ng.js" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, - "node_modules/@angular/compiler-cli/node_modules/@babel/generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", - "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "node_modules/@angular/common": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.1.0.tgz", + "integrity": "sha512-noHDLarQSCZZh7hyNd0HR61Fut+q4QCVq9qc/jKPglfbV/6nPujQSmSpT+rNJlNuBOrCLuvH/CNBNbiqii+x3g==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/core": "18.1.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/compiler": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.1.0.tgz", + "integrity": "sha512-JRQzVTeJGSfRLY+dx+gwu/hPQVB8K+5pW12Z42M9x/HBgGW4in0cO2zHkeQPvImqm0nak82Us1Hyf5C+qTlMMQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/core": "18.1.0" + }, + "peerDependenciesMeta": { + "@angular/core": { + "optional": true + } + } + }, + "node_modules/@angular/compiler-cli": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.1.0.tgz", + "integrity": "sha512-BBsogLPJwxkPh7f8RVHsxyyqNE8XpHbAanjB5fAwnU4W6Sw1kR5rFzkeZM3xaRm2MDiC8DovIl6hlf+s/mKYOw==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "@babel/core": "7.24.7", + "@jridgewell/sourcemap-codec": "^1.4.14", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "reflect-metadata": "^0.2.0", + "semver": "^7.0.0", + "tslib": "^2.3.0", + "yargs": "^17.2.1" + }, + "bin": { + "ng-xi18n": "bundles/src/bin/ng_xi18n.js", + "ngc": "bundles/src/bin/ngc.js", + "ngcc": "bundles/ngcc/index.js" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/compiler": "18.1.0", + "typescript": ">=5.4 <5.6" } }, "node_modules/@angular/core": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.0.5.tgz", - "integrity": "sha512-0UuL+aMMWGYksz09YBsiHq1li7GmL8obB3IC3T5MwDqnn7FGRUBfBUOZEkM6B+pwgg+RAtNdJkbCfbh1z74bFQ==", + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.1.0.tgz", + "integrity": "sha512-/57/s7CD/0CwlN+3FlhVmx7ypCWXjKi5UKtnlBAUg0D1denIf6ADxwTHFZABYZcYBqOTJgeQUtUw9u/A+0CIlg==", "dependencies": { "tslib": "^2.3.0" }, @@ -716,9 +794,9 @@ } }, "node_modules/@angular/forms": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.0.5.tgz", - "integrity": "sha512-nO7bN+nO2/czgKSvPx6ewqpfb8xXOyns06uovWpAXSH4jYoiZ6CHTHhOKrOL/3SRkhUV9u+EUXTTAOSBkS+OBA==", + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.1.0.tgz", + "integrity": "sha512-m+7m9wa+n5dEacd458eSZsZTz0B+HbOtr7/uqM0YTMQaPrhwl1epG5Y103mB6yr00JiJcLNlPLjP888cHFjldQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -726,25 +804,25 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.0.5", - "@angular/core": "18.0.5", - "@angular/platform-browser": "18.0.5", + "@angular/common": "18.1.0", + "@angular/core": "18.1.0", + "@angular/platform-browser": "18.1.0", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.0.5.tgz", - "integrity": "sha512-ahZnsUk8q/4k+okP9hBcfWRiOiMximSAI7Vq5M/fe9cezykt8cWEzxgRoduTvDKoQPqcRl0nHlDYju2zkXcU6g==", + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.1.0.tgz", + "integrity": "sha512-sS9G/ZdS4CVhbClunpur8lZDP2cNTMFiAaxsF3sWg+HTSbQm7v57ypQsainSzoD30YxzoSCvyk18unDAO1vYUA==", "dev": true, "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0" } }, "node_modules/@angular/platform-browser": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.0.5.tgz", - "integrity": "sha512-hBKaGz7dhsjNhD0aWB8G2/YZQ/MaBhzFIQSAZMPs2ccAqH1Jx772/Y11k57seA3VaPpnL8WZ1apOSJgALUJ//w==", + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.1.0.tgz", + "integrity": "sha512-jCmxthiI4Zef54crckNht60xwfIsuciGeyZvb7SsXna2maLW9fA4uz1VhZqIWTiBnHwNynVlyfBX3/jBD7S9+g==", "dependencies": { "tslib": "^2.3.0" }, @@ -752,9 +830,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "18.0.5", - "@angular/common": "18.0.5", - "@angular/core": "18.0.5" + "@angular/animations": "18.1.0", + "@angular/common": "18.1.0", + "@angular/core": "18.1.0" }, "peerDependenciesMeta": { "@angular/animations": { @@ -763,9 +841,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.0.5.tgz", - "integrity": "sha512-i8CXojKcjsKzD2JR2clIisqavlHCW1jw+F2hJVrf/JR9iu6kVpGpZOqb3yYHoQCsPa7hUzQnn0ewYwBvlWsDmw==", + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.1.0.tgz", + "integrity": "sha512-D/wuOQf+gULld9DVEzn2Lw3WbTyAYf/sp3DC5k83O+DQsG3eAIsVkt0zdE+U3DrDYsiWg8M3X+ioi3ouqK0mNg==", "dependencies": { "tslib": "^2.3.0" }, @@ -773,16 +851,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.0.5", - "@angular/compiler": "18.0.5", - "@angular/core": "18.0.5", - "@angular/platform-browser": "18.0.5" + "@angular/common": "18.1.0", + "@angular/compiler": "18.1.0", + "@angular/core": "18.1.0", + "@angular/platform-browser": "18.1.0" } }, "node_modules/@angular/router": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.0.5.tgz", - "integrity": "sha512-GmdzD5FZYPKCGP6mV3AZraAU6czfGcjjCym6mIsdJr3DyMwnQSwaaHAu8qlQbPDVfsP+gKVSPh1JxI1lzzarLA==", + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.1.0.tgz", + "integrity": "sha512-dl2cSxZkl4we+rWMxdm123TZzlor6yxwNFI2yT7b6DP2i+rXaaHBSSPet0ASp+UX6djz+Osr56Bifs6wi4rhiQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -790,9 +868,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.0.5", - "@angular/core": "18.0.5", - "@angular/platform-browser": "18.0.5", + "@angular/common": "18.1.0", + "@angular/core": "18.1.0", + "@angular/platform-browser": "18.1.0", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -819,21 +897,21 @@ } }, "node_modules/@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@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", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -864,12 +942,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", - "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.5", + "@babel/types": "^7.24.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -879,12 +957,12 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -951,30 +1029,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -1001,18 +1055,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -1120,18 +1162,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", @@ -1170,18 +1200,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-replace-supers": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", @@ -1226,12 +1244,12 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "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==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1646,14 +1664,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz", - "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", + "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -1664,14 +1682,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", - "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-remap-async-to-generator": "^7.22.20" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1765,30 +1783,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", @@ -2240,18 +2234,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-property-literals": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", @@ -2299,13 +2281,13 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz", - "integrity": "sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", + "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.10.1", "babel-plugin-polyfill-regenerator": "^0.6.1", @@ -2467,27 +2449,27 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.5.tgz", - "integrity": "sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.5", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.7.tgz", + "integrity": "sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.1", - "@babel/plugin-syntax-import-attributes": "^7.24.1", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -2499,54 +2481,54 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.1", - "@babel/plugin-transform-async-generator-functions": "^7.24.3", - "@babel/plugin-transform-async-to-generator": "^7.24.1", - "@babel/plugin-transform-block-scoped-functions": "^7.24.1", - "@babel/plugin-transform-block-scoping": "^7.24.5", - "@babel/plugin-transform-class-properties": "^7.24.1", - "@babel/plugin-transform-class-static-block": "^7.24.4", - "@babel/plugin-transform-classes": "^7.24.5", - "@babel/plugin-transform-computed-properties": "^7.24.1", - "@babel/plugin-transform-destructuring": "^7.24.5", - "@babel/plugin-transform-dotall-regex": "^7.24.1", - "@babel/plugin-transform-duplicate-keys": "^7.24.1", - "@babel/plugin-transform-dynamic-import": "^7.24.1", - "@babel/plugin-transform-exponentiation-operator": "^7.24.1", - "@babel/plugin-transform-export-namespace-from": "^7.24.1", - "@babel/plugin-transform-for-of": "^7.24.1", - "@babel/plugin-transform-function-name": "^7.24.1", - "@babel/plugin-transform-json-strings": "^7.24.1", - "@babel/plugin-transform-literals": "^7.24.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", - "@babel/plugin-transform-member-expression-literals": "^7.24.1", - "@babel/plugin-transform-modules-amd": "^7.24.1", - "@babel/plugin-transform-modules-commonjs": "^7.24.1", - "@babel/plugin-transform-modules-systemjs": "^7.24.1", - "@babel/plugin-transform-modules-umd": "^7.24.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.24.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", - "@babel/plugin-transform-numeric-separator": "^7.24.1", - "@babel/plugin-transform-object-rest-spread": "^7.24.5", - "@babel/plugin-transform-object-super": "^7.24.1", - "@babel/plugin-transform-optional-catch-binding": "^7.24.1", - "@babel/plugin-transform-optional-chaining": "^7.24.5", - "@babel/plugin-transform-parameters": "^7.24.5", - "@babel/plugin-transform-private-methods": "^7.24.1", - "@babel/plugin-transform-private-property-in-object": "^7.24.5", - "@babel/plugin-transform-property-literals": "^7.24.1", - "@babel/plugin-transform-regenerator": "^7.24.1", - "@babel/plugin-transform-reserved-words": "^7.24.1", - "@babel/plugin-transform-shorthand-properties": "^7.24.1", - "@babel/plugin-transform-spread": "^7.24.1", - "@babel/plugin-transform-sticky-regex": "^7.24.1", - "@babel/plugin-transform-template-literals": "^7.24.1", - "@babel/plugin-transform-typeof-symbol": "^7.24.5", - "@babel/plugin-transform-unicode-escapes": "^7.24.1", - "@babel/plugin-transform-unicode-property-regex": "^7.24.1", - "@babel/plugin-transform-unicode-regex": "^7.24.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.1", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.24.7", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.7", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.7", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.10.4", @@ -2591,9 +2573,9 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", - "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", + "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -2637,33 +2619,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", - "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/types": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", @@ -2959,639 +2914,1072 @@ "plist": "^3.0.4" }, "engines": { - "node": ">=8.6" + "node": ">=8.6" + } + }, + "node_modules/@electron/universal/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/universal/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/universal/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@electron/universal/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@electron/universal/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/@electron/universal/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@electron/universal/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/@electron/universal/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 10.0.0" + "node": ">=12" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.3.tgz", - "integrity": "sha512-yTgnwQpFVYfvvo4SvRFB0SwrW8YjOxEoT7wfMT7Ol5v7v5LDNvSGo67aExmxOb87nQNeWPVvaGBNfQ7BXcrZ9w==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", "cpu": [ - "ppc64" + "s390x" ], "dev": true, "optional": true, "os": [ - "aix" + "linux" ], "engines": { "node": ">=12" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.3.tgz", - "integrity": "sha512-bviJOLMgurLJtF1/mAoJLxDZDL6oU5/ztMHnJQRejbJrSc9FFu0QoUoFhvi6qSKJEw9y5oGyvr9fuDtzJ30rNQ==", + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", "cpu": [ - "arm" + "x64" ], "dev": true, "optional": true, "os": [ - "android" + "linux" ], "engines": { "node": ">=12" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.3.tgz", - "integrity": "sha512-c+ty9necz3zB1Y+d/N+mC6KVVkGUUOcm4ZmT5i/Fk5arOaY3i6CA3P5wo/7+XzV8cb4GrI/Zjp8NuOQ9Lfsosw==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", "cpu": [ - "arm64" + "x64" ], "dev": true, "optional": true, "os": [ - "android" + "netbsd" ], "engines": { "node": ">=12" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.3.tgz", - "integrity": "sha512-JReHfYCRK3FVX4Ra+y5EBH1b9e16TV2OxrPAvzMsGeES0X2Ndm9ImQRI4Ket757vhc5XBOuGperw63upesclRw==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ - "android" + "openbsd" ], "engines": { "node": ">=12" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.3.tgz", - "integrity": "sha512-U3fuQ0xNiAkXOmQ6w5dKpEvXQRSpHOnbw7gEfHCRXPeTKW9sBzVck6C5Yneb8LfJm0l6le4NQfkNPnWMSlTFUQ==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", "cpu": [ - "arm64" + "x64" ], "dev": true, "optional": true, "os": [ - "darwin" + "sunos" ], "engines": { "node": ">=12" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.3.tgz", - "integrity": "sha512-3m1CEB7F07s19wmaMNI2KANLcnaqryJxO1fXHUV5j1rWn+wMxdUYoPyO2TnAbfRZdi7ADRwJClmOwgT13qlP3Q==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, "os": [ - "darwin" + "win32" ], "engines": { "node": ">=12" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.3.tgz", - "integrity": "sha512-fsNAAl5pU6wmKHq91cHWQT0Fz0vtyE1JauMzKotrwqIKAswwP5cpHUCxZNSTuA/JlqtScq20/5KZ+TxQdovU/g==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", "cpu": [ - "arm64" + "ia32" ], "dev": true, "optional": true, "os": [ - "freebsd" + "win32" ], "engines": { "node": ">=12" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.3.tgz", - "integrity": "sha512-tci+UJ4zP5EGF4rp8XlZIdq1q1a/1h9XuronfxTMCNBslpCtmk97Q/5qqy1Mu4zIc0yswN/yP/BLX+NTUC1bXA==", + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ - "freebsd" + "win32" ], "engines": { - "node": ">=12" + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.3.tgz", - "integrity": "sha512-f6kz2QpSuyHHg01cDawj0vkyMwuIvN62UAguQfnNVzbge2uWLhA7TCXOn83DT0ZvyJmBI943MItgTovUob36SQ==", - "cpu": [ - "arm" - ], + "node_modules/@eslint/js": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", + "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.3.tgz", - "integrity": "sha512-vvG6R5g5ieB4eCJBQevyDMb31LMHthLpXTc2IGkFnPWS/GzIFDnaYFp558O+XybTmYrVjxnryru7QRleJvmZ6Q==", - "cpu": [ - "arm64" - ], + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "dev": true + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@hapi/hoek": "^9.0.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.3.tgz", - "integrity": "sha512-HjCWhH7K96Na+66TacDLJmOI9R8iDWDDiqe17C7znGvvE4sW1ECt9ly0AJ3dJH62jHyVqW9xpxZEU1jKdt+29A==", - "cpu": [ - "ia32" - ], + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, "engines": { - "node": ">=12" + "node": ">=10.10.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.3.tgz", - "integrity": "sha512-BGpimEccmHBZRcAhdlRIxMp7x9PyJxUtj7apL2IuoG9VxvU/l/v1z015nFs7Si7tXUwEsvjc1rOJdZCn4QTU+Q==", - "cpu": [ - "loong64" - ], + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=12" + "node": "*" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.3.tgz", - "integrity": "sha512-5rMOWkp7FQGtAH3QJddP4w3s47iT20hwftqdm7b+loe95o8JU8ro3qZbhgMRy0VuFU0DizymF1pBKkn3YHWtsw==", - "cpu": [ - "mips64el" - ], + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.3.tgz", - "integrity": "sha512-h0zj1ldel89V5sjPLo5H1SyMzp4VrgN1tPkN29TmjvO1/r0MuMRwJxL8QY05SmfsZRs6TF0c/IDH3u7XYYmbAg==", - "cpu": [ - "ppc64" - ], + "node_modules/@humanwhocodes/object-schema": { + "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==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@inquirer/checkbox": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.3.10.tgz", + "integrity": "sha512-CTc864M2/523rKc9AglIzAcUCuPXDZENgc5S2KZFVRbnMzpXcYTsUWmbqSeL0XLvtlvEtNevkkVbfVhJpruOyQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@inquirer/core": "^9.0.2", + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.4.0", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.3.tgz", - "integrity": "sha512-dkAKcTsTJ+CRX6bnO17qDJbLoW37npd5gSNtSzjYQr0svghLJYGYB0NF1SNcU1vDcjXLYS5pO4qOW4YbFama4A==", - "cpu": [ - "riscv64" - ], + "node_modules/@inquirer/checkbox/node_modules/@inquirer/core": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.2.tgz", + "integrity": "sha512-nguvH3TZar3ACwbytZrraRTzGqyxJfYJwv+ZwqZNatAosdWQMP1GV8zvmkNlBe2JeZSaw0WYBHZk52pDpWC9qA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.4.0", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.14.9", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.3.tgz", - "integrity": "sha512-vnD1YUkovEdnZWEuMmy2X2JmzsHQqPpZElXx6dxENcIwTu+Cu5ERax6+Ke1QsE814Zf3c6rxCfwQdCTQ7tPuXA==", - "cpu": [ - "s390x" - ], + "node_modules/@inquirer/checkbox/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.3.tgz", - "integrity": "sha512-IOXOIm9WaK7plL2gMhsWJd+l2bfrhfilv0uPTptoRoSb2p09RghhQQp9YY6ZJhk/kqmeRt6siRdMSLLwzuT0KQ==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/confirm": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.11.tgz", + "integrity": "sha512-3wWw10VPxQP279FO4bzWsf8YjIAq7NdwATJ4xS2h1uwsXZu/RmtOVV95rZ7yllS1h/dzu+uLewjMAzNDEj8h2w==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@inquirer/core": "^8.2.4", + "@inquirer/type": "^1.3.3" + }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.3.tgz", - "integrity": "sha512-uTgCwsvQ5+vCQnqM//EfDSuomo2LhdWhFPS8VL8xKf+PKTCrcT/2kPPoWMTs22aB63MLdGMJiE3f1PHvCDmUOw==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/core": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.4.tgz", + "integrity": "sha512-7vsXSfxtrrbwMTirfaKwPcjqJy7pzeuF/bP62yo1NQrRJ5HjmMlrhZml/Ljm9ODc1RnbhJlTeSnCkjtFddKjwA==", "dev": true, - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.3.3", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.14.9", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "picocolors": "^1.0.1", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.3.tgz", - "integrity": "sha512-vNAkR17Ub2MgEud2Wag/OE4HTSI6zlb291UYzHez/psiKarp0J8PKGDnAhMBcHFoOHMXHfExzmjMojJNbAStrQ==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "optional": true, - "os": [ - "openbsd" - ], "engines": { - "node": ">=12" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.3.tgz", - "integrity": "sha512-W8H9jlGiSBomkgmouaRoTXo49j4w4Kfbl6I1bIdO/vT0+0u4f20ko3ELzV3hPI6XV6JNBVX+8BC+ajHkvffIJA==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/editor": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.14.tgz", + "integrity": "sha512-6nWpoJyVAKwAcv67bkbBmmi3f32xua79fP7TRmNUoR4K+B1GiOBsHO1YdvET/jvC+nTlBZL7puKAKyM7G+Lkzw==", "dev": true, - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@inquirer/core": "^9.0.2", + "@inquirer/type": "^1.4.0", + "external-editor": "^3.1.0" + }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.3.tgz", - "integrity": "sha512-EjEomwyLSCg8Ag3LDILIqYCZAq/y3diJ04PnqGRgq8/4O3VNlXyMd54j/saShaN4h5o5mivOjAzmU6C3X4v0xw==", - "cpu": [ - "arm64" - ], + "node_modules/@inquirer/editor/node_modules/@inquirer/core": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.2.tgz", + "integrity": "sha512-nguvH3TZar3ACwbytZrraRTzGqyxJfYJwv+ZwqZNatAosdWQMP1GV8zvmkNlBe2JeZSaw0WYBHZk52pDpWC9qA==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.4.0", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.14.9", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.3.tgz", - "integrity": "sha512-WGiE/GgbsEwR33++5rzjiYsKyHywE8QSZPF7Rfx9EBfK3Qn3xyR6IjyCr5Uk38Kg8fG4/2phN7sXp4NPWd3fcw==", - "cpu": [ - "ia32" - ], + "node_modules/@inquirer/editor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.3.tgz", - "integrity": "sha512-xRxC0jaJWDLYvcUvjQmHCJSfMrgmUuvsoXgDeU/wTorQ1ngDdUBuFtgY3W1Pc5sprGAvZBtWdJX7RPg/iZZUqA==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/expand": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.14.tgz", + "integrity": "sha512-JcxsLajwPykF2kq6biIUdoOzTQ3LXqb8XMVrWkCprG/pFeU1SsxcSSFbF1T5jJGvvlTVcsE+JdGjbQ8ZRZ82RA==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@inquirer/core": "^9.0.2", + "@inquirer/type": "^1.4.0", + "yoctocolors-cjs": "^2.1.2" + }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@inquirer/expand/node_modules/@inquirer/core": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.2.tgz", + "integrity": "sha512-nguvH3TZar3ACwbytZrraRTzGqyxJfYJwv+ZwqZNatAosdWQMP1GV8zvmkNlBe2JeZSaw0WYBHZk52pDpWC9qA==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.4.0", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.14.9", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" + } + }, + "node_modules/@inquirer/expand/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "node_modules/@inquirer/figures": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.3.tgz", + "integrity": "sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==", "dev": true, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@inquirer/input": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.2.1.tgz", + "integrity": "sha512-Yl1G6h7qWydzrJwqN777geeJVaAFL5Ly83aZlw4xHf8Z/BoTMfKRheyuMaQwOG7LQ4e5nQP7PxXdEg4SzQ+OKw==", "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@inquirer/core": "^9.0.2", + "@inquirer/type": "^1.4.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@inquirer/input/node_modules/@inquirer/core": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.2.tgz", + "integrity": "sha512-nguvH3TZar3ACwbytZrraRTzGqyxJfYJwv+ZwqZNatAosdWQMP1GV8zvmkNlBe2JeZSaw0WYBHZk52pDpWC9qA==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.4.0", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.14.9", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@inquirer/input/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/@inquirer/password": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.14.tgz", + "integrity": "sha512-sPzOkXLhWJQ96K6nPZFnF8XB8tsDrcCRobd1d3EDz81F+4hp8BbdmsnsQcqZ7oYDIOVM/mWJyIUtJ35TrssJxQ==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "@inquirer/core": "^9.0.2", + "@inquirer/type": "^1.4.0", + "ansi-escapes": "^4.3.2" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@inquirer/password/node_modules/@inquirer/core": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.2.tgz", + "integrity": "sha512-nguvH3TZar3ACwbytZrraRTzGqyxJfYJwv+ZwqZNatAosdWQMP1GV8zvmkNlBe2JeZSaw0WYBHZk52pDpWC9qA==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.4.0", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.14.9", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@inquirer/password/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@eslint/js": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", - "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", + "node_modules/@inquirer/prompts": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.0.7.tgz", + "integrity": "sha512-GFcigCxJTKCH3aECzMIu4FhgLJWnFvMXzpI4CCSoELWFtkOOU2P+goYA61+OKpGrB8fPE7q6n8zAXBSlZRrHjQ==", "dev": true, + "dependencies": { + "@inquirer/checkbox": "^2.3.7", + "@inquirer/confirm": "^3.1.11", + "@inquirer/editor": "^2.1.11", + "@inquirer/expand": "^2.1.11", + "@inquirer/input": "^2.1.11", + "@inquirer/password": "^2.1.11", + "@inquirer/rawlist": "^2.1.11", + "@inquirer/select": "^2.3.7" + }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "node_modules/@inquirer/rawlist": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.1.14.tgz", + "integrity": "sha512-pLpEzhKNQ/ugFAFfgCNaXljB+dcCwmXwR1jOxAbVeFIdB3l02E5gjI+h1rb136tq0T8JO6P5KFR1oTeld/wdrA==", "dev": true, "dependencies": { - "@hapi/hoek": "^9.0.0" + "@inquirer/core": "^9.0.2", + "@inquirer/type": "^1.4.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@inquirer/rawlist/node_modules/@inquirer/core": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.2.tgz", + "integrity": "sha512-nguvH3TZar3ACwbytZrraRTzGqyxJfYJwv+ZwqZNatAosdWQMP1GV8zvmkNlBe2JeZSaw0WYBHZk52pDpWC9qA==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.4.0", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.14.9", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=10.10.0" + "node": ">=18" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@inquirer/rawlist/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/select": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.3.10.tgz", + "integrity": "sha512-rr7iR0Zj1YFfgM8IUGimPD9Yukd+n/U63CnYT9kdum6DbRXtMxR45rrreP+EA9ixCnShr+W4xj7suRxC1+8t9g==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@inquirer/core": "^9.0.2", + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.4.0", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@inquirer/select/node_modules/@inquirer/core": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.2.tgz", + "integrity": "sha512-nguvH3TZar3ACwbytZrraRTzGqyxJfYJwv+ZwqZNatAosdWQMP1GV8zvmkNlBe2JeZSaw0WYBHZk52pDpWC9qA==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.4.0", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.14.9", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@inquirer/select/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "engines": { - "node": ">=12.22" + "node": ">=14" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@humanwhocodes/object-schema": { - "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==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true - }, - "node_modules/@inquirer/figures": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.3.tgz", - "integrity": "sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==", + "node_modules/@inquirer/type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.4.0.tgz", + "integrity": "sha512-AjOqykVyjdJQvtfkNDGUyMYGF8xN50VUxftCQWsOyIo4DFRLr6VQhW0VItGI1JIyQGCGgIpKa7hMMwNhZb4OIw==", "dev": true, + "dependencies": { + "mute-stream": "^1.0.0" + }, "engines": { "node": ">=18" } @@ -3829,22 +4217,25 @@ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "dev": true }, - "node_modules/@ljharb/through": { - "version": "2.3.13", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz", - "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==", + "node_modules/@listr2/prompt-adapter-inquirer": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.13.tgz", + "integrity": "sha512-nAl6teTt7EWSjttNavAnv3uFR3w3vPP3OTYmHyPNHzKhAj2NoBDHmbS3MGpvvO8KXXPASnHjEGrrKrdKTMKPnQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7" + "@inquirer/type": "^1.3.3" }, "engines": { - "node": ">= 0.4" + "node": ">=18.0.0" + }, + "peerDependencies": { + "@inquirer/prompts": ">= 3 < 6" } }, "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.0.8.tgz", - "integrity": "sha512-+lFwFvU+zQ9zVIFETNtmW++syh3Ps5JS8MPQ8zOYtQZoU+dTR8ivWHTaE2QVk1JG2payGDLUAvpndLAjGMdeeA==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.0.12.tgz", + "integrity": "sha512-vgTwzNUD3Hy4aqtGhX2+nV/usI0mwy3hDRuTjs8VcK0BLiMVEpNQXgzwlWEgPmA8AAPloUgyOs2nK5clJF5oIg==", "cpu": [ "arm64" ], @@ -3855,9 +4246,9 @@ ] }, "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.0.8.tgz", - "integrity": "sha512-T98rfsgfdQMS5/mqdsPb6oHSJ+iBYNa+PQDLtXLh6rzTEBsYP9x2uXxIj6VS4qXVDWXVi8rv85NCOG+UBOsHXQ==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.0.12.tgz", + "integrity": "sha512-qOt0hAhj2ZLY6aEWu85rzt5zcyCAQITMhCMEPNlo1tuYekpVAdkQNiwXxEkCjBYvwTskvXuwXOOUpjuSc+aJnA==", "cpu": [ "x64" ], @@ -3868,9 +4259,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.0.8.tgz", - "integrity": "sha512-gVNCi3bYWatdPMeFpFjuZl6bzVL55FkeZU3sPeU+NsMRXC+Zl3qOx3M6cM4OMlJWbhHjYjf2b8q83K0mczaiWQ==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.0.12.tgz", + "integrity": "sha512-Ggd/UXpE+alMncbELCXA3OKpDj9bDBR3qVO7WRTxstloDglRAHfZmUJgTkeaNKjFO1JHqS7AKy0jba9XebZB1w==", "cpu": [ "arm" ], @@ -3881,9 +4272,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.0.8.tgz", - "integrity": "sha512-uEBGCQIChsixpykL0pjCxfF64btv64vzsb1NoM5u0qvabKvKEvErhXGoqovyldDu9u1T/fswD8Kf6ih0vJEvDQ==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.0.12.tgz", + "integrity": "sha512-Qy4cFXFe9h1wAWMsojex8x1ifvw2kqiZv686YiRTdQEzAfc3vJASHFcD/QejHUCx7YHMYdnUoCS45rG2AiGDTQ==", "cpu": [ "arm64" ], @@ -3894,9 +4285,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.0.8.tgz", - "integrity": "sha512-6v0B4sa9ulNezmDZtVpLjNHmA0qZzUl3001YJ2RF0naxsuv/Jq/xEwNYpOzfcdizHfpCE0oBkWzk/r+Slr+0zw==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.0.12.tgz", + "integrity": "sha512-c+noT9IofktxktFllKHFmci8ka2SYGSLN17pj/KSl1hg7mmfAiGp4xxFxEwMLTb+SX95vP1DFiR++1I3WLVxvA==", "cpu": [ "x64" ], @@ -3907,9 +4298,9 @@ ] }, "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.0.8.tgz", - "integrity": "sha512-lDLGRIMqdwYD39vinwNqqZUxCdL2m2iIdn+0HyQgIHEiT0g5rIAlzaMKzoGWon5NQumfxXFk9y0DarttkR7C1w==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.0.12.tgz", + "integrity": "sha512-CO3MFV8gUx16NU/CyyuumAKblESwvoGVA2XhQKZ976OTOxaTbb8F8D3f0iiZ4MYqsN74jIrFuCmXpPnpjbhfOQ==", "cpu": [ "x64" ], @@ -4076,9 +4467,9 @@ ] }, "node_modules/@ngtools/webpack": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.0.6.tgz", - "integrity": "sha512-chSRbPpnqTThURQqUvWAgEGkLcn5TQnUQPD1HBf4WcoO/OkaK4Q1Sa8FrEllkC6/Dlyj7myi8rskQz+V8K7GSg==", + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.1.0.tgz", + "integrity": "sha512-J4ATDGq0AubLbP3DOFRjp0pDBvSgzjtiu5l1hGq3xf6AzVAEmZFlp2Ac2EykuK2r8XDnCVoLrxICJOXZWWzP2g==", "dev": true, "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0", @@ -4087,7 +4478,7 @@ }, "peerDependencies": { "@angular/compiler-cli": "^18.0.0", - "typescript": ">=5.4 <5.5", + "typescript": ">=5.4 <5.6", "webpack": "^5.54.0" } }, @@ -4439,9 +4830,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", - "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", + "integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==", "cpu": [ "arm" ], @@ -4452,9 +4843,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", - "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz", + "integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==", "cpu": [ "arm64" ], @@ -4465,9 +4856,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", - "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz", + "integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==", "cpu": [ "arm64" ], @@ -4478,9 +4869,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", - "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz", + "integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==", "cpu": [ "x64" ], @@ -4490,10 +4881,10 @@ "darwin" ] }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", - "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz", + "integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==", "cpu": [ "arm" ], @@ -4504,9 +4895,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", - "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz", + "integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==", "cpu": [ "arm" ], @@ -4517,9 +4908,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", - "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz", + "integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==", "cpu": [ "arm64" ], @@ -4530,9 +4921,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", - "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz", + "integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==", "cpu": [ "arm64" ], @@ -4543,9 +4934,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", - "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz", + "integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==", "cpu": [ "ppc64" ], @@ -4556,9 +4947,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", - "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz", + "integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==", "cpu": [ "riscv64" ], @@ -4569,9 +4960,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", - "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz", + "integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==", "cpu": [ "s390x" ], @@ -4582,9 +4973,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", - "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz", + "integrity": "sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==", "cpu": [ "x64" ], @@ -4595,9 +4986,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", - "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.1.tgz", + "integrity": "sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==", "cpu": [ "x64" ], @@ -4608,9 +4999,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", - "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz", + "integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==", "cpu": [ "arm64" ], @@ -4621,9 +5012,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", - "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz", + "integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==", "cpu": [ "ia32" ], @@ -4634,9 +5025,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", - "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz", + "integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==", "cpu": [ "x64" ], @@ -4647,14 +5038,14 @@ ] }, "node_modules/@schematics/angular": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.0.6.tgz", - "integrity": "sha512-SZ73nNhCengIOy3GCUbLL++GdpaQ5T9bh05OAdQJuUNtwz1ot8QoQjkcbumKIfTicwMiLxy+OR4sZN1VcUVYpQ==", + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.1.0.tgz", + "integrity": "sha512-k9Dy6JD7hqvCzDqnMjDm7J8H/P6m5mLuX2yEgQWKRAJ/YMINtBQAaKA1T9qXk97kEX6RNLpHMuDIsrIfK/H31Q==", "dev": true, "dependencies": { - "@angular-devkit/core": "18.0.6", - "@angular-devkit/schematics": "18.0.6", - "jsonc-parser": "3.2.1" + "@angular-devkit/core": "18.1.0", + "@angular-devkit/schematics": "18.1.0", + "jsonc-parser": "3.3.1" }, "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0", @@ -4769,6 +5160,18 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -5041,6 +5444,15 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", "dev": true }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", @@ -5143,6 +5555,12 @@ "dev": true, "optional": true }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "dev": true + }, "node_modules/@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", @@ -5634,21 +6052,11 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-import-attributes": { "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "dev": true, - "peer": true, "peerDependencies": { "acorn": "^8" } @@ -5727,9 +6135,9 @@ } }, "node_modules/ajv": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", - "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", @@ -7578,20 +7986,20 @@ } }, "node_modules/copy-webpack-plugin": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", - "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz", + "integrity": "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==", "dev": true, "dependencies": { - "fast-glob": "^3.2.11", + "fast-glob": "^3.3.2", "glob-parent": "^6.0.1", - "globby": "^13.1.1", + "globby": "^14.0.0", "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" + "schema-utils": "^4.2.0", + "serialize-javascript": "^6.0.2" }, "engines": { - "node": ">= 14.15.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", @@ -7745,9 +8153,9 @@ "dev": true }, "node_modules/critters": { - "version": "0.0.22", - "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.22.tgz", - "integrity": "sha512-NU7DEcQZM2Dy8XTKFHxtdnIM/drE312j2T4PCVaSUcS0oBeyT/NImpRw/Ap0zOr/1SE7SgPK9tGPg1WK/sVakw==", + "version": "0.0.24", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.24.tgz", + "integrity": "sha512-Oyqew0FGM0wYUSNqR0L6AteO5MpMoUU0rhKRieXeiKs+PmRTxiJMyaunYB2KF6fQ3dzChXKCpbFOEJx3OQ1v/Q==", "dev": true, "dependencies": { "chalk": "^4.1.0", @@ -7866,9 +8274,9 @@ } }, "node_modules/css-loader": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.1.tgz", - "integrity": "sha512-OxIR5P2mjO1PSXk44bWuQ8XtMK4dpEqpIyERCx3ewOo3I8EmbcxMPUc5ScLtQfgXtOojoMv57So4V/C02HQLsw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", + "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", "dev": true, "dependencies": { "icss-utils": "^5.1.0", @@ -8120,12 +8528,15 @@ } }, "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/define-properties": { @@ -9093,9 +9504,9 @@ "optional": true }, "node_modules/esbuild": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.3.tgz", - "integrity": "sha512-Kgq0/ZsAPzKrbOjCQcjoSmPoWhlcVnGAUo7jvaLHoxW1Drto0KGkR1xBNg2Cp43b9ImvxmPEJZ9xkfcnqPsfBw==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, "bin": { @@ -9105,35 +9516,35 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.3", - "@esbuild/android-arm": "0.21.3", - "@esbuild/android-arm64": "0.21.3", - "@esbuild/android-x64": "0.21.3", - "@esbuild/darwin-arm64": "0.21.3", - "@esbuild/darwin-x64": "0.21.3", - "@esbuild/freebsd-arm64": "0.21.3", - "@esbuild/freebsd-x64": "0.21.3", - "@esbuild/linux-arm": "0.21.3", - "@esbuild/linux-arm64": "0.21.3", - "@esbuild/linux-ia32": "0.21.3", - "@esbuild/linux-loong64": "0.21.3", - "@esbuild/linux-mips64el": "0.21.3", - "@esbuild/linux-ppc64": "0.21.3", - "@esbuild/linux-riscv64": "0.21.3", - "@esbuild/linux-s390x": "0.21.3", - "@esbuild/linux-x64": "0.21.3", - "@esbuild/netbsd-x64": "0.21.3", - "@esbuild/openbsd-x64": "0.21.3", - "@esbuild/sunos-x64": "0.21.3", - "@esbuild/win32-arm64": "0.21.3", - "@esbuild/win32-ia32": "0.21.3", - "@esbuild/win32-x64": "0.21.3" + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, "node_modules/esbuild-wasm": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.21.3.tgz", - "integrity": "sha512-DMOV+eeVra0yVq3XIojfczdEQsz+RiFnpEj7lqs8Gux9mlTpN7yIbw0a4KzLspn0Uhw6UVEH3nUAidSqc/rcQg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.21.5.tgz", + "integrity": "sha512-L/FlOPMMFtw+6qPAbuPvJXdrOYOp9yx/PEwSrIZW0qghY4vgV003evdYDwqQ/9ENMQI0B6RMod9xT4FHtto6OQ==", "dev": true, "bin": { "esbuild": "bin/esbuild" @@ -10094,6 +10505,18 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -10250,19 +10673,32 @@ } }, "node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", "dev": true, "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -10666,9 +11102,9 @@ "dev": true }, "node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, "dependencies": { "agent-base": "^7.0.2", @@ -10876,52 +11312,14 @@ "dev": true }, "node_modules/ini": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", - "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/inquirer": { - "version": "9.2.22", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.22.tgz", - "integrity": "sha512-SqLLa/Oe5rZUagTR9z+Zd6izyatHglbmbvVofo1KzuVB54YHleWzeHNLoR7FOICGOeQSqeLh1cordb3MzhGcEw==", - "dev": true, - "dependencies": { - "@inquirer/figures": "^1.0.2", - "@ljharb/through": "^2.3.13", - "ansi-escapes": "^4.3.2", - "chalk": "^5.3.0", - "cli-cursor": "^3.1.0", - "cli-width": "^4.1.0", - "external-editor": "^3.1.0", - "lodash": "^4.17.21", - "mute-stream": "1.0.0", - "ora": "^5.4.1", - "run-async": "^3.0.0", - "rxjs": "^7.8.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/inquirer/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/interactjs": { "version": "1.10.27", "resolved": "https://registry.npmjs.org/interactjs/-/interactjs-1.10.27.tgz", @@ -11114,15 +11512,15 @@ } }, "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, "bin": { "is-docker": "cli.js" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11191,21 +11589,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-inside-container/node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -11437,15 +11820,18 @@ "dev": true }, "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "dependencies": { - "is-docker": "^2.0.0" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isarray": { @@ -11783,9 +12169,9 @@ } }, "node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", "dev": true }, "node_modules/jsonfile": { @@ -12018,16 +12404,162 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/listr2": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.3.tgz", + "integrity": "sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/listr2/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/lmdb": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.0.8.tgz", - "integrity": "sha512-9rp8JT4jPhCRJUL7vRARa2N06OLSYzLwQsEkhC6Qu5XbcLyM/XBLMzDlgS/K7l7c5CdURLdDk9uE+hPFIogHTQ==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.0.12.tgz", + "integrity": "sha512-JnoEulTgveoC64vlYJ9sufGLuNkk6TcxSYpKxSC9aM42I61jIv3pQH0fgb6qW7HV0+FNqA3g1WCQQYfhfawGoQ==", "dev": true, "hasInstallScript": true, "dependencies": { - "msgpackr": "^1.9.9", + "msgpackr": "^1.10.2", "node-addon-api": "^6.1.0", - "node-gyp-build-optional-packages": "5.1.1", + "node-gyp-build-optional-packages": "5.2.2", "ordered-binary": "^1.4.1", "weak-lru-cache": "^1.2.2" }, @@ -12035,12 +12567,12 @@ "download-lmdb-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "3.0.8", - "@lmdb/lmdb-darwin-x64": "3.0.8", - "@lmdb/lmdb-linux-arm": "3.0.8", - "@lmdb/lmdb-linux-arm64": "3.0.8", - "@lmdb/lmdb-linux-x64": "3.0.8", - "@lmdb/lmdb-win32-x64": "3.0.8" + "@lmdb/lmdb-darwin-arm64": "3.0.12", + "@lmdb/lmdb-darwin-x64": "3.0.12", + "@lmdb/lmdb-linux-arm": "3.0.12", + "@lmdb/lmdb-linux-arm64": "3.0.12", + "@lmdb/lmdb-linux-x64": "3.0.12", + "@lmdb/lmdb-win32-x64": "3.0.12" } }, "node_modules/lmdb/node_modules/node-addon-api": { @@ -12096,9 +12628,9 @@ } }, "node_modules/loader-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", - "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", "dev": true, "engines": { "node": ">= 12.13.0" @@ -12191,3540 +12723,3238 @@ "node_modules/log-symbols/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/make-fetch-happen": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", - "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", - "dev": true, - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "optional": true, - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/matcher/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", - "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", - "dev": true, - "dependencies": { - "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.1.2", - "tree-dump": "^1.0.1", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">= 4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=8.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=8.6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" + "color-name": "~1.1.4" }, - "bin": { - "miller-rabin": "bin/miller-rabin" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/miller-rabin/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/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "bin": { - "mime": "cli.js" - }, "engines": { - "node": ">=4.0.0" + "node": ">=8" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", "dev": true, "dependencies": { - "mime-db": "1.52.0" + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", "dev": true, "engines": { - "node": ">=6" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/mini-css-extract-plugin": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", - "integrity": "sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==", + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, "dependencies": { - "schema-utils": "^4.0.0", - "tapable": "^2.2.1" + "restore-cursor": "^4.0.0" }, "engines": { - "node": ">= 12.13.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", "dev": true }, - "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "get-east-asian-width": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/log-update/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { - "minipass": "^7.0.3" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=12" }, - "optionalDependencies": { - "encoding": "^0.1.13" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "minipass": "^3.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">= 8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { "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-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" + "yallist": "^3.0.2" } }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@jridgewell/sourcemap-codec": "^1.4.15" } }, - "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", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, + "optional": true, "dependencies": { - "minipass": "^3.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" + "optional": true, + "bin": { + "semver": "bin/semver" } }, - "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==", + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "node_modules/make-fetch-happen": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", + "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", "dev": true, "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" }, "engines": { - "node": ">= 8" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", "dev": true, + "optional": true, "dependencies": { - "yallist": "^4.0.0" + "escape-string-regexp": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/minizlib/node_modules/yallist": { + "node_modules/matcher/node_modules/escape-string-regexp": { "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", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, + "optional": true, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "engines": { - "node": "*" - } - }, - "node_modules/mrmime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", - "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "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 - }, - "node_modules/msgpackr": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.10.2.tgz", - "integrity": "sha512-L60rsPynBvNE+8BWipKKZ9jHcSGbtyJYIwjRq0VrIvQ08cRjntGXJYW/tmciZ2IHWIY8WEW32Qa2xbh5+SKBZA==", + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, - "optionalDependencies": { - "msgpackr-extract": "^3.0.2" + "engines": { + "node": ">= 0.6" } }, - "node_modules/msgpackr-extract": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", - "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "node_modules/memfs": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", + "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", "dev": true, - "hasInstallScript": true, - "optional": true, "dependencies": { - "node-gyp-build-optional-packages": "5.2.2" + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.1.2", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" }, - "bin": { - "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + "engines": { + "node": ">= 4.0.0" }, - "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" } }, - "node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", - "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", "dev": true, - "optional": true, - "dependencies": { - "detect-libc": "^2.0.1" - }, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" + "engines": { + "node": ">= 0.10.0" } }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true }, - "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">= 0.6" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/needle": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", - "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, - "optional": true, "dependencies": { - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 4.4.x" + "node": ">=8.6" } }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/ngraph.events": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.2.2.tgz", - "integrity": "sha512-JsUbEOzANskax+WSYiAPETemLWYXmixuPAlmZmhIbIj6FH/WDgEGCGnRwUQBK0GjOnVm8Ui+e5IJ+5VZ4e32eQ==" - }, - "node_modules/nice-napi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", - "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "!win32" - ], "dependencies": { - "node-addon-api": "^3.0.0", - "node-gyp-build": "^4.2.2" + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" } }, - "node_modules/nice-napi/node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "optional": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "node_modules/miller-rabin/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==", "dev": true }, - "node_modules/node-addon-api": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", - "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, - "optional": true + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "engines": { - "node": ">= 6.13.0" + "node": ">= 0.6" } }, - "node_modules/node-gyp": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.1.0.tgz", - "integrity": "sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^4.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" + "mime-db": "1.52.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">= 0.6" } }, - "node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "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, - "optional": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" + "engines": { + "node": ">=6" } }, - "node_modules/node-gyp-build-optional-packages": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz", - "integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==", + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", + "integrity": "sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==", "dev": true, "dependencies": { - "detect-libc": "^2.0.1" + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" }, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" } }, - "node_modules/node-gyp/node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "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==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=16 || 14 >=14.18" - }, + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/node-gyp/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "engines": { - "node": ">=16" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/node-gyp/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "minipass": "^7.0.3" }, "engines": { "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "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", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" } }, - "node_modules/node-gyp/node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/node-gyp/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" + "yallist": "^4.0.0" }, "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/node-polyfill-webpack-plugin": { + "node_modules/minipass-flush/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-4.0.0.tgz", - "integrity": "sha512-WLk77vLpbcpmTekRj6s6vYxk30XoyaY5MDZ4+9g8OaKoG3Ij+TjOqhpQjVUlfDZBPBgpNATDltaQkzuXSnnkwg==", + "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", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "dependencies": { - "assert": "^2.1.0", - "browserify-zlib": "^0.2.0", - "buffer": "^6.0.3", - "console-browserify": "^1.2.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.12.0", - "domain-browser": "^5.7.0", - "events": "^3.3.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "^1.0.1", - "process": "^0.11.10", - "punycode": "^2.3.1", - "querystring-es3": "^0.2.1", - "readable-stream": "^4.5.2", - "stream-browserify": "^3.0.0", - "stream-http": "^3.2.0", - "string_decoder": "^1.3.0", - "timers-browserify": "^2.0.12", - "tty-browserify": "^0.0.1", - "type-fest": "^4.18.2", - "url": "^0.11.3", - "util": "^0.12.5", - "vm-browserify": "^1.1.2" + "minipass": "^3.0.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "webpack": ">=5" + "node": ">=8" } }, - "node_modules/node-polyfill-webpack-plugin/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "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" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/node-polyfill-webpack-plugin/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==", + "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", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" + "minipass": "^3.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" } }, - "node_modules/node-polyfill-webpack-plugin/node_modules/type-fest": { - "version": "4.20.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.20.1.tgz", - "integrity": "sha512-R6wDsVsoS9xYOpy8vgeBlqpdOyzJ12HNfQhC/aAKWM3YoCV9TtunJzh/QpkMgeDhkoynDcw5f1y+qF9yc/HHyg==", + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "engines": { - "node": ">=16" + "dependencies": { + "yallist": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "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/nopt": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", - "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" + "yallist": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/normalize-package-data/node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "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", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, - "dependencies": { - "lru-cache": "^10.0.1" + "bin": { + "mkdirp": "bin/cmd.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/normalize-package-data/node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", - "dev": true, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "engines": { - "node": "14 || >=16.14" + "node": "*" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "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 }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "node_modules/msgpackr": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.10.2.tgz", + "integrity": "sha512-L60rsPynBvNE+8BWipKKZ9jHcSGbtyJYIwjRq0VrIvQ08cRjntGXJYW/tmciZ2IHWIY8WEW32Qa2xbh5+SKBZA==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" } }, - "node_modules/npm-bundled": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", - "integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==", + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", "dev": true, + "hasInstallScript": true, + "optional": true, "dependencies": { - "npm-normalize-package-bin": "^3.0.0" + "node-gyp-build-optional-packages": "5.2.2" }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" } }, - "node_modules/npm-install-checks": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", - "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dev": true, "dependencies": { - "semver": "^7.1.1" + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "bin": { + "multicast-dns": "cli.js" } }, - "node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm-package-arg": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.2.tgz", - "integrity": "sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==", + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, - "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^4.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/npm-package-arg/node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/needle": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", + "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", "dev": true, + "optional": true, "dependencies": { - "lru-cache": "^10.0.1" + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">= 4.4.x" } }, - "node_modules/npm-package-arg/node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "engines": { - "node": "14 || >=16.14" + "node": ">= 0.6" } }, - "node_modules/npm-packlist": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", - "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/ngraph.events": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.2.2.tgz", + "integrity": "sha512-JsUbEOzANskax+WSYiAPETemLWYXmixuPAlmZmhIbIj6FH/WDgEGCGnRwUQBK0GjOnVm8Ui+e5IJ+5VZ4e32eQ==" + }, + "node_modules/nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "!win32" + ], "dependencies": { - "ignore-walk": "^6.0.4" - }, + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } + }, + "node_modules/nice-napi/node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "optional": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "optional": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 6.13.0" } }, - "node_modules/npm-pick-manifest": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.1.tgz", - "integrity": "sha512-Udm1f0l2nXb3wxDpKjfohwgdFUSV50UVwzEIpDXVsbDMXVIEF81a/i0UhuQbhrPMMmdiq3+YMFLFIRVLs3hxQw==", + "node_modules/node-gyp": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.1.0.tgz", + "integrity": "sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==", "dev": true, "dependencies": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^11.0.0", - "semver": "^7.3.5" + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/npm-registry-fetch": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-17.1.0.tgz", - "integrity": "sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==", + "node_modules/node-gyp-build": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", + "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "dev": true, + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", "dev": true, "dependencies": { - "@npmcli/redact": "^2.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^13.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minizlib": "^2.1.2", - "npm-package-arg": "^11.0.0", - "proc-log": "^4.0.0" + "detect-libc": "^2.0.1" }, - "engines": { - "node": "^16.14.0 || >=18.0.0" + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" } }, - "node_modules/npm-run-all": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", - "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "node_modules/node-gyp/node_modules/glob": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", + "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { - "npm-run-all": "bin/npm-run-all/index.js", - "run-p": "bin/run-p/index.js", - "run-s": "bin/run-s/index.js" + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">= 4" + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/npm-run-all/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=16" } }, - "node_modules/npm-run-all/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "node_modules/node-gyp/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=4.8" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/npm-run-all/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/node-gyp/node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" }, "engines": { - "node": "*" + "node": "^16.13.0 || >=18.0.0" } }, - "node_modules/npm-run-all/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "node_modules/node-polyfill-webpack-plugin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-4.0.0.tgz", + "integrity": "sha512-WLk77vLpbcpmTekRj6s6vYxk30XoyaY5MDZ4+9g8OaKoG3Ij+TjOqhpQjVUlfDZBPBgpNATDltaQkzuXSnnkwg==", "dev": true, + "dependencies": { + "assert": "^2.1.0", + "browserify-zlib": "^0.2.0", + "buffer": "^6.0.3", + "console-browserify": "^1.2.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.12.0", + "domain-browser": "^5.7.0", + "events": "^3.3.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "punycode": "^2.3.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^4.5.2", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.3.0", + "timers-browserify": "^2.0.12", + "tty-browserify": "^0.0.1", + "type-fest": "^4.18.2", + "url": "^0.11.3", + "util": "^0.12.5", + "vm-browserify": "^1.1.2" + }, "engines": { - "node": ">=4" + "node": ">=14" + }, + "peerDependencies": { + "webpack": ">=5" } }, - "node_modules/npm-run-all/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/node-polyfill-webpack-plugin/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, - "bin": { - "semver": "bin/semver" + "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/npm-run-all/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "node_modules/node-polyfill-webpack-plugin/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==", "dev": true, "dependencies": { - "shebang-regex": "^1.0.0" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">=0.10.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/npm-run-all/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "node_modules/node-polyfill-webpack-plugin/node_modules/type-fest": { + "version": "4.20.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.20.1.tgz", + "integrity": "sha512-R6wDsVsoS9xYOpy8vgeBlqpdOyzJ12HNfQhC/aAKWM3YoCV9TtunJzh/QpkMgeDhkoynDcw5f1y+qF9yc/HHyg==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-run-all/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "abbrev": "^2.0.0" }, "bin": { - "which": "bin/which" + "nopt": "bin/nopt.js" + }, + "engines": { + "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==", + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", "dev": true, "dependencies": { - "path-key": "^3.0.0" + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": ">=8" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, "dependencies": { - "boolbase": "^1.0.0" + "lru-cache": "^10.0.1" }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nuid": { - "version": "2.0.1-2", - "resolved": "https://registry.npmjs.org/nuid/-/nuid-2.0.1-2.tgz", - "integrity": "sha512-zL7Z5+CivaZyUdBn76Ih8rffXABBSe3hzazHBk7qXsF4/o5DPDsblXjs5KQRlgjkeLa6XSCd5/GJaShArI2WMQ==", + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", + "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", + "dev": true, "engines": { - "node": ">= 18.x" + "node": "14 || >=16.14" } }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "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==", + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "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==", + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true, "engines": { - "node": ">= 0.4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "node_modules/npm-bundled": { + "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": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "npm-normalize-package-bin": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "node_modules/npm-install-checks": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", "dev": true, "dependencies": { - "ee-first": "1.1.1" + "semver": "^7.1.1" }, "engines": { - "node": ">= 0.8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", "dev": true, "engines": { - "node": ">= 0.8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/npm-package-arg": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.2.tgz", + "integrity": "sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==", "dev": true, "dependencies": { - "wrappy": "1" + "hosted-git-info": "^7.0.0", + "proc-log": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/npm-package-arg/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "lru-cache": "^10.0.1" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "node_modules/npm-package-arg/node_modules/lru-cache": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", + "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "14 || >=16.14" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/npm-packlist": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", + "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", "dev": true, "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" + "ignore-walk": "^6.0.4" }, "engines": { - "node": ">= 0.8.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/npm-pick-manifest": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.1.tgz", + "integrity": "sha512-Udm1f0l2nXb3wxDpKjfohwgdFUSV50UVwzEIpDXVsbDMXVIEF81a/i0UhuQbhrPMMmdiq3+YMFLFIRVLs3hxQw==", "dev": true, "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/npm-registry-fetch": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-17.1.0.tgz", + "integrity": "sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@npmcli/redact": "^2.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^4.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" }, - "engines": { - "node": ">=10" + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "engines": { + "node": ">= 4" } }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/npm-run-all/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, "engines": { - "node": ">=8" + "node": ">=4.8" } }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/npm-run-all/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/ordered-binary": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.1.tgz", - "integrity": "sha512-5VyHfHY3cd0iza71JepYG50My+YUbrFtGoUz2ooEydPyPM7Aai/JW098juLr+RG6+rDJuzNNTsEQu2DZa1A41A==", - "dev": true - }, - "node_modules/os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", - "dev": true - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "engines": { - "node": ">=8" + "bin": { + "semver": "bin/semver" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "shebang-regex": "^1.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" + "isexe": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "which": "bin/which" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "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": { - "aggregate-error": "^3.0.0" + "path-key": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/p-retry": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", - "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=16.17" + "boolbase": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/p-retry/node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, + "node_modules/nuid": { + "version": "2.0.1-2", + "resolved": "https://registry.npmjs.org/nuid/-/nuid-2.0.1-2.tgz", + "integrity": "sha512-zL7Z5+CivaZyUdBn76Ih8rffXABBSe3hzazHBk7qXsF4/o5DPDsblXjs5KQRlgjkeLa6XSCd5/GJaShArI2WMQ==", "engines": { - "node": ">= 4" + "node": ">= 18.x" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true - }, - "node_modules/pacote": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-18.0.6.tgz", - "integrity": "sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==", + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, - "dependencies": { - "@npmcli/git": "^5.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/package-json": "^5.1.0", - "@npmcli/promise-spawn": "^7.0.0", - "@npmcli/run-script": "^8.0.0", - "cacache": "^18.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^11.0.0", - "npm-packlist": "^8.0.0", - "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^17.0.0", - "proc-log": "^4.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^2.2.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "bin/index.js" - }, "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "node_modules/panzoom": { - "version": "9.4.3", - "resolved": "https://registry.npmjs.org/panzoom/-/panzoom-9.4.3.tgz", - "integrity": "sha512-xaxCpElcRbQsUtIdwlrZA90P90+BHip4Vda2BC8MEb4tkI05PmR6cKECdqUCZ85ZvBHjpI9htJrZBxV5Gp/q/w==", - "dependencies": { - "amator": "^1.1.0", - "ngraph.events": "^1.2.2", - "wheel": "^1.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "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==", "dev": true, "dependencies": { - "callsites": "^3.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parse-asn1": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", - "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", + "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, - "dependencies": { - "asn1.js": "^4.10.1", - "browserify-aes": "^1.2.0", - "evp_bytestokey": "^1.0.3", - "hash-base": "~3.0", - "pbkdf2": "^3.1.2", - "safe-buffer": "^5.2.1" - }, "engines": { - "node": ">= 0.10" + "node": ">= 0.4" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parse-json/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, "engines": { - "node": ">= 0.10" + "node": ">= 0.8" } }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "devOptional": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" } }, - "node_modules/parse5-html-rewriting-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", - "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { - "entities": "^4.3.0", - "parse5": "^7.0.0", - "parse5-sax-parser": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "wrappy": "1" } }, - "node_modules/parse5-sax-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", - "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", + "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": { - "parse5": "^7.0.0" + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" }, "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", "dev": true, + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": "14 || >=16.14" + "node": ">=7.0.0" } }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/path-type": { + "node_modules/ora/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.12" + "node": ">=8" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "node_modules/ordered-binary": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.1.tgz", + "integrity": "sha512-5VyHfHY3cd0iza71JepYG50My+YUbrFtGoUz2ooEydPyPM7Aai/JW098juLr+RG6+rDJuzNNTsEQu2DZa1A41A==", "dev": true }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", "dev": true }, - "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", - "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, - "optional": true, "engines": { - "node": ">=6" - } - }, - "node_modules/piscina": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.5.0.tgz", - "integrity": "sha512-iBaLWI56PFP81cfBSomWTmhOo9W2/yhIOL+Tk8O1vBCpK39cM0tGxB+wgYjG31qq4ohGvysfXSdnj8h7g4rZxA==", - "dev": true, - "optionalDependencies": { - "nice-napi": "^1.0.2" + "node": ">=0.10.0" } }, - "node_modules/pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", "dev": true, - "dependencies": { - "find-up": "^6.3.0" - }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "p-locate": "^6.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-dir/node_modules/p-limit": { + "node_modules/p-map": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "dependencies": { - "p-limit": "^4.0.0" + "aggregate-error": "^3.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "node_modules/p-retry": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", "dev": true, + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-dir/node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 4" } }, - "node_modules/plist": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", - "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, + "node_modules/pacote": { + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-18.0.6.tgz", + "integrity": "sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==", "dev": true, "dependencies": { - "@xmldom/xmldom": "^0.8.8", - "base64-js": "^1.5.1", - "xmlbuilder": "^15.1.1" + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/package-json": "^5.1.0", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^8.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^17.0.0", + "proc-log": "^4.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^2.2.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" }, "engines": { - "node": ">=10.4.0" + "node": "^16.14.0 || >=18.0.0" } }, - "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==", + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/panzoom": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/panzoom/-/panzoom-9.4.3.tgz", + "integrity": "sha512-xaxCpElcRbQsUtIdwlrZA90P90+BHip4Vda2BC8MEb4tkI05PmR6cKECdqUCZ85ZvBHjpI9htJrZBxV5Gp/q/w==", + "dependencies": { + "amator": "^1.1.0", + "ngraph.events": "^1.2.2", + "wheel": "^1.0.0" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=6" } }, - "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "node_modules/parse-asn1": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", + "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "hash-base": "~3.0", + "pbkdf2": "^3.1.2", + "safe-buffer": "^5.2.1" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">= 0.10" } }, - "node_modules/postcss-loader": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", - "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "dependencies": { - "cosmiconfig": "^9.0.0", - "jiti": "^1.20.0", - "semver": "^7.5.4" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": ">= 18.12.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "node_modules/parse-json/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", "dev": true, "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">= 0.10" } }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "devOptional": true, "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" + "entities": "^4.4.0" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "node_modules/parse5-html-rewriting-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", + "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "node_modules/parse5-sax-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", + "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", "dev": true, "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" + "parse5": "^7.0.0" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/postcss-selector-parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", - "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", "dev": true }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/primeflex": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/primeflex/-/primeflex-3.3.1.tgz", - "integrity": "sha512-zaOq3YvcOYytbAmKv3zYc+0VNS9Wg5d37dfxZnveKBFPr7vEIwfV5ydrpiouTft8MVW6qNjfkaQphHSnvgQbpQ==" + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "node_modules/primeicons": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-7.0.0.tgz", - "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==" + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, - "node_modules/primeng": { - "version": "17.18.2", - "resolved": "https://registry.npmjs.org/primeng/-/primeng-17.18.2.tgz", - "integrity": "sha512-2uux//0AOj/EwiOQHmUVFst+9dtf4duNLI+Oo6vN3HLXoQF+Eax5Mfi5eHh+EDSJMFCrzeCUma0N2Nj5pNpSHg==", + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, "dependencies": { - "tslib": "^2.3.0" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, - "peerDependencies": { - "@angular/common": "^17.0.0 || ^18.0.0", - "@angular/core": "^17.0.0 || ^18.0.0", - "@angular/forms": "^17.0.0 || ^18.0.0", - "rxjs": "^6.0.0 || ^7.8.1", - "zone.js": "~0.14.0" + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/primeng-sass-theme": { - "version": "17.18.0", - "resolved": "git+ssh://git@github.com/primefaces/primeng-sass-theme.git#3309f0ec9a597109490e26d05cf35d3c4e188f60" - }, - "node_modules/proc-log": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", - "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", + "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", "dev": true, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "14 || >=16.14" } }, - "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==", + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "engines": { - "node": ">= 0.6.0" + "node": ">=8" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, "engines": { - "node": ">=0.4.0" + "node": ">=0.12" } }, - "node_modules/promise-inflight": { + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/picocolors": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "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==", + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "bin": { + "pidtree": "bin/pidtree.js" }, "engines": { - "node": ">= 0.10" + "node": ">=0.10" } }, - "node_modules/proxy-addr/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==", + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, + "optional": true, "engines": { - "node": ">= 0.10" + "node": ">=6" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "node_modules/piscina": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.6.1.tgz", + "integrity": "sha512-z30AwWGtQE+Apr+2WBZensP2lIvwoaMcOPkQlIEmSGMJNUvaYACylPYrQM6wSdUNJlnDVMSpLv7xTMJqlVshOA==", "dev": true, - "optional": true + "optionalDependencies": { + "nice-napi": "^1.0.2" + } }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", "dev": true, "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/public-encrypt/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==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, "engines": { - "node": ">=6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/qs": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", - "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, "dependencies": { - "side-channel": "^1.0.6" + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=0.6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, "engines": { - "node": ">=0.4.x" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "node_modules/pkg-dir/node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dev": true, "dependencies": { - "safe-buffer": "^5.1.0" + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" } }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "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, - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, "engines": { - "node": ">= 0.6" + "node": "^10 || ^12 || >=14" } }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "node_modules/postcss-loader": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", + "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", "dev": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "cosmiconfig": "^9.0.0", + "jiti": "^1.20.0", + "semver": "^7.5.4" }, "engines": { - "node": ">= 0.8" + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", "dev": true, "engines": { - "node": ">= 0.8" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", "dev": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/read-config-file": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", - "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", "dev": true, "dependencies": { - "config-file-ts": "^0.2.4", - "dotenv": "^9.0.2", - "dotenv-expand": "^5.1.0", - "js-yaml": "^4.1.0", - "json5": "^2.2.0", - "lazy-val": "^1.0.4" + "postcss-selector-parser": "^6.0.4" }, "engines": { - "node": ">=12.0.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "icss-utils": "^5.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "node_modules/postcss-selector-parser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", + "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", "dev": true, "dependencies": { - "pify": "^3.0.0" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { "node": ">=4" } }, - "node_modules/read-pkg/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", "dev": true, "bin": { - "semver": "bin/semver" - } - }, - "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" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">= 6" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/readdir-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", - "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", - "dev": true, - "peer": true, - "dependencies": { - "minimatch": "^5.1.0" - } + "node_modules/primeflex": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/primeflex/-/primeflex-3.3.1.tgz", + "integrity": "sha512-zaOq3YvcOYytbAmKv3zYc+0VNS9Wg5d37dfxZnveKBFPr7vEIwfV5ydrpiouTft8MVW6qNjfkaQphHSnvgQbpQ==" }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, + "node_modules/primeicons": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-7.0.0.tgz", + "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==" + }, + "node_modules/primeng": { + "version": "17.18.2", + "resolved": "https://registry.npmjs.org/primeng/-/primeng-17.18.2.tgz", + "integrity": "sha512-2uux//0AOj/EwiOQHmUVFst+9dtf4duNLI+Oo6vN3HLXoQF+Eax5Mfi5eHh+EDSJMFCrzeCUma0N2Nj5pNpSHg==", "dependencies": { - "picomatch": "^2.2.1" + "tslib": "^2.3.0" }, - "engines": { - "node": ">=8.10.0" + "peerDependencies": { + "@angular/common": "^17.0.0 || ^18.0.0", + "@angular/core": "^17.0.0 || ^18.0.0", + "@angular/forms": "^17.0.0 || ^18.0.0", + "rxjs": "^6.0.0 || ^7.8.1", + "zone.js": "~0.14.0" } }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/primeng-sass-theme": { + "version": "17.18.0", + "resolved": "git+ssh://git@github.com/primefaces/primeng-sass-theme.git#3309f0ec9a597109490e26d05cf35d3c4e188f60" + }, + "node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "dev": true, "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "dev": true - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "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==", "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, "engines": { - "node": ">=4" + "node": ">= 0.6.0" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/regex-parser": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", - "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==", + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true }, - "node_modules/regexp.prototype.flags": { - "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==", + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "err-code": "^2.0.2", + "retry": "^0.12.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "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==", "dev": true, "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, "engines": { - "node": ">=4" + "node": ">= 0.10" } }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "node_modules/proxy-addr/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==", "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" + "engines": { + "node": ">= 0.10" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "optional": true }, - "node_modules/require-from-string": { - "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==", + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "node_modules/public-encrypt/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==", "dev": true }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "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": ">=4" + "node": ">=6" } }, - "node_modules/resolve-url-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", - "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", + "node_modules/qs": { + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", + "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", "dev": true, "dependencies": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.14", - "source-map": "0.6.1" + "side-channel": "^1.0.6" }, "engines": { - "node": ">=12" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-url-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, "engines": { - "node": ">=8.9.0" + "node": ">=0.4.x" } }, - "node_modules/resolve-url-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "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/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, - "dependencies": { - "lowercase-keys": "^2.0.0" + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" + "safe-buffer": "^5.1.0" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, - "engines": { - "node": ">= 4" + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "engines": { + "node": ">= 0.8" } }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, "engines": { - "node": ">=8.0" + "node": ">= 0.8" } }, - "node_modules/rollup": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", - "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.0", - "@rollup/rollup-android-arm64": "4.18.0", - "@rollup/rollup-darwin-arm64": "4.18.0", - "@rollup/rollup-darwin-x64": "4.18.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", - "@rollup/rollup-linux-arm-musleabihf": "4.18.0", - "@rollup/rollup-linux-arm64-gnu": "4.18.0", - "@rollup/rollup-linux-arm64-musl": "4.18.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", - "@rollup/rollup-linux-riscv64-gnu": "4.18.0", - "@rollup/rollup-linux-s390x-gnu": "4.18.0", - "@rollup/rollup-linux-x64-gnu": "4.18.0", - "@rollup/rollup-linux-x64-musl": "4.18.0", - "@rollup/rollup-win32-arm64-msvc": "4.18.0", - "@rollup/rollup-win32-ia32-msvc": "4.18.0", - "@rollup/rollup-win32-x64-msvc": "4.18.0", - "fsevents": "~2.3.2" + "node": ">=0.10.0" } }, - "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "node_modules/read-config-file": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", "dev": true, - "engines": { - "node": ">=18" + "dependencies": { + "config-file-ts": "^0.2.4", + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=12.0.0" } }, - "node_modules/run-async": { + "node_modules/read-pkg": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", - "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, "engines": { - "node": ">=0.12.0" + "node": ">=4" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, - "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": { - "queue-microtask": "^1.2.2" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, "dependencies": { - "tslib": "^2.1.0" + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "node_modules/read-pkg/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "bin": { + "semver": "bin/semver" + } }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "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": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 6" } }, - "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 - }, - "node_modules/sanitize-filename": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", "dev": true, + "peer": true, "dependencies": { - "truncate-utf8-bytes": "^1.0.0" + "minimatch": "^5.1.0" } }, - "node_modules/sass": { - "version": "1.77.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.2.tgz", - "integrity": "sha512-eb4GZt1C3avsX3heBNlrc7I09nyT00IUuo4eFhAbeXWU2fvA7oXI53SxODVAA+zgZCk9aunAZgO+losjR3fAwA==", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" + "picomatch": "^2.2.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=8.10.0" } }, - "node_modules/sass-loader": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-14.2.1.tgz", - "integrity": "sha512-G0VcnMYU18a4N7VoNDegg2OuMjYtxnqzQWARVWCIVSZwJeiL9kg8QMsuIZOplsJgTzZLF6jGxI3AClj8I9nRdQ==", + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "dependencies": { - "neo-async": "^2.6.2" - }, "engines": { - "node": ">= 18.12.0" + "node": ">=8.6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "webpack": { - "optional": true - } + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "dev": true }, - "node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "regenerate": "^1.4.2" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=4" } }, - "node_modules/schema-utils/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==", + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "@babel/runtime": "^7.8.4" } }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "node_modules/regex-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", + "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==", "dev": true }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "node_modules/regexp.prototype.flags": { + "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": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "optional": true - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", "dev": true, "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "jsesc": "~0.5.0" }, - "engines": { - "node": ">= 0.8.0" + "bin": { + "regjsparser": "bin/parser" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", "dev": true, - "dependencies": { - "ms": "2.0.0" + "bin": { + "jsesc": "bin/jsesc" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "node_modules/require-from-string": { + "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, - "bin": { - "mime": "cli.js" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, - "optional": true, "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" + "bin": { + "resolve": "bin/resolve" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, "engines": { - "node": ">= 0.8.0" + "node": ">=4" } }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/resolve-url-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", + "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", "dev": true, "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" + }, "engines": { - "node": ">= 0.6" + "node": ">=12" } }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, "engines": { - "node": ">= 0.6" + "node": ">=8.9.0" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", "dev": true, "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" + "lowercase-keys": "^2.0.0" }, - "engines": { - "node": ">= 0.8.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/set-function-name": { - "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==", + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">= 4" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true + "node_modules/reusify": { + "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/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "glob": "^7.1.3" }, "bin": { - "sha.js": "bin.js" + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "dependencies": { - "kind-of": "^6.0.2" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" }, "engines": { - "node": ">=8" + "node": ">=8.0" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/rollup": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz", + "integrity": "sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==", "dev": true, "dependencies": { - "shebang-regex": "^3.0.0" + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=8" + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.1", + "@rollup/rollup-android-arm64": "4.18.1", + "@rollup/rollup-darwin-arm64": "4.18.1", + "@rollup/rollup-darwin-x64": "4.18.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.1", + "@rollup/rollup-linux-arm-musleabihf": "4.18.1", + "@rollup/rollup-linux-arm64-gnu": "4.18.1", + "@rollup/rollup-linux-arm64-musl": "4.18.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.1", + "@rollup/rollup-linux-riscv64-gnu": "4.18.1", + "@rollup/rollup-linux-s390x-gnu": "4.18.1", + "@rollup/rollup-linux-x64-gnu": "4.18.1", + "@rollup/rollup-linux-x64-musl": "4.18.1", + "@rollup/rollup-win32-arm64-msvc": "4.18.1", + "@rollup/rollup-win32-ia32-msvc": "4.18.1", + "@rollup/rollup-win32-x64-msvc": "4.18.1", + "fsevents": "~2.3.2" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", "dev": true, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "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": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "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.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "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/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.6", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "is-regex": "^1.1.4" }, "engines": { "node": ">= 0.4" @@ -15733,390 +15963,455 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "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 }, - "node_modules/sigstore": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.3.1.tgz", - "integrity": "sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==", + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", "dev": true, "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^2.3.2", - "@sigstore/tuf": "^2.3.4", - "@sigstore/verify": "^1.2.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" + "truncate-utf8-bytes": "^1.0.0" } }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "node_modules/sass": { + "version": "1.77.6", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz", + "integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==", "dev": true, "dependencies": { - "semver": "^7.5.3" + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" }, "engines": { - "node": ">=10" + "node": ">=14.0.0" } }, - "node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/sass-loader": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-14.2.1.tgz", + "integrity": "sha512-G0VcnMYU18a4N7VoNDegg2OuMjYtxnqzQWARVWCIVSZwJeiL9kg8QMsuIZOplsJgTzZLF6jGxI3AClj8I9nRdQ==", "dev": true, + "dependencies": { + "neo-async": "^2.6.2" + }, "engines": { - "node": ">=12" + "node": ">= 18.12.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "dev": true + }, + "node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", "dev": true, - "optional": true, "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">=8" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/schema-utils/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==", "dev": true, - "optional": true, "dependencies": { - "color-convert": "^2.0.1" + "ajv": "^8.0.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "ajv": "^8.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, - "optional": true, "dependencies": { - "color-name": "~1.1.4" + "@types/node-forge": "^1.3.0", + "node-forge": "^1" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" } }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "optional": true - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "node": ">=10" } }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } + "optional": true }, - "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dev": true, "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" + "node": ">= 0.8.0" } }, - "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">= 14" + "node": ">=4" } }, - "node_modules/socks-proxy-agent/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", "dev": true, + "optional": true, "dependencies": { - "debug": "^4.3.4" + "type-fest": "^0.13.1" }, "engines": { - "node": ">= 14" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true, + "optional": true, "engines": { - "node": ">= 8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "randombytes": "^2.1.0" } }, - "node_modules/source-map-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-5.0.0.tgz", - "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", "dev": true, "dependencies": { - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.2" + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.72.1" + "node": ">= 0.8.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "ms": "2.0.0" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", "dev": true, "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", "dev": true }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true }, - "node_modules/spdx-license-ids": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", - "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, "engines": { - "node": ">=6.0.0" + "node": ">= 0.6" } }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dev": true, "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true - }, - "node_modules/ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "minipass": "^7.0.3" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 0.4" } }, - "node_modules/stat-mode": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", - "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "node_modules/set-function-name": { + "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==", "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">= 6" + "node": ">= 0.4" } }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dev": true, - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true }, - "node_modules/stream-http": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", - "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" } }, - "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==", + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "dependencies": { - "safe-buffer": "~5.2.0" + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, "engines": { "node": ">=8" } }, - "node_modules/string.prototype.padend": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", - "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" }, "engines": { "node": ">= 0.4" @@ -16125,1486 +16420,1484 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sigstore": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.3.1.tgz", + "integrity": "sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "@sigstore/bundle": "^2.3.2", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "@sigstore/sign": "^2.3.2", + "@sigstore/tuf": "^2.3.4", + "@sigstore/verify": "^1.2.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "semver": "^7.5.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, + "optional": true, "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "optional": true, "dependencies": { - "ansi-regex": "^5.0.1" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "optional": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=4" + "node": ">=7.0.0" } }, - "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==", + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "optional": true + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, "engines": { - "node": ">=6" + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" } }, - "node_modules/sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dev": true, "dependencies": { - "debug": "^4.1.0" + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 8.0" + "node": ">= 10.0.0", + "npm": ">= 3.0.0" } }, - "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==", + "node_modules/socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">=4" + "node": ">= 14" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, - "engines": { - "node": ">= 0.4" + "dependencies": { + "debug": "^4.3.4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 14" } }, - "node_modules/symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, "engines": { - "node": ">=0.10" + "node": ">= 8" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "node_modules/source-map-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-5.0.0.tgz", + "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", "dev": true, "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.72.1" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, - "peer": true, "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/spdx-exceptions": { + "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": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/spdx-license-ids": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", + "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" } }, - "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==", + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, - "node_modules/temp-file": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", - "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", - "dev": true, - "dependencies": { - "async-exit-hook": "^2.0.1", - "fs-extra": "^10.0.0" - } - }, - "node_modules/temp-file/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "node_modules/ssri": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">=12" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/temp-file/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">= 6" } }, - "node_modules/temp-file/node_modules/universalify": { + "node_modules/statuses": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">= 0.8" } }, - "node_modules/terser": { - "version": "5.31.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", - "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", "dev": true, "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "safe-buffer": "~5.2.0" } }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/string.prototype.padend": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", + "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/thingies": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", - "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "node_modules/string.prototype.trim": { + "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.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">=10.18" + "node": ">= 0.4" }, - "peerDependencies": { - "tslib": "^2" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true + "node_modules/string.prototype.trimend": { + "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.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "node_modules/string.prototype.trimstart": { + "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": { - "setimmediate": "^1.0.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=0.6.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "os-tmpdir": "~1.0.2" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=0.6.0" + "node": ">=8" } }, - "node_modules/tmp-promise": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", - "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "tmp": "^0.2.0" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/tmp-promise/node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "engines": { - "node": ">=14.14" + "node": ">=4" } }, - "node_modules/to-fast-properties": { + "node_modules/strip-final-newline": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", "dev": true, "dependencies": { - "is-number": "^7.0.0" + "debug": "^4.1.0" }, "engines": { - "node": ">=8.0" + "node": ">= 8.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "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": ">=0.6" + "node": ">=4" } }, - "node_modules/tree-dump": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", - "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "engines": { - "node": ">=10.0" + "node": ">= 0.4" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", "dev": true, - "dependencies": { - "utf8-byte-length": "^1.0.1" + "engines": { + "node": ">=0.10" } }, - "node_modules/ts-api-utils": { - "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==", + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" + "node": ">=6" } }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "node_modules/tar": { + "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": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, + "peer": true, "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" }, "engines": { "node": ">=6" } }, - "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" - }, - "node_modules/tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", - "dev": true - }, - "node_modules/tuf-js": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz", - "integrity": "sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==", + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, "dependencies": { - "@tufjs/models": "2.0.1", - "debug": "^4.3.4", - "make-fetch-happen": "^13.0.1" + "minipass": "^3.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "prelude-ls": "^1.2.1" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, "engines": { - "node": ">=10" + "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/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=12" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/temp-file/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "universalify": "^2.0.0" }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/temp-file/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": ">= 10.0.0" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "node_modules/terser": { + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", + "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" }, "engines": { - "node": ">= 0.4" + "node": ">=10" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 10.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "node_modules/typed-array-byte-offset": { - "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==", + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/typed-array-length": { - "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==", + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" }, "engines": { - "node": ">= 0.4" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "dev": true, + "engines": { + "node": ">=10.18" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "tslib": "^2" } }, - "node_modules/typed-assert": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", - "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, - "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "dependencies": { + "setimmediate": "^1.0.4" }, "engines": { - "node": ">=14.17" + "node": ">=0.6.0" } }, - "node_modules/typescript-eslint": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.14.1.tgz", - "integrity": "sha512-Eo1X+Y0JgGPspcANKjeR6nIqXl4VL5ldXLc15k4m9upq+eY5fhU2IueiEZL6jmHrKH8aCfbIvM/v3IrX5Hg99w==", + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "7.14.1", - "@typescript-eslint/parser": "7.14.1", - "@typescript-eslint/utils": "7.14.1" + "os-tmpdir": "~1.0.2" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=0.6.0" } }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "tmp": "^0.2.0" } }, - "node_modules/undici": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.18.0.tgz", - "integrity": "sha512-nT8jjv/fE9Et1ilR6QoW8ingRTY2Pp4l2RUrdzV5Yz35RJDrtPc1DXvuNqcpsJSGIRHFdt3YKKktTzJA6r0fTA==", + "node_modules/tmp-promise/node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, "engines": { - "node": ">=18.17" + "node": ">=14.14" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { + "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "is-number": "^7.0.0" }, "engines": { - "node": ">=4" + "node": ">=8.0" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.6" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "node_modules/tree-dump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", "dev": true, "engines": { - "node": ">=4" - } - }, - "node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "dependencies": { - "unique-slug": "^4.0.0" + "node": ">=10.0" }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "bin": { + "tree-kill": "cli.js" } }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", "dev": true, - "engines": { - "node": ">= 4.0.0" + "dependencies": { + "utf8-byte-length": "^1.0.1" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/ts-api-utils": { + "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": ">= 0.8" + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" }, "bin": { - "update-browserslist-db": "cli.js" + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" }, "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "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" + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.11.2" + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, - "node_modules/utf8-byte-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", - "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", "dev": true }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "node_modules/tuf-js": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz", + "integrity": "sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" + "@tufjs/models": "2.0.1", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.8.0" } }, - "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==", + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "node_modules/typed-array-buffer": { + "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.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 0.4" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "node_modules/typed-array-byte-length": { + "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.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/verror": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", - "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "node_modules/typed-array-byte-offset": { + "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, - "optional": true, "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">=0.6.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vite": { - "version": "5.2.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz", - "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==", + "node_modules/typed-array-length": { + "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": { - "esbuild": "^0.20.1", - "postcss": "^8.4.38", - "rollup": "^4.13.0" - }, - "bin": { - "vite": "bin/vite.js" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", - "cpu": [ - "ppc64" - ], + "node_modules/typed-assert": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", + "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", + "dev": true + }, + "node_modules/typescript": { + "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, - "optional": true, - "os": [ - "aix" - ], + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=12" + "node": ">=14.17" } }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "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" - ], + "node_modules/typescript-eslint": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.14.1.tgz", + "integrity": "sha512-Eo1X+Y0JgGPspcANKjeR6nIqXl4VL5ldXLc15k4m9upq+eY5fhU2IueiEZL6jmHrKH8aCfbIvM/v3IrX5Hg99w==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.14.1", + "@typescript-eslint/parser": "7.14.1", + "@typescript-eslint/utils": "7.14.1" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "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" - ], + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", - "cpu": [ - "x64" - ], + "node_modules/undici": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.2.tgz", + "integrity": "sha512-JfjKqIauur3Q6biAtHJ564e3bWa8VvT+7cSiOJHFbX4Erv6CLGDpg8z+Fmg/1OI/47RA+GI2QZaF48SSaLvyBA==", "dev": true, - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=12" + "node": ">=18.17" } }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "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" - ], + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "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" - ], + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", - "cpu": [ - "arm64" - ], + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "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" - ], + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", - "cpu": [ - "arm" - ], + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "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" - ], + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "unique-slug": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", - "cpu": [ - "ia32" - ], + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "imurmurhash": "^0.1.4" + }, "engines": { - "node": ">=12" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "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" - ], + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">= 4.0.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "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" - ], + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "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" - ], + "node_modules/update-browserslist-db": { + "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, - "optional": true, - "os": [ - "linux" + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } ], - "engines": { - "node": ">=12" + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "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" - ], + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "punycode": "^2.1.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "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" - ], + "node_modules/url": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.11.2" } }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "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" - ], + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", - "cpu": [ - "x64" - ], + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, - "optional": true, - "os": [ - "netbsd" - ], "engines": { - "node": ">=12" + "node": ">= 0.4.0" } }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "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" - ], + "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==", "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "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" - ], + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "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" - ], + "node_modules/validate-npm-package-name": { + "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, - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "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" - ], + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "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" - ], + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", "dev": true, "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, "engines": { - "node": ">=12" + "node": ">=0.6.0" } }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "node_modules/vite": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.2.tgz", + "integrity": "sha512-6lA7OBHBlXUxiJxbO5aAY2fsHHzDr1q7DvXYnyZycRs2Dz+dXBWuhpWHvmljTRTpQC2uvGmUFFkSHF2vGo90MA==", "dev": true, - "hasInstallScript": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + }, "bin": { - "esbuild": "bin/esbuild" + "vite": "bin/vite.js" }, "engines": { - "node": ">=12" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "@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" + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, "node_modules/vm-browserify": { @@ -17674,7 +17967,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz", "integrity": "sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==", "dev": true, - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", @@ -17805,22 +18097,10 @@ } } }, - "node_modules/webpack-dev-server/node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/webpack-dev-server/node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", @@ -17833,9 +18113,6 @@ "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -17864,21 +18141,6 @@ } } }, - "node_modules/webpack-dev-server/node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/webpack-dev-server/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -17894,28 +18156,10 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/webpack-dev-server/node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", - "dev": true, - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/webpack-dev-server/node_modules/rimraf": { - "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==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.9.tgz", + "integrity": "sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA==", "dev": true, "dependencies": { "glob": "^10.3.7" @@ -17924,7 +18168,7 @@ "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": ">=14.18" + "node": "14 >=14.20 || 16 >=16.20 || >=18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -17979,7 +18223,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -17996,7 +18239,6 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, - "peer": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -18006,7 +18248,6 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -18020,7 +18261,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "peer": true, "engines": { "node": ">=4.0" } @@ -18029,22 +18269,19 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "peer": true + "dev": true }, "node_modules/webpack/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/webpack/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, - "peer": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -18256,9 +18493,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "engines": { "node": ">=10.0.0" @@ -18367,6 +18604,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zip-stream": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", diff --git a/desktop/package.json b/desktop/package.json index 85a10d154..bb8282440 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -34,15 +34,15 @@ "prettier:json": "npx prettier '**/*.json' --write" }, "dependencies": { - "@angular/animations": "18.0.5", - "@angular/cdk": "18.0.5", - "@angular/common": "18.0.5", - "@angular/compiler": "18.0.5", - "@angular/core": "18.0.5", - "@angular/forms": "18.0.5", - "@angular/platform-browser": "18.0.5", - "@angular/platform-browser-dynamic": "18.0.5", - "@angular/router": "18.0.5", + "@angular/animations": "18.1.0", + "@angular/cdk": "18.1.0", + "@angular/common": "18.1.0", + "@angular/compiler": "18.1.0", + "@angular/core": "18.1.0", + "@angular/forms": "18.1.0", + "@angular/platform-browser": "18.1.0", + "@angular/platform-browser-dynamic": "18.1.0", + "@angular/router": "18.1.0", "@mdi/font": "7.4.47", "chart.js": "4.4.3", "chartjs-plugin-zoom": "2.0.1", @@ -62,10 +62,10 @@ }, "devDependencies": { "@angular-builders/custom-webpack": "18.0.0", - "@angular-devkit/build-angular": "18.0.6", - "@angular/cli": "18.0.6", - "@angular/compiler-cli": "18.0.5", - "@angular/language-service": "18.0.5", + "@angular-devkit/build-angular": "18.1.0", + "@angular/cli": "18.1.0", + "@angular/compiler-cli": "18.1.0", + "@angular/language-service": "18.1.0", "@eslint/js": "9.6.0", "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", From 97f01606c7ec722a1cd9c8f24e17f1e096fc4c4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:20:08 +0000 Subject: [PATCH 024/104] [desktop]: Bump electron from 31.1.0 to 31.2.0 in /desktop Bumps [electron](https://github.com/electron/electron) from 31.1.0 to 31.2.0. - [Release notes](https://github.com/electron/electron/releases) - [Changelog](https://github.com/electron/electron/blob/main/docs/breaking-changes.md) - [Commits](https://github.com/electron/electron/compare/v31.1.0...v31.2.0) --- updated-dependencies: - dependency-name: electron dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 8 ++++---- desktop/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index beb2973e1..6852dae47 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -46,7 +46,7 @@ "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", "@types/node": "20.14.10", - "electron": "31.1.0", + "electron": "31.2.0", "electron-builder": "24.13.3", "eslint": "8.57.0", "node-polyfill-webpack-plugin": "4.0.0", @@ -8915,9 +8915,9 @@ } }, "node_modules/electron": { - "version": "31.1.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-31.1.0.tgz", - "integrity": "sha512-TBOwqLxSxnx6+pH6GMri7R3JPH2AkuGJHfWZS0p1HsmN+Qr1T9b0IRJnnehSd/3NZAmAre4ft9Ljec7zjyKFJA==", + "version": "31.2.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-31.2.0.tgz", + "integrity": "sha512-5w+kjOsGiTXytPSErBPNp/3znnuEMKc42RD41MqRoQkiYaR8x/Le2+qWk1cL60UwE/67oeKnOHnnol8xEuldGg==", "dev": true, "hasInstallScript": true, "dependencies": { diff --git a/desktop/package.json b/desktop/package.json index bb8282440..edfbae2cf 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -70,7 +70,7 @@ "@types/eslint__js": "8.42.3", "@types/leaflet": "1.9.12", "@types/node": "20.14.10", - "electron": "31.1.0", + "electron": "31.2.0", "electron-builder": "24.13.3", "eslint": "8.57.0", "node-polyfill-webpack-plugin": "4.0.0", From 80197a958d33a7da435633a9c28fd72c2968c4ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:26:21 +0000 Subject: [PATCH 025/104] [desktop]: Bump typescript-eslint from 7.14.1 to 7.16.0 in /desktop Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 7.14.1 to 7.16.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.16.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: typescript-eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 98 +++++++++++++++++++-------------------- desktop/package.json | 2 +- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 6852dae47..8da80da33 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -54,7 +54,7 @@ "prettier": "3.3.2", "ts-node": "10.9.2", "typescript": "5.4.5", - "typescript-eslint": "7.14.1", + "typescript-eslint": "7.16.0", "wait-on": "7.2.0" }, "engines": { @@ -5581,16 +5581,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz", - "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", + "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/type-utils": "7.14.1", - "@typescript-eslint/utils": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/type-utils": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -5614,15 +5614,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", + "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/typescript-estree": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", "debug": "^4.3.4" }, "engines": { @@ -5642,13 +5642,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", - "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", + "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1" + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -5659,13 +5659,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz", - "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", + "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.14.1", - "@typescript-eslint/utils": "7.14.1", + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/utils": "7.16.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -5686,9 +5686,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -5699,13 +5699,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", - "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -5771,15 +5771,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", - "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/typescript-estree": "7.14.1" + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -5793,12 +5793,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", - "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", + "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/types": "7.16.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -17549,14 +17549,14 @@ } }, "node_modules/typescript-eslint": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.14.1.tgz", - "integrity": "sha512-Eo1X+Y0JgGPspcANKjeR6nIqXl4VL5ldXLc15k4m9upq+eY5fhU2IueiEZL6jmHrKH8aCfbIvM/v3IrX5Hg99w==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", + "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "7.14.1", - "@typescript-eslint/parser": "7.14.1", - "@typescript-eslint/utils": "7.14.1" + "@typescript-eslint/eslint-plugin": "7.16.0", + "@typescript-eslint/parser": "7.16.0", + "@typescript-eslint/utils": "7.16.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" diff --git a/desktop/package.json b/desktop/package.json index edfbae2cf..276785e05 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -78,7 +78,7 @@ "prettier": "3.3.2", "ts-node": "10.9.2", "typescript": "5.4.5", - "typescript-eslint": "7.14.1", + "typescript-eslint": "7.16.0", "wait-on": "7.2.0" }, "overrides": { From 9622c5e7ef3772efdb0292927315e39e9d65d26f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:30:53 +0000 Subject: [PATCH 026/104] [desktop]: Bump primeng from 17.18.2 to 17.18.3 in /desktop Bumps [primeng](https://github.com/primefaces/primeng) from 17.18.2 to 17.18.3. - [Release notes](https://github.com/primefaces/primeng/releases) - [Changelog](https://github.com/primefaces/primeng/blob/master/CHANGELOG.md) - [Commits](https://github.com/primefaces/primeng/compare/17.18.2...17.18.3) --- updated-dependencies: - dependency-name: primeng dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 8 ++++---- desktop/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 8da80da33..5f46ca594 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -30,7 +30,7 @@ "panzoom": "9.4.3", "primeflex": "3.3.1", "primeicons": "7.0.0", - "primeng": "17.18.2", + "primeng": "17.18.3", "primeng-sass-theme": "github:primefaces/primeng-sass-theme#17.18.0", "rxjs": "7.8.1", "tslib": "2.6.3", @@ -15149,9 +15149,9 @@ "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==" }, "node_modules/primeng": { - "version": "17.18.2", - "resolved": "https://registry.npmjs.org/primeng/-/primeng-17.18.2.tgz", - "integrity": "sha512-2uux//0AOj/EwiOQHmUVFst+9dtf4duNLI+Oo6vN3HLXoQF+Eax5Mfi5eHh+EDSJMFCrzeCUma0N2Nj5pNpSHg==", + "version": "17.18.3", + "resolved": "https://registry.npmjs.org/primeng/-/primeng-17.18.3.tgz", + "integrity": "sha512-gbFo9cZF3E2ox8MkIPMp5CuqACMkJwgpjjNofzI2gh/9BKnAWB4Iao7mLKTlU46CtzHsmslQ9lU8OmmKG7LG1A==", "dependencies": { "tslib": "^2.3.0" }, diff --git a/desktop/package.json b/desktop/package.json index 276785e05..3ed954200 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -54,7 +54,7 @@ "panzoom": "9.4.3", "primeflex": "3.3.1", "primeicons": "7.0.0", - "primeng": "17.18.2", + "primeng": "17.18.3", "primeng-sass-theme": "github:primefaces/primeng-sass-theme#17.18.0", "rxjs": "7.8.1", "tslib": "2.6.3", From 71491f45d93743a49aa7c0ea399b58e7999602bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:33:20 +0000 Subject: [PATCH 027/104] [desktop]: Bump primeng-sass-theme from 17.18.0 to 17.18.3 in /desktop Bumps [primeng-sass-theme](https://github.com/primefaces/primeng-sass-theme) from 17.18.0 to 17.18.3. - [Release notes](https://github.com/primefaces/primeng-sass-theme/releases) - [Changelog](https://github.com/primefaces/primeng-sass-theme/blob/main/CHANGELOG.md) - [Commits](https://github.com/primefaces/primeng-sass-theme/compare/3309f0ec9a597109490e26d05cf35d3c4e188f60...2f7b1705c8783a098381c078345eb5dbe45c4008) --- updated-dependencies: - dependency-name: primeng-sass-theme dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 8 +++++--- desktop/package.json | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 5f46ca594..29a7541da 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -31,7 +31,7 @@ "primeflex": "3.3.1", "primeicons": "7.0.0", "primeng": "17.18.3", - "primeng-sass-theme": "github:primefaces/primeng-sass-theme#17.18.0", + "primeng-sass-theme": "github:primefaces/primeng-sass-theme#17.18.3", "rxjs": "7.8.1", "tslib": "2.6.3", "zone.js": "0.14.7" @@ -15164,8 +15164,10 @@ } }, "node_modules/primeng-sass-theme": { - "version": "17.18.0", - "resolved": "git+ssh://git@github.com/primefaces/primeng-sass-theme.git#3309f0ec9a597109490e26d05cf35d3c4e188f60" + "version": "17.18.3", + "resolved": "git+ssh://git@github.com/primefaces/primeng-sass-theme.git#2f7b1705c8783a098381c078345eb5dbe45c4008", + "integrity": "sha512-SUuLlE4Z06XIswSrmiFK9pK5Vx90WzZuB6s0qo79POGCRUtrct+O6K0rjfItmRlDpXRKPdKeGmrsXP0xx70GzQ==", + "license": "MIT" }, "node_modules/proc-log": { "version": "4.2.0", diff --git a/desktop/package.json b/desktop/package.json index 3ed954200..501a741b8 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -55,7 +55,7 @@ "primeflex": "3.3.1", "primeicons": "7.0.0", "primeng": "17.18.3", - "primeng-sass-theme": "github:primefaces/primeng-sass-theme#17.18.0", + "primeng-sass-theme": "github:primefaces/primeng-sass-theme#17.18.3", "rxjs": "7.8.1", "tslib": "2.6.3", "zone.js": "0.14.7" From 4b1e68f26de74b81ef49174274e1f0e9e2846570 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Wed, 10 Jul 2024 16:38:11 -0300 Subject: [PATCH 028/104] [desktop]: Bump typescript from 5.4 to 5.5 --- desktop/package-lock.json | 8 ++++---- desktop/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 29a7541da..6745f6365 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -53,7 +53,7 @@ "npm-run-all": "4.1.5", "prettier": "3.3.2", "ts-node": "10.9.2", - "typescript": "5.4.5", + "typescript": "5.5.3", "typescript-eslint": "7.16.0", "wait-on": "7.2.0" }, @@ -17538,9 +17538,9 @@ "dev": true }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/desktop/package.json b/desktop/package.json index 501a741b8..70022a9fa 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -77,7 +77,7 @@ "npm-run-all": "4.1.5", "prettier": "3.3.2", "ts-node": "10.9.2", - "typescript": "5.4.5", + "typescript": "5.5.3", "typescript-eslint": "7.16.0", "wait-on": "7.2.0" }, From fabb4c570570cae0bdfe3690ec3d09311f523d86 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Wed, 10 Jul 2024 16:40:30 -0300 Subject: [PATCH 029/104] [desktop]: Upgrade NPM dependencies --- desktop/package-lock.json | 1011 +++++++++++-------------------------- 1 file changed, 307 insertions(+), 704 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 6745f6365..b97e74e4c 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -252,343 +252,6 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/@angular/build": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.1.0.tgz", - "integrity": "sha512-4yLrGqMDoNBis2Z4s8F3wSqlB2XLtwy/10tREBk9xVaCojERiwDvtHqzbMeHqD6ZMGDFtdhI12q8FT5jZVUmAw==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1801.0", - "@babel/core": "7.24.7", - "@babel/helper-annotate-as-pure": "7.24.7", - "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-syntax-import-attributes": "7.24.7", - "@inquirer/confirm": "3.1.11", - "@vitejs/plugin-basic-ssl": "1.1.0", - "ansi-colors": "4.1.3", - "browserslist": "^4.23.0", - "critters": "0.0.24", - "esbuild": "0.21.5", - "fast-glob": "3.3.2", - "https-proxy-agent": "7.0.5", - "lmdb": "3.0.12", - "magic-string": "0.30.10", - "mrmime": "2.0.0", - "ora": "5.4.1", - "parse5-html-rewriting-stream": "7.0.0", - "picomatch": "4.0.2", - "piscina": "4.6.1", - "rollup": "4.18.0", - "sass": "1.77.6", - "semver": "7.6.2", - "undici": "6.19.2", - "vite": "5.3.2", - "watchpack": "2.4.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "@angular/compiler-cli": "^18.0.0", - "@angular/localize": "^18.0.0", - "@angular/platform-server": "^18.0.0", - "@angular/service-worker": "^18.0.0", - "less": "^4.2.0", - "postcss": "^8.4.0", - "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.4 <5.6" - }, - "peerDependenciesMeta": { - "@angular/localize": { - "optional": true - }, - "@angular/platform-server": { - "optional": true - }, - "@angular/service-worker": { - "optional": true - }, - "less": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tailwindcss": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", - "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", - "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", - "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", - "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", - "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", - "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", - "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", - "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", - "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", - "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", - "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", - "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", - "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", - "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", - "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", - "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/rollup": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", - "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.0", - "@rollup/rollup-android-arm64": "4.18.0", - "@rollup/rollup-darwin-arm64": "4.18.0", - "@rollup/rollup-darwin-x64": "4.18.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", - "@rollup/rollup-linux-arm-musleabihf": "4.18.0", - "@rollup/rollup-linux-arm64-gnu": "4.18.0", - "@rollup/rollup-linux-arm64-musl": "4.18.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", - "@rollup/rollup-linux-riscv64-gnu": "4.18.0", - "@rollup/rollup-linux-s390x-gnu": "4.18.0", - "@rollup/rollup-linux-x64-gnu": "4.18.0", - "@rollup/rollup-linux-x64-musl": "4.18.0", - "@rollup/rollup-win32-arm64-msvc": "4.18.0", - "@rollup/rollup-win32-ia32-msvc": "4.18.0", - "@rollup/rollup-win32-x64-msvc": "4.18.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/terser": { - "version": "5.29.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz", - "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@angular-devkit/build-webpack": { "version": "0.1801.0", "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1801.0.tgz", @@ -667,6 +330,76 @@ "@angular/core": "18.1.0" } }, + "node_modules/@angular/build": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.1.0.tgz", + "integrity": "sha512-4yLrGqMDoNBis2Z4s8F3wSqlB2XLtwy/10tREBk9xVaCojERiwDvtHqzbMeHqD6ZMGDFtdhI12q8FT5jZVUmAw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "2.3.0", + "@angular-devkit/architect": "0.1801.0", + "@babel/core": "7.24.7", + "@babel/helper-annotate-as-pure": "7.24.7", + "@babel/helper-split-export-declaration": "7.24.7", + "@babel/plugin-syntax-import-attributes": "7.24.7", + "@inquirer/confirm": "3.1.11", + "@vitejs/plugin-basic-ssl": "1.1.0", + "ansi-colors": "4.1.3", + "browserslist": "^4.23.0", + "critters": "0.0.24", + "esbuild": "0.21.5", + "fast-glob": "3.3.2", + "https-proxy-agent": "7.0.5", + "lmdb": "3.0.12", + "magic-string": "0.30.10", + "mrmime": "2.0.0", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "picomatch": "4.0.2", + "piscina": "4.6.1", + "rollup": "4.18.0", + "sass": "1.77.6", + "semver": "7.6.2", + "undici": "6.19.2", + "vite": "5.3.2", + "watchpack": "2.4.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^18.0.0", + "@angular/localize": "^18.0.0", + "@angular/platform-server": "^18.0.0", + "@angular/service-worker": "^18.0.0", + "less": "^4.2.0", + "postcss": "^8.4.0", + "tailwindcss": "^2.0.0 || ^3.0.0", + "typescript": ">=5.4 <5.6" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/platform-server": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "less": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tailwindcss": { + "optional": true + } + } + }, "node_modules/@angular/cdk": { "version": "18.1.0", "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.1.0.tgz", @@ -3582,18 +3315,6 @@ "node": ">=18" } }, - "node_modules/@inquirer/checkbox/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@inquirer/confirm": { "version": "3.1.11", "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.11.tgz", @@ -3631,18 +3352,6 @@ "node": ">=18" } }, - "node_modules/@inquirer/core/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@inquirer/editor": { "version": "2.1.14", "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.14.tgz", @@ -3681,18 +3390,6 @@ "node": ">=18" } }, - "node_modules/@inquirer/editor/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@inquirer/expand": { "version": "2.1.14", "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.14.tgz", @@ -3731,18 +3428,6 @@ "node": ">=18" } }, - "node_modules/@inquirer/expand/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@inquirer/figures": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.3.tgz", @@ -3789,18 +3474,6 @@ "node": ">=18" } }, - "node_modules/@inquirer/input/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@inquirer/password": { "version": "2.1.14", "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.14.tgz", @@ -3839,18 +3512,6 @@ "node": ">=18" } }, - "node_modules/@inquirer/password/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@inquirer/prompts": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.0.7.tgz", @@ -3908,18 +3569,6 @@ "node": ">=18" } }, - "node_modules/@inquirer/rawlist/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@inquirer/select": { "version": "2.3.10", "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.3.10.tgz", @@ -3960,18 +3609,6 @@ "node": ">=18" } }, - "node_modules/@inquirer/select/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@inquirer/type": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.4.0.tgz", @@ -4137,9 +3774,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { @@ -4559,13 +4196,10 @@ } }, "node_modules/@npmcli/agent/node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/@npmcli/fs": { "version": "3.1.1", @@ -4580,12 +4214,13 @@ } }, "node_modules/@npmcli/git": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.7.tgz", - "integrity": "sha512-WaOVvto604d5IpdCRV2KjQu8PzkfE96d50CQGKgywXh2GxXmDeUO5EWcBC4V57uFyrNqx83+MewuJh3WTR3xPA==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.8.tgz", + "integrity": "sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==", "dev": true, "dependencies": { "@npmcli/promise-spawn": "^7.0.0", + "ini": "^4.1.3", "lru-cache": "^10.0.1", "npm-pick-manifest": "^9.0.0", "proc-log": "^4.0.0", @@ -4608,13 +4243,10 @@ } }, "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/@npmcli/git/node_modules/which": { "version": "4.0.0", @@ -4675,9 +4307,9 @@ } }, "node_modules/@npmcli/package-json/node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", @@ -4690,9 +4322,6 @@ "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -4710,13 +4339,10 @@ } }, "node_modules/@npmcli/package-json/node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/@npmcli/package-json/node_modules/minimatch": { "version": "9.0.5", @@ -4830,9 +4456,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", - "integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", "cpu": [ "arm" ], @@ -4843,9 +4469,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz", - "integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", "cpu": [ "arm64" ], @@ -4856,9 +4482,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz", - "integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", "cpu": [ "arm64" ], @@ -4869,9 +4495,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz", - "integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", "cpu": [ "x64" ], @@ -4882,9 +4508,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz", - "integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", "cpu": [ "arm" ], @@ -4895,9 +4521,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz", - "integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", "cpu": [ "arm" ], @@ -4908,9 +4534,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz", - "integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", "cpu": [ "arm64" ], @@ -4921,9 +4547,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz", - "integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", "cpu": [ "arm64" ], @@ -4934,9 +4560,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz", - "integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", "cpu": [ "ppc64" ], @@ -4947,9 +4573,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz", - "integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", "cpu": [ "riscv64" ], @@ -4960,9 +4586,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz", - "integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", "cpu": [ "s390x" ], @@ -4973,9 +4599,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz", - "integrity": "sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", "cpu": [ "x64" ], @@ -4986,9 +4612,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.1.tgz", - "integrity": "sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", "cpu": [ "x64" ], @@ -4999,9 +4625,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz", - "integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", "cpu": [ "arm64" ], @@ -5012,9 +4638,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz", - "integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", "cpu": [ "ia32" ], @@ -5025,9 +4651,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz", - "integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", "cpu": [ "x64" ], @@ -6041,9 +5667,9 @@ } }, "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -7041,9 +6667,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", - "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", "dev": true, "funding": [ { @@ -7060,10 +6686,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001629", - "electron-to-chromium": "^1.4.796", + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.16" + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -7338,9 +6964,9 @@ } }, "node_modules/cacache/node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", @@ -7353,21 +6979,15 @@ "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/cacache/node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/cacache/node_modules/minimatch": { "version": "9.0.5", @@ -7440,9 +7060,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001639", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001639.tgz", - "integrity": "sha512-eFHflNTBIlFwP2AIKaYuBQN/apnUoKNhBdza8ZnW/h2di4LCZ4xFqYlxUxo+LQ76KFI1PGcC1QDxMbxTZpSCAg==", + "version": "1.0.30001641", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001641.tgz", + "integrity": "sha512-Phv5thgl67bHYo1TtMY/MurjkHhV4EDaCosezRXgZ8jzA/Ub+wjxAvbGvjoFENStinwi5kCyOYV3mi5tOGykwA==", "dev": true, "funding": [ { @@ -7584,15 +7204,18 @@ } }, "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, "dependencies": { - "restore-cursor": "^3.1.0" + "restore-cursor": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cli-spinners": { @@ -7873,9 +7496,9 @@ } }, "node_modules/config-file-ts/node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", @@ -7888,9 +7511,6 @@ "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -8679,6 +8299,15 @@ "node": ">=8" } }, + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/dmg-builder": { "version": "24.13.3", "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", @@ -9235,9 +8864,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.815", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.815.tgz", - "integrity": "sha512-OvpTT2ItpOXJL7IGcYakRjHCt8L5GrrN/wHCQsRB4PQa1X9fe+X9oen245mIId7s14xvArCGSTIq644yPUKKLg==", + "version": "1.4.823", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.823.tgz", + "integrity": "sha512-4h+oPeAiGQOHFyUJOqpoEcPj/xxlicxBzOErVeYVMMmAiXUXsGpsFd0QXBMaUUbnD8hhSfLf9uw+MlsoIA7j5w==", "dev": true }, "node_modules/elliptic": { @@ -9852,9 +9481,9 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -9971,6 +9600,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/exponential-backoff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", @@ -10341,18 +9976,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -10692,18 +10315,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -11893,16 +11504,13 @@ } }, "node_modules/jackspeak": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", - "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -12845,21 +12453,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/log-update/node_modules/emoji-regex": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", @@ -12881,22 +12474,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/log-update/node_modules/slice-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", @@ -13647,9 +13224,9 @@ } }, "node_modules/node-gyp": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.1.0.tgz", - "integrity": "sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", + "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", "dev": true, "dependencies": { "env-paths": "^2.2.0", @@ -13658,9 +13235,9 @@ "graceful-fs": "^4.2.6", "make-fetch-happen": "^13.0.0", "nopt": "^7.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.1.0", "semver": "^7.3.5", - "tar": "^6.1.2", + "tar": "^6.2.1", "which": "^4.0.0" }, "bin": { @@ -13697,9 +13274,9 @@ } }, "node_modules/node-gyp/node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", @@ -13712,9 +13289,6 @@ "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -13743,15 +13317,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/node-gyp/node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/node-gyp/node_modules/which": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", @@ -13846,9 +13411,9 @@ } }, "node_modules/node-polyfill-webpack-plugin/node_modules/type-fest": { - "version": "4.20.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.20.1.tgz", - "integrity": "sha512-R6wDsVsoS9xYOpy8vgeBlqpdOyzJ12HNfQhC/aAKWM3YoCV9TtunJzh/QpkMgeDhkoynDcw5f1y+qF9yc/HHyg==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.21.0.tgz", + "integrity": "sha512-ADn2w7hVPcK6w1I0uWnM//y1rLXZhzB9mr0a3OirzclKF1Wp6VzevUmzz/NRAWunOT6E8HrnpGY7xOfc6K57fA==", "dev": true, "engines": { "node": ">=16" @@ -13905,13 +13470,10 @@ } }, "node_modules/normalize-package-data/node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/normalize-path": { "version": "3.0.0", @@ -14004,13 +13566,10 @@ } }, "node_modules/npm-package-arg/node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/npm-packlist": { "version": "8.0.2", @@ -14399,6 +13958,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/ora/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ora/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -14426,6 +13997,25 @@ "node": ">=8" } }, + "node_modules/ora/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/ora/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -14757,13 +14347,10 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/path-to-regexp": { "version": "0.1.7", @@ -14772,12 +14359,15 @@ "dev": true }, "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/pbkdf2": { @@ -15165,9 +14755,7 @@ }, "node_modules/primeng-sass-theme": { "version": "17.18.3", - "resolved": "git+ssh://git@github.com/primefaces/primeng-sass-theme.git#2f7b1705c8783a098381c078345eb5dbe45c4008", - "integrity": "sha512-SUuLlE4Z06XIswSrmiFK9pK5Vx90WzZuB6s0qo79POGCRUtrct+O6K0rjfItmRlDpXRKPdKeGmrsXP0xx70GzQ==", - "license": "MIT" + "resolved": "git+ssh://git@github.com/primefaces/primeng-sass-theme.git#2f7b1705c8783a098381c078345eb5dbe45c4008" }, "node_modules/proc-log": { "version": "4.2.0", @@ -15296,9 +14884,9 @@ } }, "node_modules/qs": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", - "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", + "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", "dev": true, "dependencies": { "side-channel": "^1.0.6" @@ -15751,18 +15339,27 @@ } }, "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -15833,9 +15430,9 @@ } }, "node_modules/rollup": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz", - "integrity": "sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -15848,22 +15445,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.1", - "@rollup/rollup-android-arm64": "4.18.1", - "@rollup/rollup-darwin-arm64": "4.18.1", - "@rollup/rollup-darwin-x64": "4.18.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.1", - "@rollup/rollup-linux-arm-musleabihf": "4.18.1", - "@rollup/rollup-linux-arm64-gnu": "4.18.1", - "@rollup/rollup-linux-arm64-musl": "4.18.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.1", - "@rollup/rollup-linux-riscv64-gnu": "4.18.1", - "@rollup/rollup-linux-s390x-gnu": "4.18.1", - "@rollup/rollup-linux-x64-gnu": "4.18.1", - "@rollup/rollup-linux-x64-musl": "4.18.1", - "@rollup/rollup-win32-arm64-msvc": "4.18.1", - "@rollup/rollup-win32-ia32-msvc": "4.18.1", - "@rollup/rollup-win32-x64-msvc": "4.18.1", + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", "fsevents": "~2.3.2" } }, @@ -16423,10 +16020,16 @@ } }, "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/sigstore": { "version": "2.3.1", @@ -17091,9 +16694,9 @@ } }, "node_modules/terser": { - "version": "5.31.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", - "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", + "version": "5.29.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz", + "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -17701,9 +17304,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "funding": [ { From 23569ff24f8573925fea44303229fb7b4673c67f Mon Sep 17 00:00:00 2001 From: tiagohm Date: Thu, 11 Jul 2024 16:14:10 -0300 Subject: [PATCH 030/104] [api]: Implement PixInsight Stacker --- .../calibration/CalibrationFrameService.kt | 16 +--- .../cameras/CameraCaptureNamingFormatter.kt | 2 +- .../nebulosa/api/cameras/CameraCaptureTask.kt | 3 +- .../nebulosa/indi/device/camera/FrameType.kt | 17 +++- nebulosa-pixinsight/build.gradle.kts | 2 + .../livestacker/PixInsightLiveStacker.kt | 48 ++++------- .../script/AbstractPixInsightScript.kt | 2 +- .../pixinsight/script/PixInsightCalibrate.kt | 8 +- .../script/PixInsightLRGBCombination.kt | 78 ++++++++++++++++++ .../stacker/PixInsightAutoStacker.kt | 50 ++++++++++++ .../pixinsight/stacker/PixInsightStacker.kt | 34 ++++++++ .../src/main/resources/pixinsight/Align.js | 2 +- .../main/resources/pixinsight/Calibrate.js | 2 +- .../resources/pixinsight/LRGBCombination.js | 80 +++++++++++++++++++ .../test/kotlin/PixInsightAutoStackerTest.kt | 42 ++++++++++ .../src/test/kotlin/PixInsightScriptTest.kt | 44 +++++++--- nebulosa-stacker/build.gradle.kts | 16 ++++ .../kotlin/nebulosa/stacker/AutoStacker.kt | 8 ++ .../main/kotlin/nebulosa/stacker/Stacker.kt | 15 ++++ settings.gradle.kts | 1 + 20 files changed, 405 insertions(+), 65 deletions(-) create mode 100644 nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt create mode 100644 nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt create mode 100644 nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt create mode 100644 nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js create mode 100644 nebulosa-pixinsight/src/test/kotlin/PixInsightAutoStackerTest.kt create mode 100644 nebulosa-stacker/build.gradle.kts create mode 100644 nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt create mode 100644 nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt index 4dc82f92c..5939b03d3 100644 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt +++ b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt @@ -6,8 +6,8 @@ import nebulosa.image.algorithms.transformation.correction.BiasSubtraction import nebulosa.image.algorithms.transformation.correction.DarkSubtraction import nebulosa.image.algorithms.transformation.correction.FlatCorrection import nebulosa.image.format.ImageHdu -import nebulosa.image.format.ReadableHeader import nebulosa.indi.device.camera.FrameType +import nebulosa.indi.device.camera.FrameType.Companion.frameType import nebulosa.log.loggerFor import nebulosa.xisf.isXisf import nebulosa.xisf.xisf @@ -100,7 +100,7 @@ class CalibrationFrameService( } fun upload(name: String, path: Path): List { - val files = if (path.isRegularFile() && path.isFits) listOf(path) + val files = if (path.isRegularFile()) listOf(path) else if (path.isDirectory()) path.listDirectoryEntries("*.{fits,fit,xisf}").filter { it.isRegularFile() } else return emptyList() @@ -220,17 +220,5 @@ class CalibrationFrameService( companion object { @JvmStatic private val LOG = loggerFor() - - @JvmStatic val ReadableHeader.frameType - get() = frame?.let { - if (it.contains("LIGHT", true)) FrameType.LIGHT - else if (it.contains("DARK", true)) FrameType.DARK - else if (it.contains("FLAT", true)) FrameType.FLAT - else if (it.contains("BIAS", true)) FrameType.BIAS - else null - } - - inline val Path.isFits - get() = "$this".let { it.endsWith(".fits") || it.endsWith(".fit") } } } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt index 6b8a8a0a7..ab590b6f0 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureNamingFormatter.kt @@ -1,11 +1,11 @@ package nebulosa.api.cameras -import nebulosa.api.calibration.CalibrationFrameService.Companion.frameType import nebulosa.common.concurrency.atomic.Incrementer import nebulosa.fits.* import nebulosa.image.format.ReadableHeader import nebulosa.indi.device.camera.Camera import nebulosa.indi.device.camera.FrameType +import nebulosa.indi.device.camera.FrameType.Companion.frameType import nebulosa.indi.device.filterwheel.FilterWheel import nebulosa.indi.device.focuser.Focuser import nebulosa.indi.device.mount.Mount diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt index bd8dad2db..3b6abfdc3 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt @@ -32,6 +32,7 @@ import java.util.concurrent.Executor import java.util.concurrent.atomic.AtomicBoolean import kotlin.io.path.copyTo import kotlin.io.path.exists +import kotlin.io.path.extension data class CameraCaptureTask( @JvmField val camera: Camera, @@ -334,7 +335,7 @@ data class CameraCaptureTask( sendEvent(CameraCaptureState.STACKING) liveStacker!!.add(path)?.let { - val stackedPath = Path.of("${path.parent}", "STACKED.fits") + val stackedPath = Path.of("${path.parent}", "STACKED.${it.extension}") it.copyTo(stackedPath, true) stackedPath } diff --git a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/camera/FrameType.kt b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/camera/FrameType.kt index f6bb25e2b..33e481bc7 100644 --- a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/camera/FrameType.kt +++ b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/camera/FrameType.kt @@ -1,8 +1,23 @@ package nebulosa.indi.device.camera +import nebulosa.fits.frame +import nebulosa.image.format.ReadableHeader + enum class FrameType(@JvmField val description: String) { LIGHT("Light"), DARK("Dark"), FLAT("Flat"), - BIAS("Bias"), + BIAS("Bias"); + + companion object { + + @JvmStatic val ReadableHeader.frameType + get() = frame?.let { + if (it.contains("LIGHT", true)) LIGHT + else if (it.contains("DARK", true)) DARK + else if (it.contains("FLAT", true)) FLAT + else if (it.contains("BIAS", true)) BIAS + else null + } + } } diff --git a/nebulosa-pixinsight/build.gradle.kts b/nebulosa-pixinsight/build.gradle.kts index a82b0f0a5..73c3ed243 100644 --- a/nebulosa-pixinsight/build.gradle.kts +++ b/nebulosa-pixinsight/build.gradle.kts @@ -7,10 +7,12 @@ dependencies { api(project(":nebulosa-common")) api(project(":nebulosa-math")) api(project(":nebulosa-stardetector")) + api(project(":nebulosa-stacker")) api(project(":nebulosa-livestacker")) api(libs.bundles.jackson) api(libs.apache.codec) implementation(project(":nebulosa-log")) + testImplementation(project(":nebulosa-image")) testImplementation(project(":nebulosa-test")) } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt index 3348915ff..0e44d456d 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt @@ -2,12 +2,15 @@ package nebulosa.pixinsight.livestacker import nebulosa.livestacker.LiveStacker import nebulosa.log.loggerFor -import nebulosa.pixinsight.script.* +import nebulosa.pixinsight.script.PixInsightIsRunning +import nebulosa.pixinsight.script.PixInsightScript +import nebulosa.pixinsight.script.PixInsightScriptRunner +import nebulosa.pixinsight.script.PixInsightStartup +import nebulosa.pixinsight.stacker.PixInsightStacker import java.nio.file.Path import java.util.concurrent.atomic.AtomicBoolean import kotlin.io.path.copyTo import kotlin.io.path.deleteIfExists -import kotlin.io.path.moveTo data class PixInsightLiveStacker( private val runner: PixInsightScriptRunner, @@ -16,7 +19,7 @@ data class PixInsightLiveStacker( private val flat: Path? = null, private val bias: Path? = null, private val use32Bits: Boolean = false, - private val slot: Int = PixInsightScript.DEFAULT_SLOT, + private val slot: Int = PixInsightScript.UNSPECIFIED_SLOT, ) : LiveStacker { private val running = AtomicBoolean() @@ -30,9 +33,10 @@ data class PixInsightLiveStacker( @Volatile private var stackCount = 0 + private val stacker = PixInsightStacker(runner, workingDirectory, slot) private val referencePath = Path.of("$workingDirectory", "reference.fits") - private val calibratedPath = Path.of("$workingDirectory", "calibrated.fits") - private val alignedPath = Path.of("$workingDirectory", "aligned.fits") + private val calibratedPath = Path.of("$workingDirectory", "calibrated.xisf") + private val alignedPath = Path.of("$workingDirectory", "aligned.xisf") private val stackedPath = Path.of("$workingDirectory", "stacked.fits") @Synchronized @@ -60,41 +64,23 @@ data class PixInsightLiveStacker( return if (running.get()) { stacking.set(true) - // Calibrate. - val calibrated = if (dark == null && flat == null && bias == null) false else { - PixInsightCalibrate(slot, workingDirectory, targetPath, dark, flat, if (dark == null) bias else null).use { s -> - val outputPath = s.runSync(runner).outputImage ?: return@use false - LOG.info("live stacking calibrated. count={}, output={}", stackCount, outputPath) - outputPath.moveTo(calibratedPath, true) - true - } - } - - if (calibrated) { + if (stacker.calibrate(targetPath, calibratedPath, dark, flat, bias)) { + LOG.info("live stacking calibrated. count={}, output={}", stackCount, calibratedPath) targetPath = calibratedPath } // TODO: Debayer, Resample? if (stackCount > 0) { - // Align. - val aligned = PixInsightAlign(slot, workingDirectory, referencePath, targetPath).use { s -> - val outputPath = s.runSync(runner).outputImage ?: return@use false - LOG.info("live stacking aligned. count={}, output={}", stackCount, outputPath) - outputPath.moveTo(alignedPath, true) - true - } - - if (aligned) { + if (stacker.align(referencePath, targetPath, alignedPath)) { + LOG.info("live stacking aligned. count={}, output={}", stackCount, alignedPath) targetPath = alignedPath - // Stack. - val expressionRK = "({{0}} * $stackCount + {{1}}) / ${stackCount + 1}" - PixInsightPixelMath(slot, listOf(stackedPath, targetPath), stackedPath, expressionRK).use { s -> - s.runSync(runner).stackedImage?.also { - LOG.info("live stacking finished. count={}, output={}", stackCount++, it) - } + if (stacker.integrate(stackCount, stackedPath, targetPath, stackedPath)) { + LOG.info("live stacking finished. count={}, output={}", stackCount, stackedPath) } + + stackCount++ } } else { targetPath.copyTo(referencePath, true) diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt index ad5554d39..5a2f54ff2 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt @@ -34,7 +34,7 @@ abstract class AbstractPixInsightScript : PixInsightScript, CommandLineLis if (isDone) return@whenComplete else if (exception != null) completeExceptionally(exception) - else complete(processOnComplete(exitCode).also { LOG.info("script processed. output={}", it) }) + else complete(processOnComplete(exitCode).also { LOG.info("{} script processed. output={}", this::class.simpleName, it) }) } finally { commandLine.unregisterCommandLineListener(this) } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt index 53cd83351..c9c7a3f2d 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt @@ -12,9 +12,9 @@ data class PixInsightCalibrate( private val slot: Int, private val workingDirectory: Path, private val targetPath: Path, - private val dark: Path? = null, - private val flat: Path? = null, - private val bias: Path? = null, + private val darkPath: Path? = null, + private val flatPath: Path? = null, + private val biasPath: Path? = null, private val compress: Boolean = false, private val use32Bit: Boolean = false, ) : AbstractPixInsightScript() { @@ -50,7 +50,7 @@ data class PixInsightCalibrate( } override val arguments = - listOf("-x=${execute(slot, scriptPath, Input(targetPath, workingDirectory, statusPath, dark, flat, bias, compress, use32Bit))}") + listOf("-x=${execute(slot, scriptPath, Input(targetPath, workingDirectory, statusPath, darkPath, flatPath, biasPath, compress, use32Bit))}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt new file mode 100644 index 000000000..e8362387c --- /dev/null +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt @@ -0,0 +1,78 @@ +package nebulosa.pixinsight.script + +import nebulosa.io.resource +import nebulosa.io.transferAndClose +import java.nio.file.Files +import java.nio.file.Path +import kotlin.io.path.deleteIfExists +import kotlin.io.path.outputStream +import kotlin.io.path.readText + +data class PixInsightLRGBCombination( + private val slot: Int, + private val outputPath: Path, + private val luminancePath: Path? = null, + private val redPath: Path? = null, + private val greenPath: Path? = null, + private val bluePath: Path? = null, +) : AbstractPixInsightScript() { + + @Suppress("ArrayInDataClass") + private data class Input( + @JvmField val outputPath: Path, + @JvmField val statusPath: Path, + @JvmField val luminancePath: Path?, + @JvmField val redPath: Path?, + @JvmField val greenPath: Path?, + @JvmField val bluePath: Path?, + @JvmField val channelWeights: DoubleArray, + ) + + data class Output( + @JvmField val success: Boolean = false, + @JvmField val errorMessage: String? = null, + @JvmField val outputImage: Path? = null, + ) { + + companion object { + + @JvmStatic val FAILED = Output() + } + } + + private val scriptPath = Files.createTempFile("pi-", ".js") + private val statusPath = Files.createTempFile("pi-", ".txt") + + init { + resource("pixinsight/LRGBCombination.js")!!.transferAndClose(scriptPath.outputStream()) + } + + override val arguments = + listOf("-x=${execute(slot, scriptPath, Input(outputPath, statusPath, luminancePath, redPath, greenPath, bluePath, DEFAULT_CHANNEL_WEIGHTS))}") + + override fun processOnComplete(exitCode: Int): Output { + if (exitCode == 0) { + repeat(30) { + val text = statusPath.readText() + + if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { + return OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), Output::class.java) + } + + Thread.sleep(1000) + } + } + + return Output.FAILED + } + + override fun close() { + scriptPath.deleteIfExists() + statusPath.deleteIfExists() + } + + companion object { + + @JvmStatic private val DEFAULT_CHANNEL_WEIGHTS = doubleArrayOf(1.0, 1.0, 1.0, 1.0) + } +} diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt new file mode 100644 index 000000000..7619a92a1 --- /dev/null +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt @@ -0,0 +1,50 @@ +package nebulosa.pixinsight.stacker + +import nebulosa.pixinsight.script.PixInsightScript +import nebulosa.pixinsight.script.PixInsightScriptRunner +import nebulosa.stacker.AutoStacker +import java.nio.file.Path +import kotlin.io.path.copyTo +import kotlin.io.path.deleteIfExists + +data class PixInsightAutoStacker( + private val runner: PixInsightScriptRunner, + private val workingDirectory: Path, + private val darkPath: Path? = null, + private val flatPath: Path? = null, + private val biasPath: Path? = null, + private val slot: Int = PixInsightScript.UNSPECIFIED_SLOT, +) : AutoStacker { + + private val stacker = PixInsightStacker(runner, workingDirectory, slot) + + override fun stack(paths: Collection, outputPath: Path, referencePath: Path): Boolean { + if (paths.isEmpty()) return false + + val calibratedPath = Path.of("$workingDirectory", "calibrated.xisf") + val alignedPath = Path.of("$workingDirectory", "aligned.xisf") + + try { + paths.forEachIndexed { stackCount, path -> + var targetPath = path + + if (stacker.calibrate(targetPath, calibratedPath, darkPath, flatPath, biasPath)) { + targetPath = calibratedPath + } + + if (stackCount > 0) { + if (stacker.align(referencePath, targetPath, alignedPath)) { + stacker.integrate(stackCount, outputPath, alignedPath, outputPath) + } + } else { + targetPath.copyTo(outputPath, true) + } + } + } finally { + calibratedPath.deleteIfExists() + alignedPath.deleteIfExists() + } + + return true + } +} diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt new file mode 100644 index 000000000..b66a33733 --- /dev/null +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt @@ -0,0 +1,34 @@ +package nebulosa.pixinsight.stacker + +import nebulosa.pixinsight.script.* +import nebulosa.stacker.Stacker +import java.nio.file.Path +import kotlin.io.path.moveTo + +data class PixInsightStacker( + private val runner: PixInsightScriptRunner, + private val workingDirectory: Path, + private val slot: Int = PixInsightScript.UNSPECIFIED_SLOT, +) : Stacker { + + override fun calibrate( + targetPath: Path, outputPath: Path, + darkPath: Path?, flatPath: Path?, biasPath: Path?, + ) = if (darkPath != null || flatPath != null || biasPath != null) { + PixInsightCalibrate(slot, workingDirectory, targetPath, darkPath, flatPath, if (darkPath == null) biasPath else null) + .use { it.runSync(runner).outputImage?.moveTo(outputPath, true) != null } + } else { + false + } + + override fun align(referencePath: Path, targetPath: Path, outputPath: Path): Boolean { + return PixInsightAlign(slot, workingDirectory, referencePath, targetPath) + .use { it.runSync(runner).outputImage?.moveTo(outputPath, true) != null } + } + + override fun integrate(stackCount: Int, stackedPath: Path, targetPath: Path, outputPath: Path): Boolean { + val expressionRK = "({{0}} * $stackCount + {{1}}) / ${stackCount + 1}" + return PixInsightPixelMath(slot, listOf(stackedPath, targetPath), outputPath, expressionRK) + .use { it.runSync(runner).stackedImage != null } + } +} diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/Align.js b/nebulosa-pixinsight/src/main/resources/pixinsight/Align.js index f8f93f38c..d03400960 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/Align.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/Align.js @@ -103,7 +103,7 @@ function alignment() { P.pixelInterpolation = StarAlignment.prototype.Auto P.clampingThreshold = 0.30 P.outputDirectory = outputDirectory - P.outputExtension = ".fits" + P.outputExtension = ".xisf" P.outputPrefix = "" P.outputPostfix = "_a" P.maskPostfix = "_m" diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/Calibrate.js b/nebulosa-pixinsight/src/main/resources/pixinsight/Calibrate.js index 814586b86..7561a2ba0 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/Calibrate.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/Calibrate.js @@ -89,7 +89,7 @@ function calibrate() { P.psfGrowth = 1.00 P.maxStars = 24576 P.outputDirectory = outputDirectory - P.outputExtension = ".fits" + P.outputExtension = ".xisf" P.outputPrefix = "" P.outputPostfix = "_c" P.outputSampleFormat = use32Bit ? ImageCalibration.prototype.f32 : ImageCalibration.prototype.i16 diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js b/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js new file mode 100644 index 000000000..bd44e4632 --- /dev/null +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js @@ -0,0 +1,80 @@ +function decodeParams(hex) { + const buffer = new Uint8Array(hex.length / 4) + + for (let i = 0; i < hex.length; i += 4) { + buffer[i / 4] = parseInt(hex.substr(i, 4), 16) + } + + return JSON.parse(String.fromCharCode.apply(null, buffer)) +} + +function lrgbCombination() { + const data = { + success: true, + errorMessage: null, + outputImage: null, + } + + try { + const input = decodeParams(jsArguments[0]) + + const outputPath = input.outputPath + const statusPath = input.statusPath + const channelWeights = input.channelWeights + const luminancePath = input.luminancePath + const redPath = input.redPath + const greenPath = input.greenPath + const bluePath = input.bluePath + + console.writeln("outputPath=" + outputPath) + console.writeln("statusPath=" + statusPath) + console.writeln("channelWeights=" + channelWeights) + console.writeln("luminancePath=" + luminancePath) + console.writeln("redPath=" + redPath) + console.writeln("greenPath=" + greenPath) + console.writeln("bluePath=" + bluePath) + + const luminanceWindow = luminancePath ? ImageWindow.open(luminancePath)[0] : undefined + const redWindow = redPath ? ImageWindow.open(redPath)[0] : undefined + const greenWindow = greenPath ? ImageWindow.open(greenPath)[0] : undefined + const blueWindow = bluePath ? ImageWindow.open(bluePath)[0] : undefined + + var P = new LRGBCombination + P.channels = [ // enabled, id, k + [!!luminancePath, luminanceWindow? luminanceWindow.mainView.id : "", channelWeights[0]], + [!!redPath, redWindow ? redWindow.mainView.id : "", channelWeights[1]], + [!!greenPath, greenWindow ? greenWindow.mainView.id : "", channelWeights[2]], + [!!bluePath, blueWindow ? blueWindow.mainView.id : "", channelWeights[3]] + ] + P.mL = 0.500 + P.mc = 0.500 + P.clipHighlights = true + P.noiseReduction = false + P.layersRemoved = 4 + P.layersProtected = 2 + P.inheritAstrometricSolution = true + + P.executeGlobal() + + const window = ImageWindow.windows[ImageWindow.windows.length - 1] + window.saveAs(outputPath, false, false, false, false) + window.forceClose() + + if (luminanceWindow) luminanceWindow.forceClose() + if (redWindow) redWindow.forceClose() + if (greenWindow) greenWindow.forceClose() + if (blueWindow) blueWindow.forceClose() + + data.outputImage = outputPath + + console.writeln("LRGB combination finished") + } catch (e) { + data.success = false + data.errorMessage = e.message + console.writeln(data.errorMessage) + } finally { + File.writeTextFile(statusPath, "@" + JSON.stringify(data) + "#") + } +} + +lrgbCombination() diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightAutoStackerTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightAutoStackerTest.kt new file mode 100644 index 000000000..e4c6a0feb --- /dev/null +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightAutoStackerTest.kt @@ -0,0 +1,42 @@ +import PixInsightScriptTest.Companion.openAsImage +import io.kotest.core.annotation.EnabledIf +import io.kotest.engine.spec.tempdir +import io.kotest.engine.spec.tempfile +import io.kotest.matchers.booleans.shouldBeTrue +import io.kotest.matchers.shouldBe +import nebulosa.image.algorithms.transformation.AutoScreenTransformFunction +import nebulosa.pixinsight.script.PixInsightScriptRunner +import nebulosa.pixinsight.stacker.PixInsightAutoStacker +import nebulosa.test.AbstractFitsAndXisfTest +import nebulosa.test.NonGitHubOnlyCondition +import java.nio.file.Path + +@EnabledIf(NonGitHubOnlyCondition::class) +class PixInsightAutoStackerTest : AbstractFitsAndXisfTest() { + + init { + val runner = PixInsightScriptRunner(Path.of("PixInsight")) + val workingDirectory = tempdir("pi-").toPath() + + "stack" { + val files = listOf(PI_01_LIGHT, PI_02_LIGHT, PI_03_LIGHT, PI_04_LIGHT, PI_05_LIGHT, PI_06_LIGHT, PI_07_LIGHT, PI_08_LIGHT) + val outputPath = tempfile("pi-", ".fits").toPath() + + val stacker = PixInsightAutoStacker(runner, workingDirectory) + stacker.stack(files, outputPath).shouldBeTrue() + + outputPath.openAsImage().transform(AutoScreenTransformFunction) + .save("pi-auto-stacked").second shouldBe "a107143dff3d43c4b56c872da869f89b" + } + "!calibrated stack" { + val files = listOf(PI_01_LIGHT, PI_02_LIGHT, PI_03_LIGHT, PI_04_LIGHT, PI_05_LIGHT, PI_06_LIGHT, PI_07_LIGHT, PI_08_LIGHT) + val outputPath = tempfile("pi-", ".fits").toPath() + + val stacker = PixInsightAutoStacker(runner, workingDirectory, PI_DARK, PI_FLAT, PI_BIAS) + stacker.stack(files, outputPath).shouldBeTrue() + + outputPath.openAsImage().transform(AutoScreenTransformFunction) + .save("pi-calibrated-auto-stacked").second shouldBe "" + } + } +} diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt index 2bc11d4d2..ab35696bc 100644 --- a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt @@ -4,12 +4,16 @@ import io.kotest.engine.spec.tempfile import io.kotest.matchers.booleans.shouldBeTrue import io.kotest.matchers.doubles.plusOrMinus import io.kotest.matchers.nulls.shouldNotBeNull -import io.kotest.matchers.paths.shouldExist import io.kotest.matchers.shouldBe +import nebulosa.fits.fits +import nebulosa.fits.isFits +import nebulosa.image.Image +import nebulosa.image.algorithms.transformation.AutoScreenTransformFunction import nebulosa.pixinsight.script.* import nebulosa.test.AbstractFitsAndXisfTest import nebulosa.test.NonGitHubOnlyCondition -import java.nio.file.Files +import nebulosa.xisf.isXisf +import nebulosa.xisf.xisf import java.nio.file.Path @EnabledIf(NonGitHubOnlyCondition::class) @@ -19,21 +23,23 @@ class PixInsightScriptTest : AbstractFitsAndXisfTest() { val runner = PixInsightScriptRunner(Path.of("PixInsight")) val workingDirectory = tempdir("pi-").toPath() - "startup" { + "!startup" { PixInsightStartup(PixInsightScript.DEFAULT_SLOT) .use { it.runSync(runner).shouldBeTrue() } } - "is running" { + "!is running" { PixInsightIsRunning(PixInsightScript.DEFAULT_SLOT) .use { it.runSync(runner).shouldBeTrue() } } "calibrate" { PixInsightCalibrate(PixInsightScript.UNSPECIFIED_SLOT, workingDirectory, PI_01_LIGHT, PI_DARK, PI_FLAT, PI_BIAS) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().shouldExist() } + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-calibrate").second shouldBe "731562ee12f45bf7c1095f4773f70e71" } "align" { PixInsightAlign(PixInsightScript.UNSPECIFIED_SLOT, workingDirectory, PI_01_LIGHT, PI_02_LIGHT) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().shouldExist() } + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-align").second shouldBe "483ebaf15afa5957fe099f3ee2beff78" } "detect stars" { PixInsightDetectStars(PixInsightScript.UNSPECIFIED_SLOT, PI_FOCUS_0) @@ -52,14 +58,32 @@ class PixInsightScriptTest : AbstractFitsAndXisfTest() { .average() shouldBe (18.35 plusOrMinus 1e-2) } "pixel math" { - val outputPath = Files.createTempFile("pi-stacked-", ".fits") + val outputPath = tempfile("pi-stacked-", ".fits").toPath() PixInsightPixelMath(PixInsightScript.UNSPECIFIED_SLOT, listOf(PI_01_LIGHT, PI_02_LIGHT), outputPath, "{{0}} + {{1}}") - .use { it.runSync(runner).also(::println).stackedImage.shouldNotBeNull().shouldExist() } + .use { it.runSync(runner).also(::println).stackedImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-pixelmath").second shouldBe "cafc8138e2ce17614dcfa10edf410b07" } "abe" { - val outputPath = tempfile("pi-", ".fits").toPath() + val outputPath = tempfile("pi-abe-", ".fits").toPath() PixInsightAutomaticBackgroundExtractor(PixInsightScript.UNSPECIFIED_SLOT, PI_01_LIGHT, outputPath) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull() } + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-abe").second shouldBe "bf62207dc17190009ba215da7c011297" + } + "lrgb combination" { + val outputPath = tempfile("pi-lrgb-", ".fits").toPath() + PixInsightLRGBCombination(PixInsightScript.UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-lrgb").second shouldBe "99db35d78f7b360e7592217f4179b189" + } + } + + companion object { + + @JvmStatic + internal fun Path.openAsImage(): Image { + return if (isFits()) fits().use(Image::open) + else if (isXisf()) xisf().use(Image::open) + else throw IllegalArgumentException("the path at $this is not an image") } } } diff --git a/nebulosa-stacker/build.gradle.kts b/nebulosa-stacker/build.gradle.kts new file mode 100644 index 000000000..4d1b2976b --- /dev/null +++ b/nebulosa-stacker/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + kotlin("jvm") + id("maven-publish") +} + +dependencies { + api(libs.logback) +} + +publishing { + publications { + create("pluginMaven") { + from(components["java"]) + } + } +} diff --git a/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt new file mode 100644 index 000000000..811c4c867 --- /dev/null +++ b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt @@ -0,0 +1,8 @@ +package nebulosa.stacker + +import java.nio.file.Path + +interface AutoStacker { + + fun stack(paths: Collection, outputPath: Path, referencePath: Path = paths.first()): Boolean +} diff --git a/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt new file mode 100644 index 000000000..bbf15d88e --- /dev/null +++ b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt @@ -0,0 +1,15 @@ +package nebulosa.stacker + +import java.nio.file.Path + +interface Stacker { + + fun calibrate( + targetPath: Path, outputPath: Path, + darkPath: Path? = null, flatPath: Path? = null, biasPath: Path? = null, + ): Boolean + + fun align(referencePath: Path, targetPath: Path, outputPath: Path): Boolean + + fun integrate(stackCount: Int, stackedPath: Path, targetPath: Path, outputPath: Path): Boolean +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 3e9c051c9..95058fe59 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -88,6 +88,7 @@ include(":nebulosa-skycatalog-hyg") include(":nebulosa-skycatalog-sao") include(":nebulosa-skycatalog-stellarium") include(":nebulosa-stardetector") +include(":nebulosa-stacker") include(":nebulosa-stellarium-protocol") include(":nebulosa-test") include(":nebulosa-time") From 15d1db5880ff0e8cf10f1915d8441018a928a7ea Mon Sep 17 00:00:00 2001 From: tiagohm Date: Fri, 12 Jul 2024 17:44:20 -0300 Subject: [PATCH 031/104] [api][desktop]: Implement PixInsight Stacker --- .../alignment/polar/darv/DARVStartRequest.kt | 6 +- .../kotlin/nebulosa/api/atlas/BodyPosition.kt | 26 +++--- .../nebulosa/api/atlas/CloseApproach.kt | 10 +-- .../kotlin/nebulosa/api/atlas/Location.kt | 2 +- .../kotlin/nebulosa/api/atlas/MinorPlanet.kt | 27 +++--- .../nebulosa/api/atlas/SatelliteEntity.kt | 6 +- .../api/atlas/SkyObjectInsideCoordinate.kt | 6 +- .../kotlin/nebulosa/api/atlas/Twilight.kt | 14 ++-- .../api/calibration/CalibrationFrameEntity.kt | 24 +++--- .../api/calibration/CalibrationFrameGroup.kt | 8 +- .../api/calibration/CalibrationGroupKey.kt | 14 ++-- .../nebulosa/api/cameras/CameraCaptureTask.kt | 15 ++-- .../api/connection/ConnectionStatus.kt | 9 +- .../kotlin/nebulosa/api/guiding/GuiderInfo.kt | 8 +- .../api/guiding/GuiderMessageEvent.kt | 2 +- .../nebulosa/api/guiding/HistoryStep.kt | 14 ++-- .../kotlin/nebulosa/api/guiding/SettleInfo.kt | 6 +- .../api/image/CoordinateInterpolation.kt | 12 ++- .../nebulosa/api/image/ImageAnnotation.kt | 8 +- .../nebulosa/api/image/ImageHeaderItem.kt | 2 +- .../kotlin/nebulosa/api/image/ImageInfo.kt | 24 +++--- .../kotlin/nebulosa/api/image/ImageSolved.kt | 16 ++-- .../kotlin/nebulosa/api/image/SaveImage.kt | 10 +-- .../nebulosa/api/indi/INDIMessageEvent.kt | 4 +- .../nebulosa/api/indi/INDISendProperty.kt | 6 +- .../nebulosa/api/indi/INDISendPropertyItem.kt | 4 +- .../api/livestacker/LiveStackingRequest.kt | 25 ++---- .../nebulosa/api/mounts/ComputedLocation.kt | 22 ++--- .../api/preference/PreferenceEntity.kt | 4 +- .../api/preference/PreferenceRequestBody.kt | 3 - .../nebulosa/api/stacker/StackerController.kt | 21 +++++ .../nebulosa/api/stacker/StackerGroupType.kt | 10 +++ .../nebulosa/api/stacker/StackerService.kt | 78 ++++++++++++++++++ .../nebulosa/api/stacker/StackerType.kt | 5 ++ .../nebulosa/api/stacker/StackingRequest.kt | 36 ++++++++ .../nebulosa/api/stacker/StackingTarget.kt | 11 +++ .../api/stardetector/StarDetectionRequest.kt | 13 +-- desktop/.editorconfig | 1 + desktop/src/app/about/about.component.html | 7 +- desktop/src/app/app-routing.module.ts | 5 ++ desktop/src/app/app.module.ts | 2 + desktop/src/app/camera/camera.component.html | 6 +- desktop/src/app/camera/camera.component.ts | 6 +- .../src/app/settings/settings.component.html | 17 ++-- .../src/app/settings/settings.component.ts | 27 +----- .../src/app/stacker/stacker.component.html | 0 desktop/src/app/stacker/stacker.component.ts | 7 ++ desktop/src/assets/icons/photo-filter.png | Bin 0 -> 1657 bytes .../src/shared/pipes/dropdown-options.pipe.ts | 9 +- desktop/src/shared/pipes/enum.pipe.ts | 62 ++++++++------ desktop/src/shared/services/api.service.ts | 23 +----- .../shared/services/browser-window.service.ts | 7 +- desktop/src/shared/types/camera.types.ts | 6 +- desktop/src/shared/types/settings.types.ts | 7 ++ desktop/src/shared/types/stacker.types.ts | 23 ++++++ .../livestacker/PixInsightLiveStacker.kt | 12 ++- .../pixinsight/script/PixInsightAlign.kt | 6 +- .../PixInsightAutomaticBackgroundExtractor.kt | 6 +- .../pixinsight/script/PixInsightCalibrate.kt | 6 +- .../script/PixInsightDetectStars.kt | 6 +- .../pixinsight/script/PixInsightHelper.kt | 15 ++++ .../script/PixInsightLRGBCombination.kt | 11 ++- .../script/PixInsightLuminanceCombination.kt | 68 +++++++++++++++ .../pixinsight/script/PixInsightOutput.kt | 8 ++ .../pixinsight/script/PixInsightPixelMath.kt | 8 +- .../stacker/PixInsightAutoStacker.kt | 28 ++++++- .../pixinsight/stacker/PixInsightStacker.kt | 19 ++++- .../src/main/resources/pixinsight/ABE.js | 1 + .../src/main/resources/pixinsight/Align.js | 1 + .../main/resources/pixinsight/Calibrate.js | 1 + .../resources/pixinsight/LRGBCombination.js | 5 +- .../pixinsight/LuminanceCombination.js | 71 ++++++++++++++++ .../main/resources/pixinsight/PixelMath.js | 7 +- .../src/test/kotlin/PixInsightScriptTest.kt | 60 ++++++++++++-- .../src/test/kotlin/PixInsightStackerTest.kt | 58 +++++++++++++ .../kotlin/nebulosa/siril/command/StartLs.kt | 8 +- .../siril/livestacker/SirilLiveStacker.kt | 6 +- .../kotlin/nebulosa/stacker/AutoStacker.kt | 2 +- .../main/kotlin/nebulosa/stacker/Stacker.kt | 4 + 79 files changed, 827 insertions(+), 316 deletions(-) delete mode 100644 api/src/main/kotlin/nebulosa/api/preference/PreferenceRequestBody.kt create mode 100644 api/src/main/kotlin/nebulosa/api/stacker/StackerController.kt create mode 100644 api/src/main/kotlin/nebulosa/api/stacker/StackerGroupType.kt create mode 100644 api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt create mode 100644 api/src/main/kotlin/nebulosa/api/stacker/StackerType.kt create mode 100644 api/src/main/kotlin/nebulosa/api/stacker/StackingRequest.kt create mode 100644 api/src/main/kotlin/nebulosa/api/stacker/StackingTarget.kt create mode 100644 desktop/src/app/stacker/stacker.component.html create mode 100644 desktop/src/app/stacker/stacker.component.ts create mode 100644 desktop/src/assets/icons/photo-filter.png create mode 100644 desktop/src/shared/types/stacker.types.ts create mode 100644 nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt create mode 100644 nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt create mode 100644 nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightOutput.kt create mode 100644 nebulosa-pixinsight/src/main/resources/pixinsight/LuminanceCombination.js create mode 100644 nebulosa-pixinsight/src/test/kotlin/PixInsightStackerTest.kt diff --git a/api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVStartRequest.kt b/api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVStartRequest.kt index 53b99114f..209792636 100644 --- a/api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVStartRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVStartRequest.kt @@ -4,7 +4,7 @@ import nebulosa.api.cameras.CameraStartCaptureRequest import nebulosa.guiding.GuideDirection data class DARVStartRequest( - val capture: CameraStartCaptureRequest = CameraStartCaptureRequest.EMPTY, - val direction: GuideDirection = GuideDirection.NORTH, - val reversed: Boolean = false, + @JvmField val capture: CameraStartCaptureRequest = CameraStartCaptureRequest.EMPTY, + @JvmField val direction: GuideDirection = GuideDirection.NORTH, + @JvmField val reversed: Boolean = false, ) diff --git a/api/src/main/kotlin/nebulosa/api/atlas/BodyPosition.kt b/api/src/main/kotlin/nebulosa/api/atlas/BodyPosition.kt index 64802dd6d..e455723ee 100644 --- a/api/src/main/kotlin/nebulosa/api/atlas/BodyPosition.kt +++ b/api/src/main/kotlin/nebulosa/api/atlas/BodyPosition.kt @@ -15,19 +15,19 @@ import nebulosa.nova.astrometry.Constellation import nebulosa.skycatalog.SkyObject data class BodyPosition( - @field:JsonSerialize(using = RightAscensionSerializer::class) val rightAscensionJ2000: Angle, - @field:JsonSerialize(using = DeclinationSerializer::class) val declinationJ2000: Angle, - @field:JsonSerialize(using = RightAscensionSerializer::class) val rightAscension: Angle, - @field:JsonSerialize(using = DeclinationSerializer::class) val declination: Angle, - @field:JsonSerialize(using = AzimuthSerializer::class) val azimuth: Angle, - @field:JsonSerialize(using = DeclinationSerializer::class) val altitude: Angle, - val magnitude: Double, - val constellation: Constellation, - val distance: Double, - val distanceUnit: String, - val illuminated: Double, - @field:JsonSerialize(using = DegreesSerializer::class) val elongation: Angle, - val leading: Boolean, // true = rises and sets BEFORE Sun. + @field:JsonSerialize(using = RightAscensionSerializer::class) @JvmField val rightAscensionJ2000: Angle, + @field:JsonSerialize(using = DeclinationSerializer::class) @JvmField val declinationJ2000: Angle, + @field:JsonSerialize(using = RightAscensionSerializer::class) @JvmField val rightAscension: Angle, + @field:JsonSerialize(using = DeclinationSerializer::class) @JvmField val declination: Angle, + @field:JsonSerialize(using = AzimuthSerializer::class) @JvmField val azimuth: Angle, + @field:JsonSerialize(using = DeclinationSerializer::class) @JvmField val altitude: Angle, + @JvmField val magnitude: Double, + @JvmField val constellation: Constellation, + @JvmField val distance: Double, + @JvmField val distanceUnit: String, + @JvmField val illuminated: Double, + @field:JsonSerialize(using = DegreesSerializer::class) @JvmField val elongation: Angle, + @JvmField val leading: Boolean, // true = rises and sets BEFORE Sun. ) { companion object { diff --git a/api/src/main/kotlin/nebulosa/api/atlas/CloseApproach.kt b/api/src/main/kotlin/nebulosa/api/atlas/CloseApproach.kt index 06914286a..c011e7c78 100644 --- a/api/src/main/kotlin/nebulosa/api/atlas/CloseApproach.kt +++ b/api/src/main/kotlin/nebulosa/api/atlas/CloseApproach.kt @@ -8,11 +8,11 @@ import java.time.format.DateTimeFormatter import java.util.* data class CloseApproach( - val name: String = "", - val designation: String = "", - val dateTime: Long = 0, - val distance: Double = 0.0, - val absoluteMagnitude: Double = 0.0, + @JvmField val name: String = "", + @JvmField val designation: String = "", + @JvmField val dateTime: Long = 0, + @JvmField val distance: Double = 0.0, + @JvmField val absoluteMagnitude: Double = 0.0, ) { companion object { diff --git a/api/src/main/kotlin/nebulosa/api/atlas/Location.kt b/api/src/main/kotlin/nebulosa/api/atlas/Location.kt index 7d92156e3..8bd3b0ca3 100644 --- a/api/src/main/kotlin/nebulosa/api/atlas/Location.kt +++ b/api/src/main/kotlin/nebulosa/api/atlas/Location.kt @@ -15,7 +15,7 @@ data class Location( @field:JsonSerialize(using = DegreesSerializer::class) @field:JsonDeserialize(using = DegreesDeserializer::class) override val latitude: Angle = 0.0, @field:JsonSerialize(using = DegreesSerializer::class) @field:JsonDeserialize(using = DegreesDeserializer::class) override val longitude: Angle = 0.0, @field:JsonSerialize(using = MetersSerializer::class) @field:JsonDeserialize(using = MetersDeserializer::class) override val elevation: Distance = 0.0, - val offsetInMinutes: Int = 0, + @JvmField val offsetInMinutes: Int = 0, ) : GeographicCoordinate, TimeZonedInSeconds { override val offsetInSeconds = offsetInMinutes * 60 diff --git a/api/src/main/kotlin/nebulosa/api/atlas/MinorPlanet.kt b/api/src/main/kotlin/nebulosa/api/atlas/MinorPlanet.kt index 423a774b0..5d13a502a 100644 --- a/api/src/main/kotlin/nebulosa/api/atlas/MinorPlanet.kt +++ b/api/src/main/kotlin/nebulosa/api/atlas/MinorPlanet.kt @@ -3,20 +3,21 @@ package nebulosa.api.atlas import nebulosa.sbd.SmallBody data class MinorPlanet( - val found: Boolean = false, - val name: String = "", - val spkId: Int = -1, - val kind: SmallBody.BodyKind? = null, - val pha: Boolean = false, val neo: Boolean = false, - val orbitType: String = "", - val parameters: List = emptyList(), - val searchItems: List = emptyList(), + @JvmField val found: Boolean = false, + @JvmField val name: String = "", + @JvmField val spkId: Int = -1, + @JvmField val kind: SmallBody.BodyKind? = null, + @JvmField val pha: Boolean = false, + @JvmField val neo: Boolean = false, + @JvmField val orbitType: String = "", + @JvmField val parameters: List = emptyList(), + @JvmField val searchItems: List = emptyList(), ) { data class OrbitalPhysicalParameter( - val name: String, - val description: String, - val value: String, + @JvmField val name: String, + @JvmField val description: String, + @JvmField val value: String, ) { constructor(param: SmallBody.OrbitElement) : this( @@ -31,8 +32,8 @@ data class MinorPlanet( } data class SearchItem( - val name: String, - val pdes: String, + @JvmField val name: String, + @JvmField val pdes: String, ) companion object { diff --git a/api/src/main/kotlin/nebulosa/api/atlas/SatelliteEntity.kt b/api/src/main/kotlin/nebulosa/api/atlas/SatelliteEntity.kt index bdaaf93bf..bed2ebab2 100644 --- a/api/src/main/kotlin/nebulosa/api/atlas/SatelliteEntity.kt +++ b/api/src/main/kotlin/nebulosa/api/atlas/SatelliteEntity.kt @@ -7,7 +7,7 @@ import nebulosa.api.database.BoxEntity @Entity data class SatelliteEntity( @Id(assignable = true) override var id: Long = 0L, - var name: String = "", - var tle: String = "", - var groups: MutableList = ArrayList(0), + @JvmField var name: String = "", + @JvmField var tle: String = "", + @JvmField var groups: MutableList = ArrayList(0), ) : BoxEntity diff --git a/api/src/main/kotlin/nebulosa/api/atlas/SkyObjectInsideCoordinate.kt b/api/src/main/kotlin/nebulosa/api/atlas/SkyObjectInsideCoordinate.kt index 10b0857bb..ac2e89655 100644 --- a/api/src/main/kotlin/nebulosa/api/atlas/SkyObjectInsideCoordinate.kt +++ b/api/src/main/kotlin/nebulosa/api/atlas/SkyObjectInsideCoordinate.kt @@ -9,9 +9,9 @@ import kotlin.math.cos import kotlin.math.sin data class SkyObjectInsideCoordinate( - private val rightAscension: Angle, - private val declination: Angle, - private val radius: Angle, + @JvmField val rightAscension: Angle, + @JvmField val declination: Angle, + @JvmField val radius: Angle, ) : QueryFilter { private val sinDEC = declination.sin diff --git a/api/src/main/kotlin/nebulosa/api/atlas/Twilight.kt b/api/src/main/kotlin/nebulosa/api/atlas/Twilight.kt index 3414234d5..3ec8cab46 100644 --- a/api/src/main/kotlin/nebulosa/api/atlas/Twilight.kt +++ b/api/src/main/kotlin/nebulosa/api/atlas/Twilight.kt @@ -2,11 +2,11 @@ package nebulosa.api.atlas @Suppress("ArrayInDataClass") data class Twilight( - val civilDusk: DoubleArray, - val nauticalDusk: DoubleArray, - val astronomicalDusk: DoubleArray, - val night: DoubleArray, - val astronomicalDawn: DoubleArray, - val nauticalDawn: DoubleArray, - val civilDawn: DoubleArray, + @JvmField val civilDusk: DoubleArray, + @JvmField val nauticalDusk: DoubleArray, + @JvmField val astronomicalDusk: DoubleArray, + @JvmField val night: DoubleArray, + @JvmField val astronomicalDawn: DoubleArray, + @JvmField val nauticalDawn: DoubleArray, + @JvmField val civilDawn: DoubleArray, ) diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameEntity.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameEntity.kt index 631dc5b9e..1b15e657e 100644 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameEntity.kt +++ b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameEntity.kt @@ -13,16 +13,16 @@ import java.nio.file.Path @Entity data class CalibrationFrameEntity( @Id override var id: Long = 0L, - @Index @Convert(converter = FrameTypePropertyConverter::class, dbType = Int::class) var type: FrameType = FrameType.LIGHT, - @Index var name: String = "", - var filter: String? = null, - var exposureTime: Long = 0L, - var temperature: Double = 0.0, - var width: Int = 0, - var height: Int = 0, - var binX: Int = 0, - var binY: Int = 0, - var gain: Double = 0.0, - @Convert(converter = PathPropertyConverter::class, dbType = String::class) var path: Path? = null, - var enabled: Boolean = true, + @JvmField @Index @Convert(converter = FrameTypePropertyConverter::class, dbType = Int::class) var type: FrameType = FrameType.LIGHT, + @JvmField @Index var name: String = "", + @JvmField var filter: String? = null, + @JvmField var exposureTime: Long = 0L, + @JvmField var temperature: Double = 0.0, + @JvmField var width: Int = 0, + @JvmField var height: Int = 0, + @JvmField var binX: Int = 0, + @JvmField var binY: Int = 0, + @JvmField var gain: Double = 0.0, + @JvmField @Convert(converter = PathPropertyConverter::class, dbType = String::class) var path: Path? = null, + @JvmField var enabled: Boolean = true, ) : BoxEntity diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameGroup.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameGroup.kt index 7e4171cda..df469a2cd 100644 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameGroup.kt +++ b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameGroup.kt @@ -1,8 +1,8 @@ package nebulosa.api.calibration data class CalibrationFrameGroup( - val id: Int, - val name: String, - val key: CalibrationGroupKey, - val frames: List, + @JvmField val id: Int, + @JvmField val name: String, + @JvmField val key: CalibrationGroupKey, + @JvmField val frames: List, ) diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationGroupKey.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationGroupKey.kt index dd659e464..5f63971b4 100644 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationGroupKey.kt +++ b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationGroupKey.kt @@ -4,11 +4,15 @@ import nebulosa.indi.device.camera.FrameType import kotlin.math.roundToInt data class CalibrationGroupKey( - val type: FrameType, val filter: String?, - val width: Int, val height: Int, - val binX: Int, val binY: Int, - val exposureTime: Long, - val temperature: Int, val gain: Double, + @JvmField val type: FrameType, + @JvmField val filter: String?, + @JvmField val width: Int, + @JvmField val height: Int, + @JvmField val binX: Int, + @JvmField val binY: Int, + @JvmField val exposureTime: Long, + @JvmField val temperature: Int, + @JvmField val gain: Double, ) { companion object { diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt index 3b6abfdc3..c57a709c7 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraCaptureTask.kt @@ -101,7 +101,7 @@ data class CameraCaptureTask( private fun LiveStackingRequest.processCalibrationGroup(): LiveStackingRequest { return if (calibrationFrameProvider != null && enabled && - !request.calibrationGroup.isNullOrBlank() && (dark == null || flat == null || bias == null) + !request.calibrationGroup.isNullOrBlank() && (darkPath == null || flatPath == null || biasPath == null) ) { val calibrationGroup = request.calibrationGroup val temperature = camera.temperature @@ -120,24 +120,27 @@ data class CameraCaptureTask( calibrationGroup, temperature, binX, binY, width, height, exposureTime, gain, filter ) - val newDark = dark?.takeIf { it.exists() } ?: calibrationFrameProvider + val newDarkPath = darkPath?.takeIf { it.exists() } ?: calibrationFrameProvider .findBestDarkFrames(calibrationGroup, temperature, width, height, binX, binY, exposureTime, gain) .firstOrNull() ?.path - val newFlat = flat?.takeIf { it.exists() } ?: calibrationFrameProvider + val newFlatPath = flatPath?.takeIf { it.exists() } ?: calibrationFrameProvider .findBestFlatFrames(calibrationGroup, width, height, binX, binY, filter) .firstOrNull() ?.path - val newBias = if (newDark != null) null else bias?.takeIf { it.exists() } ?: calibrationFrameProvider + val newBiasPath = if (newDarkPath != null) null else biasPath?.takeIf { it.exists() } ?: calibrationFrameProvider .findBestBiasFrames(calibrationGroup, width, height, binX, binY) .firstOrNull() ?.path - LOG.info("live stacking will use calibration frames. group={}, dark={}, flat={}, bias={}", calibrationGroup, newDark, newFlat, newBias) + LOG.info( + "live stacking will use calibration frames. group={}, dark={}, flat={}, bias={}", + calibrationGroup, newDarkPath, newFlatPath, newBiasPath + ) - copy(dark = newDark, flat = newFlat, bias = newBias) + copy(darkPath = newDarkPath, flatPath = newFlatPath, biasPath = newBiasPath) } else { this } diff --git a/api/src/main/kotlin/nebulosa/api/connection/ConnectionStatus.kt b/api/src/main/kotlin/nebulosa/api/connection/ConnectionStatus.kt index 2eba3f9ae..f511fda92 100644 --- a/api/src/main/kotlin/nebulosa/api/connection/ConnectionStatus.kt +++ b/api/src/main/kotlin/nebulosa/api/connection/ConnectionStatus.kt @@ -1,8 +1,9 @@ package nebulosa.api.connection data class ConnectionStatus( - val id: String, - val type: ConnectionType, - val host: String, val port: Int, - val ip: String? = null, + @JvmField val id: String, + @JvmField val type: ConnectionType, + @JvmField val host: String, + @JvmField val port: Int, + @JvmField val ip: String? = null, ) diff --git a/api/src/main/kotlin/nebulosa/api/guiding/GuiderInfo.kt b/api/src/main/kotlin/nebulosa/api/guiding/GuiderInfo.kt index 3ce34f5b7..ec1d38a4f 100644 --- a/api/src/main/kotlin/nebulosa/api/guiding/GuiderInfo.kt +++ b/api/src/main/kotlin/nebulosa/api/guiding/GuiderInfo.kt @@ -3,10 +3,10 @@ package nebulosa.api.guiding import nebulosa.guiding.GuideState data class GuiderInfo( - val connected: Boolean = false, - val state: GuideState = GuideState.STOPPED, - val settling: Boolean = false, - val pixelScale: Double = 1.0, + @JvmField val connected: Boolean = false, + @JvmField val state: GuideState = GuideState.STOPPED, + @JvmField val settling: Boolean = false, + @JvmField val pixelScale: Double = 1.0, ) { companion object { diff --git a/api/src/main/kotlin/nebulosa/api/guiding/GuiderMessageEvent.kt b/api/src/main/kotlin/nebulosa/api/guiding/GuiderMessageEvent.kt index 33ed3a7bc..8237710b5 100644 --- a/api/src/main/kotlin/nebulosa/api/guiding/GuiderMessageEvent.kt +++ b/api/src/main/kotlin/nebulosa/api/guiding/GuiderMessageEvent.kt @@ -2,4 +2,4 @@ package nebulosa.api.guiding import nebulosa.api.message.MessageEvent -data class GuiderMessageEvent(override val eventName: String, val data: Any? = null) : MessageEvent +data class GuiderMessageEvent(override val eventName: String, @JvmField val data: Any? = null) : MessageEvent diff --git a/api/src/main/kotlin/nebulosa/api/guiding/HistoryStep.kt b/api/src/main/kotlin/nebulosa/api/guiding/HistoryStep.kt index a4f178d70..61f22abcd 100644 --- a/api/src/main/kotlin/nebulosa/api/guiding/HistoryStep.kt +++ b/api/src/main/kotlin/nebulosa/api/guiding/HistoryStep.kt @@ -3,11 +3,11 @@ package nebulosa.api.guiding import nebulosa.guiding.GuideStep data class HistoryStep( - val id: Long = 0L, - val rmsRA: Double = 0.0, - val rmsDEC: Double = 0.0, - val rmsTotal: Double = 0.0, - val guideStep: GuideStep? = null, - val ditherX: Double = 0.0, - val ditherY: Double = 0.0, + @JvmField val id: Long = 0L, + @JvmField val rmsRA: Double = 0.0, + @JvmField val rmsDEC: Double = 0.0, + @JvmField val rmsTotal: Double = 0.0, + @JvmField val guideStep: GuideStep? = null, + @JvmField val ditherX: Double = 0.0, + @JvmField val ditherY: Double = 0.0, ) diff --git a/api/src/main/kotlin/nebulosa/api/guiding/SettleInfo.kt b/api/src/main/kotlin/nebulosa/api/guiding/SettleInfo.kt index f46d6986d..5ec2eda2b 100644 --- a/api/src/main/kotlin/nebulosa/api/guiding/SettleInfo.kt +++ b/api/src/main/kotlin/nebulosa/api/guiding/SettleInfo.kt @@ -4,9 +4,9 @@ import nebulosa.guiding.Guider import org.hibernate.validator.constraints.Range data class SettleInfo( - @Range(min = 1, max = 25) val amount: Double = 1.5, - @Range(min = 1, max = 60) val time: Long = 10, - @Range(min = 1, max = 60) val timeout: Long = 30, + @Range(min = 1, max = 25) @JvmField val amount: Double = 1.5, + @Range(min = 1, max = 60) @JvmField val time: Long = 10, + @Range(min = 1, max = 60) @JvmField val timeout: Long = 30, ) { companion object { diff --git a/api/src/main/kotlin/nebulosa/api/image/CoordinateInterpolation.kt b/api/src/main/kotlin/nebulosa/api/image/CoordinateInterpolation.kt index 5fa45e25a..563c7723f 100644 --- a/api/src/main/kotlin/nebulosa/api/image/CoordinateInterpolation.kt +++ b/api/src/main/kotlin/nebulosa/api/image/CoordinateInterpolation.kt @@ -4,8 +4,12 @@ import java.time.LocalDateTime @Suppress("ArrayInDataClass") data class CoordinateInterpolation( - val ma: DoubleArray, - val md: DoubleArray, - val x0: Int, val y0: Int, val x1: Int, val y1: Int, - val delta: Int, val date: LocalDateTime?, + @JvmField val ma: DoubleArray, + @JvmField val md: DoubleArray, + @JvmField val x0: Int, + @JvmField val y0: Int, + @JvmField val x1: Int, + @JvmField val y1: Int, + @JvmField val delta: Int, + @JvmField val date: LocalDateTime?, ) diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageAnnotation.kt b/api/src/main/kotlin/nebulosa/api/image/ImageAnnotation.kt index 5253b0038..1db713fd5 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageAnnotation.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageAnnotation.kt @@ -15,9 +15,9 @@ import nebulosa.skycatalog.SkyObjectType data class ImageAnnotation( override val x: Double, override val y: Double, - val star: StarDSO? = null, - val dso: StarDSO? = null, - val minorPlanet: MinorPlanet? = null, + @JvmField val star: StarDSO? = null, + @JvmField val dso: StarDSO? = null, + @JvmField val minorPlanet: MinorPlanet? = null, ) : Point2D { data class StarDSO( @@ -48,6 +48,6 @@ data class ImageAnnotation( @field:JsonSerialize(using = RightAscensionSerializer::class) override val rightAscensionJ2000: Angle = 0.0, @field:JsonSerialize(using = DeclinationSerializer::class) override val declinationJ2000: Angle = 0.0, override val magnitude: Double = SkyObject.UNKNOWN_MAGNITUDE, - val constellation: Constellation = Constellation.find(ICRF.equatorial(rightAscensionJ2000, declinationJ2000)), + @JvmField val constellation: Constellation = Constellation.find(ICRF.equatorial(rightAscensionJ2000, declinationJ2000)), ) : SkyObject } diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageHeaderItem.kt b/api/src/main/kotlin/nebulosa/api/image/ImageHeaderItem.kt index faf357950..b02f3a15d 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageHeaderItem.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageHeaderItem.kt @@ -1,3 +1,3 @@ package nebulosa.api.image -data class ImageHeaderItem(val name: String, val value: String) +data class ImageHeaderItem(@JvmField val name: String, @JvmField val value: String) diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageInfo.kt b/api/src/main/kotlin/nebulosa/api/image/ImageInfo.kt index f9afc085d..9c41c8d78 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageInfo.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageInfo.kt @@ -10,14 +10,18 @@ import nebulosa.indi.device.camera.Camera import java.nio.file.Path data class ImageInfo( - val path: Path, - val width: Int, val height: Int, val mono: Boolean, - val stretchShadow: Float = 0.0f, val stretchHighlight: Float = 1.0f, val stretchMidtone: Float = 0.5f, - @field:JsonSerialize(using = RightAscensionSerializer::class) val rightAscension: Double? = null, - @field:JsonSerialize(using = DeclinationSerializer::class) val declination: Double? = null, - val solved: ImageSolved? = null, - val headers: List = emptyList(), - val bitpix: Bitpix = Bitpix.BYTE, - val camera: Camera? = null, - @JsonIgnoreProperties("histogram") val statistics: Statistics.Data? = null, + @JvmField val path: Path, + @JvmField val width: Int, + @JvmField val height: Int, + @JvmField val mono: Boolean, + @JvmField val stretchShadow: Float = 0.0f, + @JvmField val stretchHighlight: Float = 1.0f, + @JvmField val stretchMidtone: Float = 0.5f, + @field:JsonSerialize(using = RightAscensionSerializer::class) @JvmField val rightAscension: Double? = null, + @field:JsonSerialize(using = DeclinationSerializer::class) @JvmField val declination: Double? = null, + @JvmField val solved: ImageSolved? = null, + @JvmField val headers: List = emptyList(), + @JvmField val bitpix: Bitpix = Bitpix.BYTE, + @JvmField val camera: Camera? = null, + @JsonIgnoreProperties("histogram") @JvmField val statistics: Statistics.Data? = null, ) diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageSolved.kt b/api/src/main/kotlin/nebulosa/api/image/ImageSolved.kt index 5823fffc0..04202b45f 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageSolved.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageSolved.kt @@ -4,14 +4,14 @@ import nebulosa.math.* import nebulosa.platesolver.PlateSolution data class ImageSolved( - val solved: Boolean = false, - val orientation: Double = 0.0, - val scale: Double = 0.0, - val rightAscensionJ2000: String = "", - val declinationJ2000: String = "", - val width: Double = 0.0, - val height: Double = 0.0, - val radius: Double = 0.0, + @JvmField val solved: Boolean = false, + @JvmField val orientation: Double = 0.0, + @JvmField val scale: Double = 0.0, + @JvmField val rightAscensionJ2000: String = "", + @JvmField val declinationJ2000: String = "", + @JvmField val width: Double = 0.0, + @JvmField val height: Double = 0.0, + @JvmField val radius: Double = 0.0, ) { constructor(solution: PlateSolution) : this( diff --git a/api/src/main/kotlin/nebulosa/api/image/SaveImage.kt b/api/src/main/kotlin/nebulosa/api/image/SaveImage.kt index 1bfa717f4..2c551086f 100644 --- a/api/src/main/kotlin/nebulosa/api/image/SaveImage.kt +++ b/api/src/main/kotlin/nebulosa/api/image/SaveImage.kt @@ -4,9 +4,9 @@ import nebulosa.fits.Bitpix import java.nio.file.Path data class SaveImage( - val format: ImageExtension = ImageExtension.FITS, - val bitpix: Bitpix = Bitpix.BYTE, - val shouldBeTransformed: Boolean = true, - val transformation: ImageTransformation = ImageTransformation.EMPTY, - val path: Path? = null, + @JvmField val format: ImageExtension = ImageExtension.FITS, + @JvmField val bitpix: Bitpix = Bitpix.BYTE, + @JvmField val shouldBeTransformed: Boolean = true, + @JvmField val transformation: ImageTransformation = ImageTransformation.EMPTY, + @JvmField val path: Path? = null, ) diff --git a/api/src/main/kotlin/nebulosa/api/indi/INDIMessageEvent.kt b/api/src/main/kotlin/nebulosa/api/indi/INDIMessageEvent.kt index 06c49459b..19b320255 100644 --- a/api/src/main/kotlin/nebulosa/api/indi/INDIMessageEvent.kt +++ b/api/src/main/kotlin/nebulosa/api/indi/INDIMessageEvent.kt @@ -9,8 +9,8 @@ import nebulosa.indi.device.PropertyVector data class INDIMessageEvent( override val eventName: String, override val device: Device? = null, - val property: PropertyVector<*, *>? = null, - val message: String? = null, + @JvmField val property: PropertyVector<*, *>? = null, + @JvmField val message: String? = null, ) : DeviceMessageEvent { constructor(eventName: String, event: DevicePropertyEvent) : this(eventName, event.device, property = event.property) diff --git a/api/src/main/kotlin/nebulosa/api/indi/INDISendProperty.kt b/api/src/main/kotlin/nebulosa/api/indi/INDISendProperty.kt index 9e71146b8..3bd06d872 100644 --- a/api/src/main/kotlin/nebulosa/api/indi/INDISendProperty.kt +++ b/api/src/main/kotlin/nebulosa/api/indi/INDISendProperty.kt @@ -7,7 +7,7 @@ import jakarta.validation.constraints.NotNull import nebulosa.indi.protocol.PropertyType data class INDISendProperty( - @field:NotBlank val name: String = "", - @field:NotNull val type: PropertyType = PropertyType.SWITCH, - @field:NotEmpty @field:Valid val items: List = emptyList(), + @field:NotBlank @JvmField val name: String = "", + @field:NotNull @JvmField val type: PropertyType = PropertyType.SWITCH, + @field:NotEmpty @field:Valid @JvmField val items: List = emptyList(), ) diff --git a/api/src/main/kotlin/nebulosa/api/indi/INDISendPropertyItem.kt b/api/src/main/kotlin/nebulosa/api/indi/INDISendPropertyItem.kt index 8b506a378..c6d382497 100644 --- a/api/src/main/kotlin/nebulosa/api/indi/INDISendPropertyItem.kt +++ b/api/src/main/kotlin/nebulosa/api/indi/INDISendPropertyItem.kt @@ -4,6 +4,6 @@ import jakarta.validation.constraints.NotBlank import jakarta.validation.constraints.NotNull data class INDISendPropertyItem( - @field:NotBlank val name: String = "", - @field:NotNull val value: Any = "", + @field:NotBlank @JvmField val name: String = "", + @field:NotNull @JvmField val value: Any = "", ) diff --git a/api/src/main/kotlin/nebulosa/api/livestacker/LiveStackingRequest.kt b/api/src/main/kotlin/nebulosa/api/livestacker/LiveStackingRequest.kt index 6f3cd31db..1d9a3bb47 100644 --- a/api/src/main/kotlin/nebulosa/api/livestacker/LiveStackingRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/livestacker/LiveStackingRequest.kt @@ -1,12 +1,10 @@ package nebulosa.api.livestacker +import jakarta.validation.constraints.NotNull import nebulosa.livestacker.LiveStacker import nebulosa.pixinsight.livestacker.PixInsightLiveStacker -import nebulosa.pixinsight.script.PixInsightIsRunning -import nebulosa.pixinsight.script.PixInsightScriptRunner -import nebulosa.pixinsight.script.PixInsightStartup +import nebulosa.pixinsight.script.startPixInsight import nebulosa.siril.livestacker.SirilLiveStacker -import org.jetbrains.annotations.NotNull import java.nio.file.Files import java.nio.file.Path import java.util.function.Supplier @@ -15,9 +13,9 @@ data class LiveStackingRequest( @JvmField val enabled: Boolean = false, @JvmField val type: LiveStackerType = LiveStackerType.SIRIL, @JvmField @field:NotNull val executablePath: Path? = null, - @JvmField val dark: Path? = null, - @JvmField val flat: Path? = null, - @JvmField val bias: Path? = null, + @JvmField val darkPath: Path? = null, + @JvmField val flatPath: Path? = null, + @JvmField val biasPath: Path? = null, @JvmField val use32Bits: Boolean = false, @JvmField val slot: Int = 1, ) : Supplier { @@ -26,17 +24,10 @@ data class LiveStackingRequest( val workingDirectory = Files.createTempDirectory("ls-") return when (type) { - LiveStackerType.SIRIL -> SirilLiveStacker(executablePath!!, workingDirectory, dark, flat, use32Bits) + LiveStackerType.SIRIL -> SirilLiveStacker(executablePath!!, workingDirectory, darkPath, flatPath, use32Bits) LiveStackerType.PIXINSIGHT -> { - val runner = PixInsightScriptRunner(executablePath!!) - - if (!PixInsightIsRunning(slot).use { it.runSync(runner) }) { - if (!PixInsightStartup(slot).use { it.runSync(runner) }) { - throw IllegalStateException("unable to start PixInsight") - } - } - - PixInsightLiveStacker(runner, workingDirectory, dark, flat, bias, use32Bits, slot) + val runner = startPixInsight(executablePath!!, slot) + PixInsightLiveStacker(runner, workingDirectory, darkPath, flatPath, biasPath, use32Bits, slot) } } } diff --git a/api/src/main/kotlin/nebulosa/api/mounts/ComputedLocation.kt b/api/src/main/kotlin/nebulosa/api/mounts/ComputedLocation.kt index f825170f9..497350194 100644 --- a/api/src/main/kotlin/nebulosa/api/mounts/ComputedLocation.kt +++ b/api/src/main/kotlin/nebulosa/api/mounts/ComputedLocation.kt @@ -12,15 +12,15 @@ import nebulosa.nova.astrometry.Constellation import java.time.LocalDateTime data class ComputedLocation( - @field:JsonSerialize(using = RightAscensionSerializer::class) var rightAscension: Angle = 0.0, - @field:JsonSerialize(using = DeclinationSerializer::class) var declination: Angle = 0.0, - @field:JsonSerialize(using = RightAscensionSerializer::class) var rightAscensionJ2000: Angle = 0.0, - @field:JsonSerialize(using = DeclinationSerializer::class) var declinationJ2000: Angle = 0.0, - @field:JsonSerialize(using = AzimuthSerializer::class) var azimuth: Angle = 0.0, - @field:JsonSerialize(using = DeclinationSerializer::class) var altitude: Angle = 0.0, - var constellation: Constellation = Constellation.AND, - @field:JsonSerialize(using = LSTSerializer::class) var lst: Angle = 0.0, - @field:JsonFormat(pattern = "HH:mm") var meridianAt: LocalDateTime = LocalDateTime.MIN, - @field:JsonSerialize(using = LSTSerializer::class) var timeLeftToMeridianFlip: Angle = 0.0, - var pierSide: PierSide = PierSide.NEITHER, + @field:JsonSerialize(using = RightAscensionSerializer::class) @JvmField var rightAscension: Angle = 0.0, + @field:JsonSerialize(using = DeclinationSerializer::class) @JvmField var declination: Angle = 0.0, + @field:JsonSerialize(using = RightAscensionSerializer::class) @JvmField var rightAscensionJ2000: Angle = 0.0, + @field:JsonSerialize(using = DeclinationSerializer::class) @JvmField var declinationJ2000: Angle = 0.0, + @field:JsonSerialize(using = AzimuthSerializer::class) @JvmField var azimuth: Angle = 0.0, + @field:JsonSerialize(using = DeclinationSerializer::class) @JvmField var altitude: Angle = 0.0, + @JvmField var constellation: Constellation = Constellation.AND, + @field:JsonSerialize(using = LSTSerializer::class) @JvmField var lst: Angle = 0.0, + @field:JsonFormat(pattern = "HH:mm") @JvmField var meridianAt: LocalDateTime = LocalDateTime.MIN, + @field:JsonSerialize(using = LSTSerializer::class) @JvmField var timeLeftToMeridianFlip: Angle = 0.0, + @JvmField var pierSide: PierSide = PierSide.NEITHER, ) diff --git a/api/src/main/kotlin/nebulosa/api/preference/PreferenceEntity.kt b/api/src/main/kotlin/nebulosa/api/preference/PreferenceEntity.kt index b00b5d7f2..4364d1baa 100644 --- a/api/src/main/kotlin/nebulosa/api/preference/PreferenceEntity.kt +++ b/api/src/main/kotlin/nebulosa/api/preference/PreferenceEntity.kt @@ -9,6 +9,6 @@ import nebulosa.api.database.BoxEntity @Entity data class PreferenceEntity( @Id override var id: Long = 0L, - @Unique(onConflict = ConflictStrategy.REPLACE) var key: String = "", - var value: String? = null, + @Unique(onConflict = ConflictStrategy.REPLACE) @JvmField var key: String = "", + @JvmField var value: String? = null, ) : BoxEntity diff --git a/api/src/main/kotlin/nebulosa/api/preference/PreferenceRequestBody.kt b/api/src/main/kotlin/nebulosa/api/preference/PreferenceRequestBody.kt deleted file mode 100644 index 00e0448f2..000000000 --- a/api/src/main/kotlin/nebulosa/api/preference/PreferenceRequestBody.kt +++ /dev/null @@ -1,3 +0,0 @@ -package nebulosa.api.preference - -data class PreferenceRequestBody(val data: Any?) diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackerController.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackerController.kt new file mode 100644 index 000000000..382b5aa3a --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackerController.kt @@ -0,0 +1,21 @@ +package nebulosa.api.stacker + +import jakarta.validation.Valid +import org.springframework.validation.annotation.Validated +import org.springframework.web.bind.annotation.* +import java.nio.file.Path + +@Validated +@RestController +@RequestMapping("stacker") +class StackerController(private val stackerService: StackerService) { + + @PutMapping + fun stack(@RequestBody @Valid body: StackingRequest): Path? { + return stackerService.stack(body) + } + + @PutMapping("analyze") + fun analyze(@RequestParam path: Path) { + } +} diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackerGroupType.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackerGroupType.kt new file mode 100644 index 000000000..067f1430c --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackerGroupType.kt @@ -0,0 +1,10 @@ +package nebulosa.api.stacker + +enum class StackerGroupType { + LUMINANCE, + RED, + GREEN, + BLUE, + MONO, + RGB, +} diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt new file mode 100644 index 000000000..32b277406 --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt @@ -0,0 +1,78 @@ +package nebulosa.api.stacker + +import nebulosa.stacker.AutoStacker +import org.springframework.stereotype.Service +import java.nio.file.Path + +@Service +class StackerService { + + fun stack(request: StackingRequest): Path? { + val luminance = request.targets.filter { it.enabled && it.group == StackerGroupType.LUMINANCE } + val red = request.targets.filter { it.enabled && it.group == StackerGroupType.RED } + val green = request.targets.filter { it.enabled && it.group == StackerGroupType.GREEN } + val blue = request.targets.filter { it.enabled && it.group == StackerGroupType.BLUE } + val mono = request.targets.filter { it.enabled && it.group == StackerGroupType.MONO } + val rgb = request.targets.filter { it.enabled && it.group == StackerGroupType.RGB } + + val name = "${System.currentTimeMillis()}" + + // Combined LRGB + return if (luminance.size + red.size + green.size + blue.size > 1) { + val stacker = request.get() + + val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE) + val stackedRedPath = red.stack(request, stacker, name, StackerGroupType.RED) + val stackedGreenPath = green.stack(request, stacker, name, StackerGroupType.GREEN) + val stackedBluePath = blue.stack(request, stacker, name, StackerGroupType.BLUE) + + val combinedPath = Path.of("${request.outputDirectory}", "$name.LRGB.fits") + stacker.combineLRGB(combinedPath, stackedLuminancePath, stackedRedPath, stackedGreenPath, stackedBluePath) + combinedPath + } + // LRGB + else if (rgb.size > 1 || luminance.size + rgb.size > 1) { + val stacker = request.get() + + val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE) + val stackedRGBPath = rgb.stack(request, stacker, name, StackerGroupType.RGB) + + if (stackedLuminancePath != null && stackedRGBPath != null) { + val combinedPath = Path.of("${request.outputDirectory}", "$name.LRGB.fits") + stacker.combineLuminance(combinedPath, stackedLuminancePath, stackedRGBPath, false) + combinedPath + } else { + stackedLuminancePath ?: stackedRGBPath + } + } + // MONO + else if (mono.size > 1 || luminance.size + mono.size > 1) { + val stacker = request.get() + + val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE) + val stackedMonoPath = mono.stack(request, stacker, name, StackerGroupType.MONO) + + if (stackedLuminancePath != null && stackedMonoPath != null) { + val combinedPath = Path.of("${request.outputDirectory}", "$name.LRGB.fits") + stacker.combineLuminance(combinedPath, stackedLuminancePath, stackedMonoPath, true) + combinedPath + } else { + stackedLuminancePath ?: stackedMonoPath + } + } else { + null + } + } + + private fun List.stack(request: StackingRequest, stacker: AutoStacker, name: String, group: StackerGroupType): Path? { + return if (size > 1) { + val outputPath = Path.of("${request.outputDirectory}", "$name.$group.fits") + if (stacker.stack(map { it.path!! }, outputPath, request.referencePath!!)) outputPath else null + } else if (isNotEmpty()) { + val outputPath = Path.of("${request.outputDirectory}", "$name.$group.fits") + if (stacker.align(request.referencePath!!, this[0].path!!, outputPath)) outputPath else null + } else { + null + } + } +} diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackerType.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackerType.kt new file mode 100644 index 000000000..4aee6a289 --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackerType.kt @@ -0,0 +1,5 @@ +package nebulosa.api.stacker + +enum class StackerType { + PIXINSIGHT, +} diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackingRequest.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackingRequest.kt new file mode 100644 index 000000000..9afe5a710 --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackingRequest.kt @@ -0,0 +1,36 @@ +package nebulosa.api.stacker + +import jakarta.validation.Valid +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Size +import nebulosa.pixinsight.script.startPixInsight +import nebulosa.pixinsight.stacker.PixInsightAutoStacker +import nebulosa.stacker.AutoStacker +import java.nio.file.Files +import java.nio.file.Path +import java.util.function.Supplier + +data class StackingRequest( + @JvmField @field:NotNull val outputDirectory: Path? = null, + @JvmField val type: StackerType = StackerType.PIXINSIGHT, + @JvmField @field:NotNull val executablePath: Path? = null, + @JvmField val darkPath: Path? = null, + @JvmField val flatPath: Path? = null, + @JvmField val biasPath: Path? = null, + @JvmField val use32Bits: Boolean = false, + @JvmField val slot: Int = 1, + @JvmField @field:NotNull val referencePath: Path? = null, + @JvmField @field:Size(min = 2) @field:Valid val targets: List = emptyList(), +) : Supplier { + + override fun get(): AutoStacker { + val workingDirectory = Files.createTempDirectory("as-") + + return when (type) { + StackerType.PIXINSIGHT -> { + val runner = startPixInsight(executablePath!!, slot) + PixInsightAutoStacker(runner, workingDirectory, darkPath, flatPath, biasPath, slot) + } + } + } +} diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackingTarget.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackingTarget.kt new file mode 100644 index 000000000..a544f999f --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackingTarget.kt @@ -0,0 +1,11 @@ +package nebulosa.api.stacker + +import jakarta.validation.constraints.NotNull +import java.nio.file.Path + +data class StackingTarget( + @JvmField val enabled: Boolean = true, + @JvmField @field:NotNull val path: Path? = null, + @JvmField val group: StackerGroupType = StackerGroupType.MONO, + @JvmField val debayer: Boolean = true, +) diff --git a/api/src/main/kotlin/nebulosa/api/stardetector/StarDetectionRequest.kt b/api/src/main/kotlin/nebulosa/api/stardetector/StarDetectionRequest.kt index c43e42c1f..982f000a9 100644 --- a/api/src/main/kotlin/nebulosa/api/stardetector/StarDetectionRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/stardetector/StarDetectionRequest.kt @@ -1,9 +1,7 @@ package nebulosa.api.stardetector import nebulosa.astap.stardetector.AstapStarDetector -import nebulosa.pixinsight.script.PixInsightIsRunning -import nebulosa.pixinsight.script.PixInsightScriptRunner -import nebulosa.pixinsight.script.PixInsightStartup +import nebulosa.pixinsight.script.startPixInsight import nebulosa.pixinsight.stardetector.PixInsightStarDetector import nebulosa.siril.stardetector.SirilStarDetector import nebulosa.stardetector.StarDetector @@ -24,14 +22,7 @@ data class StarDetectionRequest( StarDetectorType.ASTAP -> AstapStarDetector(executablePath!!, minSNR) StarDetectorType.SIRIL -> SirilStarDetector(executablePath!!, maxStars) StarDetectorType.PIXINSIGHT -> { - val runner = PixInsightScriptRunner(executablePath!!) - - if (!PixInsightIsRunning(slot).use { it.runSync(runner) }) { - if (!PixInsightStartup(slot).use { it.runSync(runner) }) { - throw IllegalStateException("unable to start PixInsight") - } - } - + val runner = startPixInsight(executablePath!!, slot) PixInsightStarDetector(runner, slot, minSNR, timeout) } } diff --git a/desktop/.editorconfig b/desktop/.editorconfig index 350957ed8..ccc726593 100644 --- a/desktop/.editorconfig +++ b/desktop/.editorconfig @@ -11,6 +11,7 @@ trim_trailing_whitespace = true [*.ts, *.js] quote_type = single +insert_final_newline = true [*.md] trim_trailing_whitespace = false diff --git a/desktop/src/app/about/about.component.html b/desktop/src/app/about/about.component.html index cfddc9af2..c2fc494dd 100644 --- a/desktop/src/app/about/about.component.html +++ b/desktop/src/app/about/about.component.html @@ -39,7 +39,7 @@
Stack icon by Pixel perfect - Flaticon + + Photo filter icon by Freepik - Flaticon + diff --git a/desktop/src/app/app-routing.module.ts b/desktop/src/app/app-routing.module.ts index 04dfdb38a..7f637d3fe 100644 --- a/desktop/src/app/app-routing.module.ts +++ b/desktop/src/app/app-routing.module.ts @@ -20,6 +20,7 @@ import { MountComponent } from './mount/mount.component' import { RotatorComponent } from './rotator/rotator.component' import { SequencerComponent } from './sequencer/sequencer.component' import { SettingsComponent } from './settings/settings.component' +import { StackerComponent } from './stacker/stacker.component' const routes: Routes = [ { @@ -91,6 +92,10 @@ const routes: Routes = [ path: 'auto-focus', component: AutoFocusComponent, }, + { + path: 'stacker', + component: StackerComponent, + }, { path: 'calculator', component: CalculatorComponent, diff --git a/desktop/src/app/app.module.ts b/desktop/src/app/app.module.ts index b16bd44e5..2bc430f40 100644 --- a/desktop/src/app/app.module.ts +++ b/desktop/src/app/app.module.ts @@ -93,6 +93,7 @@ import { MountComponent } from './mount/mount.component' import { RotatorComponent } from './rotator/rotator.component' import { SequencerComponent } from './sequencer/sequencer.component' import { SettingsComponent } from './settings/settings.component' +import { StackerComponent } from './stacker/stacker.component' @NgModule({ declarations: [ @@ -141,6 +142,7 @@ import { SettingsComponent } from './settings/settings.component' SettingsComponent, SkyObjectPipe, SlideMenuComponent, + StackerComponent, StopPropagationDirective, WinPipe, ], diff --git a/desktop/src/app/camera/camera.component.html b/desktop/src/app/camera/camera.component.html index 3fdeabac0..4eed5b90b 100644 --- a/desktop/src/app/camera/camera.component.html +++ b/desktop/src/app/camera/camera.component.html @@ -609,7 +609,7 @@ [directory]="false" label="Dark File" key="LS_DARK_PATH" - [(path)]="liveStacking.request.dark" + [(path)]="liveStacking.request.darkPath" class="w-full" (pathChange)="savePreference()" />
@@ -619,7 +619,7 @@ [directory]="false" label="Flat File" key="LS_FLAT_PATH" - [(path)]="liveStacking.request.flat" + [(path)]="liveStacking.request.flatPath" class="w-full" (pathChange)="savePreference()" />
@@ -629,7 +629,7 @@ [directory]="false" label="Bias File" key="LS_BIAS_PATH" - [(path)]="liveStacking.request.bias" + [(path)]="liveStacking.request.biasPath" class="w-full" (pathChange)="savePreference()" />
diff --git a/desktop/src/app/camera/camera.component.ts b/desktop/src/app/camera/camera.component.ts index 668fac8f5..43b72eaba 100644 --- a/desktop/src/app/camera/camera.component.ts +++ b/desktop/src/app/camera/camera.component.ts @@ -750,9 +750,9 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Pingable { this.request.liveStacking.enabled = cameraPreference.liveStacking?.enabled ?? false this.request.liveStacking.type = cameraPreference.liveStacking?.type ?? 'SIRIL' this.request.liveStacking.executablePath = cameraPreference.liveStacking?.executablePath ?? '' - this.request.liveStacking.dark = cameraPreference.liveStacking?.dark - this.request.liveStacking.flat = cameraPreference.liveStacking?.flat - this.request.liveStacking.bias = cameraPreference.liveStacking?.bias + this.request.liveStacking.darkPath = cameraPreference.liveStacking?.darkPath + this.request.liveStacking.flatPath = cameraPreference.liveStacking?.flatPath + this.request.liveStacking.biasPath = cameraPreference.liveStacking?.biasPath this.request.liveStacking.use32Bits = cameraPreference.liveStacking?.use32Bits ?? false this.request.liveStacking.slot = cameraPreference.liveStacking?.slot ?? 1 diff --git a/desktop/src/app/settings/settings.component.html b/desktop/src/app/settings/settings.component.html index 95f91e293..d4e0ed15f 100644 --- a/desktop/src/app/settings/settings.component.html +++ b/desktop/src/app/settings/settings.component.html @@ -2,11 +2,10 @@
@@ -14,7 +13,7 @@
+ *ngIf="tab === 'LOCATION'">
@@ -61,7 +60,7 @@
+ *ngIf="tab === 'PLATE_SOLVER'">
@@ -139,7 +138,7 @@
+ *ngIf="tab === 'STAR_DETECTOR'">
@@ -236,7 +235,7 @@
+ *ngIf="tab === 'LIVE_STACKER'">
@@ -282,7 +281,7 @@
+ *ngIf="tab === 'CAPTURE_NAMING_FORMAT'">
diff --git a/desktop/src/app/settings/settings.component.ts b/desktop/src/app/settings/settings.component.ts index d164128f5..3c5677e8d 100644 --- a/desktop/src/app/settings/settings.component.ts +++ b/desktop/src/app/settings/settings.component.ts @@ -6,7 +6,7 @@ import { PreferenceService } from '../../shared/services/preference.service' import { PrimeService } from '../../shared/services/prime.service' import { EMPTY_LOCATION, Location } from '../../shared/types/atlas.types' import { FrameType, LiveStackerType, LiveStackingRequest } from '../../shared/types/camera.types' -import { DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, PlateSolverRequest, PlateSolverType, resetCameraCaptureNamingFormat, StarDetectionRequest, StarDetectorType } from '../../shared/types/settings.types' +import { DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, PlateSolverRequest, PlateSolverType, resetCameraCaptureNamingFormat, SettingsTabKey, StarDetectionRequest, StarDetectorType } from '../../shared/types/settings.types' import { AppComponent } from '../app.component' @Component({ @@ -14,29 +14,8 @@ import { AppComponent } from '../app.component' templateUrl: './settings.component.html', }) export class SettingsComponent { - tab = 0 - readonly tabs: { id: number; name: string }[] = [ - { - id: 0, - name: 'Location', - }, - { - id: 1, - name: 'Plate Solver', - }, - { - id: 2, - name: 'Star Detection', - }, - { - id: 3, - name: 'Live Stacking', - }, - { - id: 4, - name: 'Capture Naming Format', - }, - ] + tab: SettingsTabKey = 'LOCATION' + readonly tabs: SettingsTabKey[] = ['LOCATION', 'PLATE_SOLVER', 'STAR_DETECTOR', 'LIVE_STACKER', 'STACKER', 'CAPTURE_NAMING_FORMAT'] readonly locations: Location[] location: Location diff --git a/desktop/src/app/stacker/stacker.component.html b/desktop/src/app/stacker/stacker.component.html new file mode 100644 index 000000000..e69de29bb diff --git a/desktop/src/app/stacker/stacker.component.ts b/desktop/src/app/stacker/stacker.component.ts new file mode 100644 index 000000000..3d2357a8c --- /dev/null +++ b/desktop/src/app/stacker/stacker.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core' + +@Component({ + selector: 'neb-stacker', + templateUrl: './stacker.component.html', +}) +export class StackerComponent {} diff --git a/desktop/src/assets/icons/photo-filter.png b/desktop/src/assets/icons/photo-filter.png new file mode 100644 index 0000000000000000000000000000000000000000..d3f7a892d75eaa33910f5b86a1205413c173088f GIT binary patch literal 1657 zcmV-<28Q{GP)fUJ9K`vTe0zr>rflbV^-C7Wprhc@fh_?%gn33gh(J$JvBpa6017eN!KDLR0u<`C_~|#a3&<`O z%L^uJmBjdo2;ZUd8>DpNJdUj~AXhe9u)RfxSZ81*8RjT4eg#0I9+g@$*oh$DPKc(l z)dB>Xc?VK8u#iOgVJ!JkG=hZr1dTcy5t_%A03q?1Y1=_jlHjQ%$`MpfP4jes2>TeO z8d5Zt*b<;qtV6?ZXr~dNLwRAEr}{|pXAEkQ#5hTq&(UeM9IFww1c-`!Zg{pB+BJE$ z5hHhsCuWnMSfZ5(yNGepLZrsno(J4k-k?d@hCanOs^g>4vz=Du^(jh@CjXaZpORsQ zsU}Jll8}w4AH>m2u*LHh9m;x2^gqa!tw^B|5=&?kuMidmQ!WJUR3^0p@$~Ie2PZB<+3&ekU$NH6TnqSI4M#=?2X%}oFSqdCd+@< zQcf1ffEbAVz@PC;0muM|*U z5ugr49Z(GvgM1c5J8;o_^)rMy0YnGL-5~CoFm40U<}9i-B97nC4c494K~w^LjvUFp zEY=5x$x)myb7Sq!VgW!Aswd$8EO84E{{VY{uw#G8NfUr#T9_yssb;!)l_ zS#C;x1gYuXDFl!pjsZWWJ)oK3J^}9g%sm855MY|m+#Dw^fam~r17<#Ra|#QdD;4`b}$>eJzt zb`Qa39{^qb3g@r-lJ3Ltj!?3>H{>B2i@%qS-pRW>-2+~_`gJ-x<|V8nD?_IwKVr(C zs|2V%RlxacIb+vqECvjWUH^VLkD8`T`un;K>nffP-)w3zv~x`t=m~izCGV8BUbt@1 zQouz5WCwJzGm|&eD?(6|A2qadO&9Qcbv}BtjdKk-#8d%5SHGlo!e0!^3Zj&k#;9+U z$OLOEpAR;!>Lw?{SWwpp08p|p%H|E@Z|&M0FSWt(zx}ORI>_4_B5bZm!hXOAuIU0( zQM^zm!#n<}mlhkHG+W12E#Q9gvUEP)GRV20pYl?bHOn3{0RSq>R4U4*PW;R@9}RaE zUanAidWpRO)b#>P$EDj|zW+G@!09VK4(%8uKg;^AldH#oMBHj04}Dk_-08M=Ht4Dr z(AMLprXgo+Dm)$ajd^tRgqgTmd-QApSr_ALg$$o$rNEVL-nCSp!nnwc6 zbO19=It6gu8JzG4HGKj|`95$vZT<`p9-%53{$2kAgN^?Ks#Ak>00000NkvXXu0mjf DMA+lo literal 0 HcmV?d00001 diff --git a/desktop/src/shared/pipes/dropdown-options.pipe.ts b/desktop/src/shared/pipes/dropdown-options.pipe.ts index a0fed50c1..213b5c4e7 100644 --- a/desktop/src/shared/pipes/dropdown-options.pipe.ts +++ b/desktop/src/shared/pipes/dropdown-options.pipe.ts @@ -6,7 +6,8 @@ import { GuideDirection, GuiderPlotMode, GuiderYAxisUnit } from '../types/guider import { Bitpix, ImageChannel, ImageFormat, SCNRProtectionMethod } from '../types/image.types' import { MountRemoteControlType } from '../types/mount.types' import { SequenceCaptureMode } from '../types/sequencer.types' -import { PlateSolverType, StarDetectorType } from '../types/settings.types' +import { PlateSolverType, SettingsTabKey, StarDetectorType } from '../types/settings.types' +import { StackerType } from '../types/stacker.types' export interface DropdownOptions { STAR_DETECTOR: StarDetectorType[] @@ -28,6 +29,8 @@ export interface DropdownOptions { GUIDER_PLOT_MODE: GuiderPlotMode[] GUIDER_Y_AXIS_UNIT: GuiderYAxisUnit[] SEQUENCE_CAPTURE_MODE: SequenceCaptureMode[] + STACKER: StackerType[] + SETTINGS_TAB: SettingsTabKey[] } @Pipe({ name: 'dropdownOptions' }) @@ -72,6 +75,10 @@ export class DropdownOptionsPipe implements PipeTransform { return ['ARCSEC', 'PIXEL'] as DropdownOptions[K] case 'SEQUENCE_CAPTURE_MODE': return ['FULLY', 'INTERLEAVED'] as DropdownOptions[K] + case 'STACKER': + return ['PIXINSIGHT'] as DropdownOptions[K] + case 'SETTINGS_TAB': + return ['LOCATION', 'PLATE_SOLVER', 'STAR_DETECTOR', 'LIVE_STACKER', 'STACKER', 'CAPTURE_NAMING_FORMAT'] as DropdownOptions[K] } return [] diff --git a/desktop/src/shared/pipes/enum.pipe.ts b/desktop/src/shared/pipes/enum.pipe.ts index 4a09f52ec..69fa7a87c 100644 --- a/desktop/src/shared/pipes/enum.pipe.ts +++ b/desktop/src/shared/pipes/enum.pipe.ts @@ -8,7 +8,8 @@ import { GuideDirection, GuideState, GuiderPlotMode, GuiderYAxisUnit } from '../ import { Bitpix, SCNRProtectionMethod } from '../types/image.types' import { MountRemoteControlType } from '../types/mount.types' import { SequenceCaptureMode } from '../types/sequencer.types' -import { PlateSolverType, StarDetectorType } from '../types/settings.types' +import { PlateSolverType, SettingsTabKey, StarDetectorType } from '../types/settings.types' +import { StackerGroupType, StackerType } from '../types/stacker.types' import { Undefinable } from '../utils/types' export type EnumPipeKey = @@ -36,11 +37,16 @@ export type EnumPipeKey = | MountRemoteControlType | SequenceCaptureMode | Bitpix + | StackerType + | StackerGroupType + | SettingsTabKey | 'ALL' @Pipe({ name: 'enum' }) export class EnumPipe implements PipeTransform { readonly enums: Record> = { + 'DX/DY': 'dx/dy', + 'RA/DEC': 'RA/DEC', ABSOLUTE: 'Absolute', ACTIVE_GALAXY_NUCLEUS: 'Active Galaxy Nucleus', ACTIVE: 'Active', @@ -57,10 +63,13 @@ export class EnumPipe implements PipeTransform { AQL: 'Aquila', AQR: 'Aquarius', ARA: 'Ara', + ARCSEC: 'Arcsec', ARGOS: 'ARGOS Data Collection System', ARI: 'Aries', ASSOCIATION_OF_STARS: 'Association of Stars', ASTAP: 'Astap', + ASTROMETRY_NET_ONLINE: 'Astrometry.net (Online)', + ASTROMETRY_NET: 'Astrometry.net', ASYMPTOTIC_GIANT_BRANCH_STAR: 'Asymptotic Giant Branch Star', AUR: 'Auriga', AVERAGE_NEUTRAL: 'Average Neutral', @@ -76,16 +85,19 @@ export class EnumPipe implements PipeTransform { BLUE_OBJECT: 'Blue Object', BLUE_STRAGGLER: 'Blue Straggler', BLUE_SUPERGIANT: 'Blue Supergiant', + BLUE: 'Blue', BOO: 'Boรถtes', BRIGHTEST_GALAXY_IN_A_CLUSTER_BCG: 'Brightest Galaxy in a Cluster (BCG)', BROWN_DWARF: 'Brown Dwarf', BUBBLE: 'Bubble', BY_DRA_VARIABLE: 'BY Dra Variable', + BYTE: 'Byte', CAE: 'Caelum', CALIBRATING: 'Calibrating', CAM: 'Camelopardalis', CAP: 'Capricornus', CAPTURE_FINISHED: undefined, + CAPTURE_NAMING_FORMAT: 'Capture Naming Format', CAPTURE_STARTED: undefined, CAPTURED: 'Captured', CAR: 'Carina', @@ -134,7 +146,9 @@ export class EnumPipe implements PipeTransform { DMC: 'Disaster Monitoring', DOR: 'Dorado', DOUBLE_OR_MULTIPLE_STAR: 'Double or Multiple Star', + DOUBLE: 'Double', DRA: 'Draco', + EAST: 'East', ECLIPSING_BINARY: 'Eclipsing Binary', EDUCATION: 'Education', ELLIPSOIDAL_VARIABLE: 'Ellipsoidal Variable', @@ -158,8 +172,10 @@ export class EnumPipe implements PipeTransform { FINISHED: 'Finished', FIXED: 'Fixed', FLAT: 'Flat', + FLOAT: 'Float', FOR: 'Fornax', FORWARD: 'Forward', + FULLY: 'Fully', GALAXY_IN_PAIR_OF_GALAXIES: 'Galaxy in Pair of Galaxies', GALAXY_TOWARDS_A_CLUSTER_OF_GALAXIES: 'Galaxy towards a Cluster of Galaxies', GALAXY_TOWARDS_A_GROUP_OF_GALAXIES: 'Galaxy towards a Group of Galaxies', @@ -186,6 +202,7 @@ export class EnumPipe implements PipeTransform { GRAVITATIONALLY_LENSED_IMAGE_OF_A_GALAXY: 'Gravitationally Lensed Image of a Galaxy', GRAVITATIONALLY_LENSED_IMAGE_OF_A_QUASAR: 'Gravitationally Lensed Image of a Quasar', GRAVITATIONALLY_LENSED_IMAGE: 'Gravitationally Lensed Image', + GREEN: 'Green', GROUP_OF_GALAXIES: 'Group of Galaxies', GRU: 'Grus', GUIDING: 'Guiding', @@ -209,8 +226,10 @@ export class EnumPipe implements PipeTransform { IND: 'Indus', INFRA_RED_SOURCE: 'Infra-Red Source', INITIAL_PAUSE: 'Initial Pause', + INTEGER: 'Integer', INTELSAT: 'Intelsat', INTERACTING_GALAXIES: 'Interacting Galaxies', + INTERLEAVED: 'Interleaved', INTERSTELLAR_FILAMENT: 'Interstellar Filament', INTERSTELLAR_MEDIUM_OBJECT: 'Interstellar Medium Object', INTERSTELLAR_SHELL: 'Interstellar Shell', @@ -225,15 +244,20 @@ export class EnumPipe implements PipeTransform { LIB: 'Libra', LIGHT: 'Light', LINER_TYPE_ACTIVE_GALAXY_NUCLEUS: 'LINER-type Active Galaxy Nucleus', + LIVE_STACKER: 'Live Stacker', LMI: 'Leo Minor', + LOCATION: 'Location', LONG_PERIOD_VARIABLE: 'Long-Period Variable', + LONG: 'Long', LOOP: 'Loop', LOOPING: 'Looping', LOST_LOCK: 'Lost Lock', LOW_MASS_STAR: 'Low-mass Star', LOW_MASS_X_RAY_BINARY: 'Low Mass X-ray Binary', LOW_SURFACE_BRIGHTNESS_GALAXY: 'Low Surface Brightness Galaxy', + LUMINANCE: 'Luminance', LUP: 'Lupus', + LX200: 'LX200', LYN: 'Lynx', LYR: 'Lyra', MAIN_SEQUENCE_STAR: 'Main Sequence Star', @@ -253,6 +277,7 @@ export class EnumPipe implements PipeTransform { MOLECULAR_CLOUD: 'Molecular Cloud', MOLNIYA: 'Molniya', MON: 'Monoceros', + MONO: 'Mono', MOVING_GROUP: 'Moving Group', MOVING: 'Moving', MUS: 'Musca', @@ -264,6 +289,8 @@ export class EnumPipe implements PipeTransform { NOAA: 'NOAA', NONE: 'None', NOR: 'Norma', + NORTH: 'North', + NORTHERN: 'Northern', NOT_AN_OBJECT_ERROR_ARTEFACT: 'Not an Object (Error, Artefact, ...)', OBJECT_OF_UNKNOWN_NATURE: 'Object of Unknown Nature', OCT: 'Octans', @@ -290,9 +317,11 @@ export class EnumPipe implements PipeTransform { PER: 'Perseus', PHE: 'Phoenix', PIC: 'Pictor', + PIXEL: 'Pixel', PIXINSIGHT: 'PixInsight', PLANET: 'Planet', PLANETARY_NEBULA: 'Planetary Nebula', + PLATE_SOLVER: 'Plate Solver', POST_AGB_STAR: 'Post-AGB Star', PROTO_CLUSTER_OF_GALAXIES: 'Proto Cluster of Galaxies', PSA: 'Piscis Austrinus', @@ -310,10 +339,12 @@ export class EnumPipe implements PipeTransform { RADUGA: 'Raduga', RED_GIANT_BRANCH_STAR: 'Red Giant Branch star', RED_SUPERGIANT: 'Red Supergiant', + RED: 'Red', REFLECTION_NEBULA: 'Reflection Nebula', REGION_DEFINED_IN_THE_SKY: 'Region defined in the Sky', RESOURCE: 'Earth Resources', RET: 'Reticulum', + RGB: 'RGB', ROTATING_VARIABLE: 'Rotating Variable', RR_LYRAE_VARIABLE: 'RR Lyrae Variable', RS_CVN_VARIABLE: 'RS CVn Variable', @@ -336,21 +367,27 @@ export class EnumPipe implements PipeTransform { SEYFERT_GALAXY: 'Seyfert Galaxy', SGE: 'Sagitta', SGR: 'Sagittarius', + SHORT: 'Short', SINGLE: 'Single', SIRIL: 'Siril', SLEWED: 'Slewed', SLEWING: 'Slewing', SOLVED: 'Solved', SOLVING: 'Solving', + SOUTH: 'South', + SOUTHERN: 'Southern', SPECTROSCOPIC_BINARY: 'Spectroscopic Binary', SPIRE: 'Spire', + STACKER: 'Stacker', STACKING: 'Stacking', + STAR_DETECTOR: 'Star Detector', STAR_FORMING_REGION: 'Star Forming Region', STAR: 'Star', STARBURST_GALAXY: 'Starburst Galaxy', STARLINK: 'Starlink', STATIONS: 'Space Stations', STELLAR_STREAM: 'Stellar Stream', + STELLARIUM: 'Stellarium', STOPPED: 'Stopped', SUB_MILLIMETRIC_SOURCE: 'Sub-Millimetric Source', SUPERCLUSTER_OF_GALAXIES: 'Supercluster of Galaxies', @@ -384,6 +421,7 @@ export class EnumPipe implements PipeTransform { VUL: 'Vulpecula', WAITING: 'Waiting', WEATHER: 'Weather', + WEST: 'West', WHITE_DWARF: 'White Dwarf', WOLF_RAYET: 'Wolf-Rayet', X_COMM: 'Experimental Comm', @@ -391,28 +429,6 @@ export class EnumPipe implements PipeTransform { X_RAY_SOURCE: 'X-ray Source', YELLOW_SUPERGIANT: 'Yellow Supergiant', YOUNG_STELLAR_OBJECT: 'Young Stellar Object', - ASTROMETRY_NET: 'Astrometry.net', - ASTROMETRY_NET_ONLINE: 'Astrometry.net (Online)', - NORTH: 'North', - NORTHERN: 'Northern', - SOUTH: 'South', - SOUTHERN: 'Southern', - WEST: 'West', - EAST: 'East', - 'RA/DEC': 'RA/DEC', - 'DX/DY': 'dx/dy', - ARCSEC: 'Arcsec', - PIXEL: 'Pixel', - LX200: 'LX200', - STELLARIUM: 'Stellarium', - FULLY: 'Fully', - INTERLEAVED: 'Interleaved', - BYTE: 'Byte', - SHORT: 'Short', - INTEGER: 'Integer', - LONG: 'Long', - FLOAT: 'Float', - DOUBLE: 'Double', } // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts index 5e2366079..3763e9ddb 100644 --- a/desktop/src/shared/services/api.service.ts +++ b/desktop/src/shared/services/api.service.ts @@ -16,6 +16,7 @@ import { CelestialLocationType, Mount, MountRemoteControl, MountRemoteControlTyp import { Rotator } from '../types/rotator.types' import { SequencePlan } from '../types/sequencer.types' import { PlateSolverRequest, StarDetectionRequest } from '../types/settings.types' +import { StackingRequest } from '../types/stacker.types' import { FilterWheel } from '../types/wheel.types' import { Undefinable } from '../utils/types' import { HttpService } from './http.service' @@ -680,26 +681,10 @@ export class ApiService { return this.http.put(`auto-focus/${camera.id}/stop`) } - // PREFERENCE + // STACKER - clearPreferences() { - return this.http.put('preferences/clear') - } - - deletePreference(key: string) { - return this.http.delete(`preferences/${key}`) - } - - getPreference(key: string) { - return this.http.get(`preferences/${key}`) - } - - setPreference(key: string, data: unknown) { - return this.http.put(`preferences/${key}`, { data }) - } - - hasPreference(key: string) { - return this.http.get(`preferences/${key}/exists`) + stacker(request: StackingRequest) { + return this.http.put('stacker', request) } // CONFIRMATION diff --git a/desktop/src/shared/services/browser-window.service.ts b/desktop/src/shared/services/browser-window.service.ts index c96e3e34b..201f8877a 100644 --- a/desktop/src/shared/services/browser-window.service.ts +++ b/desktop/src/shared/services/browser-window.service.ts @@ -139,10 +139,15 @@ export class BrowserWindowService { } openCalibration(preference: WindowPreference = {}) { - Object.assign(preference, { icon: 'stack', width: 420, height: 400, minHeight: 400 }) + Object.assign(preference, { icon: 'photo-filter', width: 420, height: 400, minHeight: 400 }) return this.openWindow({ preference, id: 'calibration', path: 'calibration' }) } + openStacker(preference: WindowPreference = {}) { + Object.assign(preference, { icon: 'stack', width: 420, height: 400 }) + return this.openWindow({ preference, id: 'stacker', path: 'stacker' }) + } + openAbout() { const preference: WindowPreference = { icon: 'about', width: 430, height: 307, bringToFront: true } return this.openWindow({ preference, id: 'about', path: 'about' }) diff --git a/desktop/src/shared/types/camera.types.ts b/desktop/src/shared/types/camera.types.ts index e0bd4123d..4948c7139 100644 --- a/desktop/src/shared/types/camera.types.ts +++ b/desktop/src/shared/types/camera.types.ts @@ -293,9 +293,9 @@ export interface LiveStackingRequest { enabled: boolean type: LiveStackerType executablePath: string - dark?: string - flat?: string - bias?: string + darkPath?: string + flatPath?: string + biasPath?: string use32Bits: boolean slot: number } diff --git a/desktop/src/shared/types/settings.types.ts b/desktop/src/shared/types/settings.types.ts index 2a0d19960..c906522dd 100644 --- a/desktop/src/shared/types/settings.types.ts +++ b/desktop/src/shared/types/settings.types.ts @@ -47,6 +47,13 @@ export interface CameraCaptureNamingFormat { bias?: string } +export type SettingsTabKey = 'LOCATION' | 'PLATE_SOLVER' | 'STAR_DETECTOR' | 'LIVE_STACKER' | 'STACKER' | 'CAPTURE_NAMING_FORMAT' + +export interface SettingsTab { + id: SettingsTabKey + name: string +} + export const DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT: CameraCaptureNamingFormat = { light: '[camera]_[type]_[year:2][month][day][hour][min][sec][ms]_[filter]_[width]_[height]_[exp]_[bin]_[gain]', dark: '[camera]_[type]_[width]_[height]_[exp]_[bin]_[gain]', diff --git a/desktop/src/shared/types/stacker.types.ts b/desktop/src/shared/types/stacker.types.ts new file mode 100644 index 000000000..135f3f371 --- /dev/null +++ b/desktop/src/shared/types/stacker.types.ts @@ -0,0 +1,23 @@ +export type StackerType = 'PIXINSIGHT' + +export type StackerGroupType = 'LUMINANCE' | 'RED' | 'GREEN' | 'BLUE' | 'MONO' | 'RGB' + +export interface StackingRequest { + outputDirectory: string + type: StackerType + executablePath: string + darkPath?: string + flatPath?: string + biasPath?: string + use32Bits: boolean + slot: number + referencePath: string + targets: StackingTarget[] +} + +export interface StackingTarget { + enabled: boolean + path: string + group: StackerGroupType + debayer: boolean +} diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt index 0e44d456d..9a4a12f56 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt @@ -15,9 +15,9 @@ import kotlin.io.path.deleteIfExists data class PixInsightLiveStacker( private val runner: PixInsightScriptRunner, private val workingDirectory: Path, - private val dark: Path? = null, - private val flat: Path? = null, - private val bias: Path? = null, + private val darkPath: Path? = null, + private val flatPath: Path? = null, + private val biasPath: Path? = null, private val use32Bits: Boolean = false, private val slot: Int = PixInsightScript.UNSPECIFIED_SLOT, ) : LiveStacker { @@ -42,9 +42,7 @@ data class PixInsightLiveStacker( @Synchronized override fun start() { if (!running.get()) { - val isPixInsightRunning = PixInsightIsRunning(slot).use { it.runSync(runner) } - - if (!isPixInsightRunning) { + if (!PixInsightIsRunning(slot).use { it.runSync(runner) }) { try { check(PixInsightStartup(slot).use { it.runSync(runner) }) } catch (e: Throwable) { @@ -64,7 +62,7 @@ data class PixInsightLiveStacker( return if (running.get()) { stacking.set(true) - if (stacker.calibrate(targetPath, calibratedPath, dark, flat, bias)) { + if (stacker.calibrate(targetPath, calibratedPath, darkPath, flatPath, biasPath)) { LOG.info("live stacking calibrated. count={}, output={}", stackCount, calibratedPath) targetPath = calibratedPath } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt index 2958d15b0..67e17fc19 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt @@ -23,8 +23,8 @@ data class PixInsightAlign( ) data class Output( - @JvmField val success: Boolean = false, - @JvmField val errorMessage: String? = null, + override val success: Boolean = false, + override val errorMessage: String? = null, @JvmField val outputImage: Path? = null, @JvmField val outputMaskImage: Path? = null, @JvmField val totalPairMatches: Int = 0, @@ -45,7 +45,7 @@ data class PixInsightAlign( @JvmField val h31: Double = 0.0, @JvmField val h32: Double = 0.0, @JvmField val h33: Double = 0.0, - ) { + ) : PixInsightOutput { companion object { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt index a68dd5049..ddd3fd64d 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt @@ -21,10 +21,10 @@ data class PixInsightAutomaticBackgroundExtractor( ) data class Output( - @JvmField val success: Boolean = false, - @JvmField val errorMessage: String? = null, + override val success: Boolean = false, + override val errorMessage: String? = null, @JvmField val outputImage: Path? = null, - ) { + ) : PixInsightOutput { companion object { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt index c9c7a3f2d..9cb328be8 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt @@ -31,10 +31,10 @@ data class PixInsightCalibrate( ) data class Output( - @JvmField val success: Boolean = false, - @JvmField val errorMessage: String? = null, + override val success: Boolean = false, + override val errorMessage: String? = null, @JvmField val outputImage: Path? = null, - ) { + ) : PixInsightOutput { companion object { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt index bfb4952f1..199de03a6 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt @@ -26,10 +26,10 @@ data class PixInsightDetectStars( ) data class Output( - @JvmField val success: Boolean = false, - @JvmField val errorMessage: String? = null, + override val success: Boolean = false, + override val errorMessage: String? = null, @JvmField val stars: List = emptyList(), - ) { + ) : PixInsightOutput { override fun toString() = "Output(success=$success, errorMessage=$errorMessage, stars=${stars.size})" diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt new file mode 100644 index 000000000..638bf19fe --- /dev/null +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt @@ -0,0 +1,15 @@ +package nebulosa.pixinsight.script + +import java.nio.file.Path + +fun startPixInsight(executablePath: Path, slot: Int): PixInsightScriptRunner { + val runner = PixInsightScriptRunner(executablePath) + + if (!PixInsightIsRunning(slot).use { it.runSync(runner) }) { + if (!PixInsightStartup(slot).use { it.runSync(runner) }) { + throw IllegalStateException("unable to start PixInsight") + } + } + + return runner +} diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt index e8362387c..9b92c1304 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt @@ -8,6 +8,7 @@ import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream import kotlin.io.path.readText +@Suppress("ArrayInDataClass") data class PixInsightLRGBCombination( private val slot: Int, private val outputPath: Path, @@ -15,6 +16,7 @@ data class PixInsightLRGBCombination( private val redPath: Path? = null, private val greenPath: Path? = null, private val bluePath: Path? = null, + private val weights: DoubleArray = DEFAULT_CHANNEL_WEIGHTS, ) : AbstractPixInsightScript() { @Suppress("ArrayInDataClass") @@ -29,10 +31,10 @@ data class PixInsightLRGBCombination( ) data class Output( - @JvmField val success: Boolean = false, - @JvmField val errorMessage: String? = null, + override val success: Boolean = false, + override val errorMessage: String? = null, @JvmField val outputImage: Path? = null, - ) { + ) : PixInsightOutput { companion object { @@ -44,11 +46,12 @@ data class PixInsightLRGBCombination( private val statusPath = Files.createTempFile("pi-", ".txt") init { + require(weights.size >= 4) { "invalid weights size: ${weights.size}" } resource("pixinsight/LRGBCombination.js")!!.transferAndClose(scriptPath.outputStream()) } override val arguments = - listOf("-x=${execute(slot, scriptPath, Input(outputPath, statusPath, luminancePath, redPath, greenPath, bluePath, DEFAULT_CHANNEL_WEIGHTS))}") + listOf("-x=${execute(slot, scriptPath, Input(outputPath, statusPath, luminancePath, redPath, greenPath, bluePath, weights))}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt new file mode 100644 index 000000000..74e2a3015 --- /dev/null +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt @@ -0,0 +1,68 @@ +package nebulosa.pixinsight.script + +import nebulosa.io.resource +import nebulosa.io.transferAndClose +import java.nio.file.Files +import java.nio.file.Path +import kotlin.io.path.deleteIfExists +import kotlin.io.path.outputStream +import kotlin.io.path.readText + +data class PixInsightLuminanceCombination( + private val slot: Int, + private val outputPath: Path, + private val luminancePath: Path, + private val targetPath: Path, +) : AbstractPixInsightScript() { + + private data class Input( + @JvmField val outputPath: Path, + @JvmField val statusPath: Path, + @JvmField val luminancePath: Path, + @JvmField val targetPath: Path, + @JvmField val wWeight: Double, + ) + + data class Output( + override val success: Boolean = false, + override val errorMessage: String? = null, + @JvmField val outputImage: Path? = null, + ) : PixInsightOutput { + + companion object { + + @JvmStatic val FAILED = Output() + } + } + + private val scriptPath = Files.createTempFile("pi-", ".js") + private val statusPath = Files.createTempFile("pi-", ".txt") + + init { + resource("pixinsight/LuminanceCombination.js")!!.transferAndClose(scriptPath.outputStream()) + } + + override val arguments = + listOf("-x=${execute(slot, scriptPath, Input(outputPath, statusPath, luminancePath, targetPath, 1.0))}") + + override fun processOnComplete(exitCode: Int): Output { + if (exitCode == 0) { + repeat(30) { + val text = statusPath.readText() + + if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { + return OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), Output::class.java) + } + + Thread.sleep(1000) + } + } + + return Output.FAILED + } + + override fun close() { + scriptPath.deleteIfExists() + statusPath.deleteIfExists() + } +} diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightOutput.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightOutput.kt new file mode 100644 index 000000000..c4d73143a --- /dev/null +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightOutput.kt @@ -0,0 +1,8 @@ +package nebulosa.pixinsight.script + +sealed interface PixInsightOutput { + + val success: Boolean + + val errorMessage: String? +} diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt index a4cd13ad8..7c69ffb33 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt @@ -27,10 +27,10 @@ data class PixInsightPixelMath( ) data class Output( - @JvmField val success: Boolean = false, - @JvmField val errorMessage: String? = null, - @JvmField val stackedImage: Path? = null, - ) { + override val success: Boolean = false, + override val errorMessage: String? = null, + @JvmField val outputImage: Path? = null, + ) : PixInsightOutput { companion object { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt index 7619a92a1..ac5028c90 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt @@ -25,8 +25,10 @@ data class PixInsightAutoStacker( val alignedPath = Path.of("$workingDirectory", "aligned.xisf") try { - paths.forEachIndexed { stackCount, path -> - var targetPath = path + var stackCount = 0 + + paths.forEach { + var targetPath = it if (stacker.calibrate(targetPath, calibratedPath, darkPath, flatPath, biasPath)) { targetPath = calibratedPath @@ -35,9 +37,11 @@ data class PixInsightAutoStacker( if (stackCount > 0) { if (stacker.align(referencePath, targetPath, alignedPath)) { stacker.integrate(stackCount, outputPath, alignedPath, outputPath) + stackCount++ } } else { targetPath.copyTo(outputPath, true) + stackCount = 1 } } } finally { @@ -47,4 +51,24 @@ data class PixInsightAutoStacker( return true } + + override fun calibrate(targetPath: Path, outputPath: Path, darkPath: Path?, flatPath: Path?, biasPath: Path?): Boolean { + return stacker.calibrate(targetPath, outputPath, darkPath, flatPath, biasPath) + } + + override fun align(referencePath: Path, targetPath: Path, outputPath: Path): Boolean { + return stacker.align(referencePath, targetPath, outputPath) + } + + override fun integrate(stackCount: Int, stackedPath: Path, targetPath: Path, outputPath: Path): Boolean { + return stacker.integrate(stackCount, stackedPath, targetPath, outputPath) + } + + override fun combineLRGB(outputPath: Path, luminancePath: Path?, redPath: Path?, greenPath: Path?, bluePath: Path?): Boolean { + return stacker.combineLRGB(outputPath, luminancePath, redPath, greenPath, bluePath) + } + + override fun combineLuminance(outputPath: Path, luminancePath: Path, targetPath: Path, mono: Boolean): Boolean { + return stacker.combineLuminance(outputPath, luminancePath, targetPath, mono) + } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt index b66a33733..56909d1f6 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt @@ -29,6 +29,23 @@ data class PixInsightStacker( override fun integrate(stackCount: Int, stackedPath: Path, targetPath: Path, outputPath: Path): Boolean { val expressionRK = "({{0}} * $stackCount + {{1}}) / ${stackCount + 1}" return PixInsightPixelMath(slot, listOf(stackedPath, targetPath), outputPath, expressionRK) - .use { it.runSync(runner).stackedImage != null } + .use { it.runSync(runner).outputImage != null } + } + + override fun combineLRGB(outputPath: Path, luminancePath: Path?, redPath: Path?, greenPath: Path?, bluePath: Path?): Boolean { + if (luminancePath == null && redPath == null && greenPath == null && bluePath == null) return false + + return PixInsightLRGBCombination(slot, outputPath, luminancePath, redPath, greenPath, bluePath) + .use { it.runSync(runner).outputImage != null } + } + + override fun combineLuminance(outputPath: Path, luminancePath: Path, targetPath: Path, mono: Boolean): Boolean { + return if (mono) { + PixInsightPixelMath(slot, listOf(luminancePath, targetPath), outputPath, "{{0}} + (1 - {{0}}) * {{1}}") + .use { it.runSync(runner).outputImage != null } + } else { + PixInsightLuminanceCombination(slot, outputPath, luminancePath, targetPath) + .use { it.runSync(runner).outputImage != null } + } } } diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/ABE.js b/nebulosa-pixinsight/src/main/resources/pixinsight/ABE.js index 9ffb6e97c..7fb6fa311 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/ABE.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/ABE.js @@ -22,6 +22,7 @@ function abe() { const outputPath = input.outputPath const statusPath = input.statusPath + console.writeln("abe started") console.writeln("targetPath=" + targetPath) console.writeln("outputPath=" + outputPath) console.writeln("statusPath=" + statusPath) diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/Align.js b/nebulosa-pixinsight/src/main/resources/pixinsight/Align.js index d03400960..1df279c34 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/Align.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/Align.js @@ -42,6 +42,7 @@ function alignment() { const outputDirectory = input.outputDirectory const statusPath = input.statusPath + console.writeln("alignment started") console.writeln("referencePath=" + referencePath) console.writeln("targetPath=" + targetPath) console.writeln("outputDirectory=" + outputDirectory) diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/Calibrate.js b/nebulosa-pixinsight/src/main/resources/pixinsight/Calibrate.js index 7561a2ba0..a4290b64d 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/Calibrate.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/Calibrate.js @@ -27,6 +27,7 @@ function calibrate() { const compress = input.compress const use32Bit = input.use32Bit + console.writeln("calibration started") console.writeln("targetPath=" + targetPath) console.writeln("outputDirectory=" + outputDirectory) console.writeln("statusPath=" + statusPath) diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js b/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js index bd44e4632..455d9b6ab 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js @@ -26,6 +26,7 @@ function lrgbCombination() { const greenPath = input.greenPath const bluePath = input.bluePath + console.writeln("LRGB combination started") console.writeln("outputPath=" + outputPath) console.writeln("statusPath=" + statusPath) console.writeln("channelWeights=" + channelWeights) @@ -41,10 +42,10 @@ function lrgbCombination() { var P = new LRGBCombination P.channels = [ // enabled, id, k - [!!luminancePath, luminanceWindow? luminanceWindow.mainView.id : "", channelWeights[0]], [!!redPath, redWindow ? redWindow.mainView.id : "", channelWeights[1]], [!!greenPath, greenWindow ? greenWindow.mainView.id : "", channelWeights[2]], - [!!bluePath, blueWindow ? blueWindow.mainView.id : "", channelWeights[3]] + [!!bluePath, blueWindow ? blueWindow.mainView.id : "", channelWeights[3]], + [!!luminancePath, luminanceWindow ? luminanceWindow.mainView.id : "", channelWeights[0]] ] P.mL = 0.500 P.mc = 0.500 diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/LuminanceCombination.js b/nebulosa-pixinsight/src/main/resources/pixinsight/LuminanceCombination.js new file mode 100644 index 000000000..e70684726 --- /dev/null +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/LuminanceCombination.js @@ -0,0 +1,71 @@ +function decodeParams(hex) { + const buffer = new Uint8Array(hex.length / 4) + + for (let i = 0; i < hex.length; i += 4) { + buffer[i / 4] = parseInt(hex.substr(i, 4), 16) + } + + return JSON.parse(String.fromCharCode.apply(null, buffer)) +} + +function luminanceCombination() { + const data = { + success: true, + errorMessage: null, + outputImage: null, + } + + try { + const input = decodeParams(jsArguments[0]) + + const outputPath = input.outputPath + const statusPath = input.statusPath + const weight = input.weight + const luminancePath = input.luminancePath + const targetPath = input.targetPath + + console.writeln("Luminance combination started") + console.writeln("outputPath=" + outputPath) + console.writeln("statusPath=" + statusPath) + console.writeln("weight=" + weight) + console.writeln("luminancePath=" + luminancePath) + console.writeln("targetPath=" + targetPath) + + const luminanceWindow = luminancePath ? ImageWindow.open(luminancePath)[0] : undefined + const targetWindow = targetPath ? ImageWindow.open(targetPath)[0] : undefined + + var P = new LRGBCombination + P.channels = [ // enabled, id, k + [false, "", 1.0], + [false, "", 1.0], + [false, "", 1.0], + [true, luminanceWindow.mainView.id, weight] + ] + P.mL = 0.500 + P.mc = 0.500 + P.clipHighlights = true + P.noiseReduction = false + P.layersRemoved = 4 + P.layersProtected = 2 + P.inheritAstrometricSolution = true + + P.executeOn(targetWindow.mainView) + + targetWindow.saveAs(outputPath, false, false, false, false) + window.forceClose() + + luminanceWindow.forceClose() + + data.outputImage = outputPath + + console.writeln("Luminance combination finished") + } catch (e) { + data.success = false + data.errorMessage = e.message + console.writeln(data.errorMessage) + } finally { + File.writeTextFile(statusPath, "@" + JSON.stringify(data) + "#") + } +} + +luminanceCombination() diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/PixelMath.js b/nebulosa-pixinsight/src/main/resources/pixinsight/PixelMath.js index 7c335ff77..b3ad983a2 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/PixelMath.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/PixelMath.js @@ -12,7 +12,7 @@ function pixelMath() { const data = { success: true, errorMessage: null, - stackedImage: null, + outputImage: null, } try { @@ -47,6 +47,7 @@ function pixelMath() { } } + console.writeln("pixel math started") console.writeln("expressionRK=" + expressionRK) console.writeln("expressionG=" + expressionG) console.writeln("expressionB=" + expressionB) @@ -87,9 +88,9 @@ function pixelMath() { windows[i].forceClose() } - data.stackedImage = outputPath + data.outputImage = outputPath - console.writeln("stacking finished") + console.writeln("pixel math finished") } catch (e) { data.success = false data.errorMessage = e.message diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt index ab35696bc..2e5f8f381 100644 --- a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt @@ -10,6 +10,7 @@ import nebulosa.fits.isFits import nebulosa.image.Image import nebulosa.image.algorithms.transformation.AutoScreenTransformFunction import nebulosa.pixinsight.script.* +import nebulosa.pixinsight.script.PixInsightScript.Companion.UNSPECIFIED_SLOT import nebulosa.test.AbstractFitsAndXisfTest import nebulosa.test.NonGitHubOnlyCondition import nebulosa.xisf.isXisf @@ -32,48 +33,89 @@ class PixInsightScriptTest : AbstractFitsAndXisfTest() { .use { it.runSync(runner).shouldBeTrue() } } "calibrate" { - PixInsightCalibrate(PixInsightScript.UNSPECIFIED_SLOT, workingDirectory, PI_01_LIGHT, PI_DARK, PI_FLAT, PI_BIAS) + PixInsightCalibrate(UNSPECIFIED_SLOT, workingDirectory, PI_01_LIGHT, PI_DARK, PI_FLAT, PI_BIAS) .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-calibrate").second shouldBe "731562ee12f45bf7c1095f4773f70e71" } "align" { - PixInsightAlign(PixInsightScript.UNSPECIFIED_SLOT, workingDirectory, PI_01_LIGHT, PI_02_LIGHT) + PixInsightAlign(UNSPECIFIED_SLOT, workingDirectory, PI_01_LIGHT, PI_02_LIGHT) .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-align").second shouldBe "483ebaf15afa5957fe099f3ee2beff78" } "detect stars" { - PixInsightDetectStars(PixInsightScript.UNSPECIFIED_SLOT, PI_FOCUS_0) + PixInsightDetectStars(UNSPECIFIED_SLOT, PI_FOCUS_0) .use { it.runSync(runner).also(::println).stars } .map { it.hfd } .average() shouldBe (8.43 plusOrMinus 1e-2) - PixInsightDetectStars(PixInsightScript.UNSPECIFIED_SLOT, PI_FOCUS_30000) + PixInsightDetectStars(UNSPECIFIED_SLOT, PI_FOCUS_30000) .use { it.runSync(runner).also(::println).stars } .map { it.hfd } .average() shouldBe (1.85 plusOrMinus 1e-2) - PixInsightDetectStars(PixInsightScript.UNSPECIFIED_SLOT, PI_FOCUS_100000) + PixInsightDetectStars(UNSPECIFIED_SLOT, PI_FOCUS_100000) .use { it.runSync(runner).also(::println).stars } .map { it.hfd } .average() shouldBe (18.35 plusOrMinus 1e-2) } "pixel math" { val outputPath = tempfile("pi-stacked-", ".fits").toPath() - PixInsightPixelMath(PixInsightScript.UNSPECIFIED_SLOT, listOf(PI_01_LIGHT, PI_02_LIGHT), outputPath, "{{0}} + {{1}}") - .use { it.runSync(runner).also(::println).stackedImage.shouldNotBeNull().openAsImage() } + PixInsightPixelMath(UNSPECIFIED_SLOT, listOf(PI_01_LIGHT, PI_02_LIGHT), outputPath, "{{0}} + {{1}}") + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-pixelmath").second shouldBe "cafc8138e2ce17614dcfa10edf410b07" } "abe" { val outputPath = tempfile("pi-abe-", ".fits").toPath() - PixInsightAutomaticBackgroundExtractor(PixInsightScript.UNSPECIFIED_SLOT, PI_01_LIGHT, outputPath) + PixInsightAutomaticBackgroundExtractor(UNSPECIFIED_SLOT, PI_01_LIGHT, outputPath) .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-abe").second shouldBe "bf62207dc17190009ba215da7c011297" } "lrgb combination" { val outputPath = tempfile("pi-lrgb-", ".fits").toPath() - PixInsightLRGBCombination(PixInsightScript.UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT) + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT) .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-lrgb").second shouldBe "99db35d78f7b360e7592217f4179b189" + + val weights = doubleArrayOf(1.0, 0.2470588, 0.31764705, 0.709803921) // LRGB #3F51B5 + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT, weights) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-weighted-lrgb").second shouldBe "1148ee222fbfb382ad2d708df5b0f79f" + + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, null, null) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-lr").second shouldBe "9100d3ce892f05f4b832b2fb5f35b5a1" + + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, null, PI_01_LIGHT, null) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-lg").second shouldBe "b4e8d8f7e289db60b41ba2bbe0035344" + + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, null, null, PI_01_LIGHT) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-lb").second shouldBe "1760e7cb1d139b63022dd975fe84897d" + + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, null, PI_01_LIGHT, PI_01_LIGHT, null) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-rg").second shouldBe "8c59307b5943932aefdf2dedfe1c8178" + + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, null, PI_01_LIGHT, null, PI_01_LIGHT) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-rb").second shouldBe "1bdf9cada6a33f76dceaccdaacf30fef" + + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, null, null, PI_01_LIGHT, PI_01_LIGHT) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-bg").second shouldBe "4a9c81c71fd37546fd300d1037742fa2" + + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT, null) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-lrg").second shouldBe "06c32c8679d409302423baa3a07fb241" + + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, null, PI_01_LIGHT) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-lrb").second shouldBe "f6d026cb63f7a58fc325e422c277ff89" + + PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, null, PI_01_LIGHT, PI_01_LIGHT) + .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .transform(AutoScreenTransformFunction).save("pi-lbg").second shouldBe "67f961110fb4b9f0033b3b8dbc8b1638" } } diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightStackerTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightStackerTest.kt new file mode 100644 index 000000000..1a8574bb2 --- /dev/null +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightStackerTest.kt @@ -0,0 +1,58 @@ +import PixInsightScriptTest.Companion.openAsImage +import io.kotest.core.annotation.EnabledIf +import io.kotest.engine.spec.tempdir +import io.kotest.engine.spec.tempfile +import io.kotest.matchers.booleans.shouldBeTrue +import io.kotest.matchers.shouldBe +import nebulosa.image.algorithms.transformation.AutoScreenTransformFunction +import nebulosa.pixinsight.script.PixInsightScriptRunner +import nebulosa.pixinsight.stacker.PixInsightStacker +import nebulosa.test.AbstractFitsAndXisfTest +import nebulosa.test.NonGitHubOnlyCondition +import java.nio.file.Path + +@EnabledIf(NonGitHubOnlyCondition::class) +class PixInsightStackerTest : AbstractFitsAndXisfTest() { + + init { + val runner = PixInsightScriptRunner(Path.of("PixInsight")) + val workingDirectory = tempdir("pi-").toPath() + val stacker = PixInsightStacker(runner, workingDirectory) + + "align" { + val outputPath = tempfile("pi-", ".fits").toPath() + stacker.align(PI_01_LIGHT, PI_03_LIGHT, outputPath).shouldBeTrue() + + outputPath.openAsImage().transform(AutoScreenTransformFunction) + .save("pi-aligned").second shouldBe "106651a7c1e640852384284ec12e0977" + } + "calibrate" { + val outputPath = tempfile("pi-", ".fits").toPath() + stacker.calibrate(PI_01_LIGHT, outputPath, PI_DARK).shouldBeTrue() + + outputPath.openAsImage().transform(AutoScreenTransformFunction) + .save("pi-calibrated").second shouldBe "8f5a2632c701680b41fcfe170c9cf468" + } + "integrate" { + val outputPath = tempfile("pi-", ".fits").toPath() + stacker.integrate(1, PI_01_LIGHT, PI_01_LIGHT, outputPath).shouldBeTrue() + + outputPath.openAsImage().transform(AutoScreenTransformFunction) + .save("pi-integrated").second shouldBe "bf62207dc17190009ba215da7c011297" + } + "combine LRGB" { + val outputPath = tempfile("pi-", ".fits").toPath() + stacker.combineLRGB(outputPath, PI_01_LIGHT, PI_01_LIGHT).shouldBeTrue() + + outputPath.openAsImage().transform(AutoScreenTransformFunction) + .save("pi-lrgb-combined").second shouldBe "9100d3ce892f05f4b832b2fb5f35b5a1" + } + "combine mono luminance" { + val outputPath = tempfile("pi-", ".fits").toPath() + stacker.combineLuminance(outputPath, PI_01_LIGHT, PI_01_LIGHT, true).shouldBeTrue() + + outputPath.openAsImage().transform(AutoScreenTransformFunction) + .save("pi-mono-luminance-combined").second shouldBe "85de365a9895234222acdc6e9feb7009" + } + } +} diff --git a/nebulosa-siril/src/main/kotlin/nebulosa/siril/command/StartLs.kt b/nebulosa-siril/src/main/kotlin/nebulosa/siril/command/StartLs.kt index 716b47754..85afd66af 100644 --- a/nebulosa-siril/src/main/kotlin/nebulosa/siril/command/StartLs.kt +++ b/nebulosa-siril/src/main/kotlin/nebulosa/siril/command/StartLs.kt @@ -12,16 +12,16 @@ import kotlin.io.path.isRegularFile * Initializes a livestacking session. */ data class StartLs( - @JvmField val dark: Path? = null, - @JvmField val flat: Path? = null, + @JvmField val darkPath: Path? = null, + @JvmField val flatPath: Path? = null, @JvmField val use32Bits: Boolean = false, ) : SirilCommand, CommandLineListener { private val command by lazy { buildString(256) { append("start_ls") - if (dark != null && dark.exists() && dark.isRegularFile()) append(" \"-dark=$dark\"") - if (flat != null && flat.exists() && flat.isRegularFile()) append(" \"-flat=$flat\"") + if (darkPath != null && darkPath.exists() && darkPath.isRegularFile()) append(" \"-dark=$darkPath\"") + if (flatPath != null && flatPath.exists() && flatPath.isRegularFile()) append(" \"-flat=$flatPath\"") if (use32Bits) append(" -32bits") } } diff --git a/nebulosa-siril/src/main/kotlin/nebulosa/siril/livestacker/SirilLiveStacker.kt b/nebulosa-siril/src/main/kotlin/nebulosa/siril/livestacker/SirilLiveStacker.kt index f8617f95b..a1e421fef 100644 --- a/nebulosa-siril/src/main/kotlin/nebulosa/siril/livestacker/SirilLiveStacker.kt +++ b/nebulosa-siril/src/main/kotlin/nebulosa/siril/livestacker/SirilLiveStacker.kt @@ -14,8 +14,8 @@ import kotlin.io.path.name data class SirilLiveStacker( private val executablePath: Path, private val workingDirectory: Path, - private val dark: Path? = null, - private val flat: Path? = null, + private val darkPath: Path? = null, + private val flatPath: Path? = null, private val use32Bits: Boolean = false, ) : LiveStacker, CommandLineListener { @@ -38,7 +38,7 @@ data class SirilLiveStacker( try { check(commandLine.execute(Cd(workingDirectory))) { "failed to run cd command" } - check(commandLine.execute(StartLs(dark, flat, use32Bits))) { "failed to start livestacking" } + check(commandLine.execute(StartLs(darkPath, flatPath, use32Bits))) { "failed to start livestacking" } } catch (e: Throwable) { commandLine.close() throw e diff --git a/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt index 811c4c867..845c0d96e 100644 --- a/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt +++ b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt @@ -2,7 +2,7 @@ package nebulosa.stacker import java.nio.file.Path -interface AutoStacker { +interface AutoStacker : Stacker { fun stack(paths: Collection, outputPath: Path, referencePath: Path = paths.first()): Boolean } diff --git a/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt index bbf15d88e..76a74fcef 100644 --- a/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt +++ b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt @@ -12,4 +12,8 @@ interface Stacker { fun align(referencePath: Path, targetPath: Path, outputPath: Path): Boolean fun integrate(stackCount: Int, stackedPath: Path, targetPath: Path, outputPath: Path): Boolean + + fun combineLRGB(outputPath: Path, luminancePath: Path? = null, redPath: Path? = null, greenPath: Path? = null, bluePath: Path? = null): Boolean + + fun combineLuminance(outputPath: Path, luminancePath: Path, targetPath: Path, mono: Boolean): Boolean } From 320d7a8fb265386df7b09999c7ad72ad0de1bc77 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 13 Jul 2024 16:14:58 -0300 Subject: [PATCH 032/104] [api][desktop]: Implement PixInsight Stacker --- .../nebulosa/api/stacker/AnalyzedTarget.kt | 23 +++ .../nebulosa/api/stacker/StackerController.kt | 35 +++- .../nebulosa/api/stacker/StackerGroupType.kt | 17 +- .../nebulosa/api/stacker/StackerService.kt | 64 ++++++-- api/src/test/kotlin/StackerServiceTest.kt | 69 ++++++++ desktop/app/window.manager.ts | 10 +- desktop/src/app/home/home.component.html | 9 ++ desktop/src/app/home/home.component.ts | 3 + .../src/app/settings/settings.component.html | 46 ++++++ .../src/app/settings/settings.component.ts | 10 ++ .../src/app/stacker/stacker.component.html | 119 ++++++++++++++ desktop/src/app/stacker/stacker.component.ts | 149 +++++++++++++++++- .../src/shared/pipes/dropdown-options.pipe.ts | 5 +- desktop/src/shared/services/api.service.ts | 18 ++- .../shared/services/browser-window.service.ts | 2 +- .../src/shared/services/electron.service.ts | 35 ++-- .../src/shared/services/preference.service.ts | 6 + desktop/src/shared/types/app.types.ts | 1 + desktop/src/shared/types/home.types.ts | 2 +- desktop/src/shared/types/image.types.ts | 2 +- desktop/src/shared/types/stacker.types.ts | 33 ++++ .../concurrency/cancel/CancellationToken.kt | 10 ++ .../script/AbstractPixInsightScript.kt | 4 +- .../script/PixInsightFileFormatConversion.kt | 65 ++++++++ .../stacker/PixInsightAutoStacker.kt | 50 +++++- .../pixinsight/stacker/PixInsightStacker.kt | 5 + .../pixinsight/FileFormatConversion.js | 46 ++++++ .../src/test/kotlin/PixInsightScriptTest.kt | 45 +++--- .../kotlin/nebulosa/stacker/AutoStacker.kt | 2 + .../main/kotlin/nebulosa/stacker/Stacker.kt | 2 + 30 files changed, 818 insertions(+), 69 deletions(-) create mode 100644 api/src/main/kotlin/nebulosa/api/stacker/AnalyzedTarget.kt create mode 100644 api/src/test/kotlin/StackerServiceTest.kt create mode 100644 nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt create mode 100644 nebulosa-pixinsight/src/main/resources/pixinsight/FileFormatConversion.js diff --git a/api/src/main/kotlin/nebulosa/api/stacker/AnalyzedTarget.kt b/api/src/main/kotlin/nebulosa/api/stacker/AnalyzedTarget.kt new file mode 100644 index 000000000..892ff518b --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/stacker/AnalyzedTarget.kt @@ -0,0 +1,23 @@ +package nebulosa.api.stacker + +import nebulosa.fits.* +import nebulosa.image.format.ReadableHeader +import nebulosa.indi.device.camera.FrameType +import nebulosa.indi.device.camera.FrameType.Companion.frameType + +data class AnalyzedTarget( + @JvmField val width: Int, + @JvmField val height: Int, + @JvmField val binX: Int, + @JvmField val binY: Int, + @JvmField val gain: Double, + @JvmField val exposureTime: Long, + @JvmField val type: FrameType, + @JvmField val group: StackerGroupType, +) { + + constructor(header: ReadableHeader) : this( + header.width, header.height, header.binX, header.binY, header.gain, header.exposureTimeInMicroseconds, + header.frameType ?: FrameType.LIGHT, StackerGroupType.from(header) + ) +} diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackerController.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackerController.kt index 382b5aa3a..66a95ff33 100644 --- a/api/src/main/kotlin/nebulosa/api/stacker/StackerController.kt +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackerController.kt @@ -1,21 +1,46 @@ package nebulosa.api.stacker import jakarta.validation.Valid +import nebulosa.common.concurrency.cancel.CancellationToken import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.* import java.nio.file.Path +import java.util.concurrent.atomic.AtomicReference @Validated @RestController @RequestMapping("stacker") -class StackerController(private val stackerService: StackerService) { +class StackerController( + private val stackerService: StackerService, +) { - @PutMapping - fun stack(@RequestBody @Valid body: StackingRequest): Path? { - return stackerService.stack(body) + private val cancellationToken = AtomicReference() + + @PutMapping("start") + fun start(@RequestBody @Valid body: StackingRequest): Path? { + return if (cancellationToken.compareAndSet(null, CancellationToken())) { + try { + stackerService.stack(body, cancellationToken.get()) + } finally { + cancellationToken.getAndSet(null)?.unlistenAll() + } + } else { + null + } + } + + @GetMapping("running") + fun isRunning(): Boolean { + return cancellationToken.get() != null + } + + @PutMapping("stop") + fun stop() { + cancellationToken.get()?.cancel() } @PutMapping("analyze") - fun analyze(@RequestParam path: Path) { + fun analyze(@RequestParam path: Path): AnalyzedTarget? { + return stackerService.analyze(path) } } diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackerGroupType.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackerGroupType.kt index 067f1430c..641984102 100644 --- a/api/src/main/kotlin/nebulosa/api/stacker/StackerGroupType.kt +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackerGroupType.kt @@ -1,10 +1,25 @@ package nebulosa.api.stacker +import nebulosa.fits.filter +import nebulosa.image.format.ReadableHeader + enum class StackerGroupType { LUMINANCE, RED, GREEN, BLUE, MONO, - RGB, + RGB; + + companion object { + + @JvmStatic + fun from(header: ReadableHeader) = header.filter?.let { + if (it.contains("RED", true) || it.equals("R", true)) RED + else if (it.contains("GREEN", true) || it.equals("G", true)) GREEN + else if (it.contains("BLUE", true) || it.equals("B", true)) BLUE + else if (it.contains("LUMINANCE", true) || it.equals("L", true)) LUMINANCE + else MONO + } ?: MONO + } } diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt index 32b277406..36ee93bd1 100644 --- a/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt @@ -1,13 +1,22 @@ package nebulosa.api.stacker +import nebulosa.common.concurrency.cancel.CancellationToken +import nebulosa.fits.fits +import nebulosa.fits.isFits import nebulosa.stacker.AutoStacker +import nebulosa.xisf.isXisf +import nebulosa.xisf.xisf import org.springframework.stereotype.Service import java.nio.file.Path +import kotlin.io.path.exists +import kotlin.io.path.isDirectory @Service class StackerService { - fun stack(request: StackingRequest): Path? { + fun stack(request: StackingRequest, cancellationToken: CancellationToken = CancellationToken.NONE): Path? { + require(request.outputDirectory != null && request.outputDirectory.exists() && request.outputDirectory.isDirectory()) + val luminance = request.targets.filter { it.enabled && it.group == StackerGroupType.LUMINANCE } val red = request.targets.filter { it.enabled && it.group == StackerGroupType.RED } val green = request.targets.filter { it.enabled && it.group == StackerGroupType.GREEN } @@ -21,23 +30,31 @@ class StackerService { return if (luminance.size + red.size + green.size + blue.size > 1) { val stacker = request.get() - val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE) - val stackedRedPath = red.stack(request, stacker, name, StackerGroupType.RED) - val stackedGreenPath = green.stack(request, stacker, name, StackerGroupType.GREEN) - val stackedBluePath = blue.stack(request, stacker, name, StackerGroupType.BLUE) + cancellationToken.listen { stacker.stop() } + + val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE, cancellationToken) + val stackedRedPath = red.stack(request, stacker, name, StackerGroupType.RED, cancellationToken) + val stackedGreenPath = green.stack(request, stacker, name, StackerGroupType.GREEN, cancellationToken) + val stackedBluePath = blue.stack(request, stacker, name, StackerGroupType.BLUE, cancellationToken) - val combinedPath = Path.of("${request.outputDirectory}", "$name.LRGB.fits") - stacker.combineLRGB(combinedPath, stackedLuminancePath, stackedRedPath, stackedGreenPath, stackedBluePath) - combinedPath + if (cancellationToken.isCancelled) { + null + } else { + val combinedPath = Path.of("${request.outputDirectory}", "$name.LRGB.fits") + stacker.combineLRGB(combinedPath, stackedLuminancePath, stackedRedPath, stackedGreenPath, stackedBluePath) + combinedPath + } } // LRGB else if (rgb.size > 1 || luminance.size + rgb.size > 1) { val stacker = request.get() - val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE) - val stackedRGBPath = rgb.stack(request, stacker, name, StackerGroupType.RGB) + val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE, cancellationToken) + val stackedRGBPath = rgb.stack(request, stacker, name, StackerGroupType.RGB, cancellationToken) - if (stackedLuminancePath != null && stackedRGBPath != null) { + if (cancellationToken.isCancelled) { + null + } else if (stackedLuminancePath != null && stackedRGBPath != null) { val combinedPath = Path.of("${request.outputDirectory}", "$name.LRGB.fits") stacker.combineLuminance(combinedPath, stackedLuminancePath, stackedRGBPath, false) combinedPath @@ -49,10 +66,12 @@ class StackerService { else if (mono.size > 1 || luminance.size + mono.size > 1) { val stacker = request.get() - val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE) - val stackedMonoPath = mono.stack(request, stacker, name, StackerGroupType.MONO) + val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE, cancellationToken) + val stackedMonoPath = mono.stack(request, stacker, name, StackerGroupType.MONO, cancellationToken) - if (stackedLuminancePath != null && stackedMonoPath != null) { + if (cancellationToken.isCancelled) { + null + } else if (stackedLuminancePath != null && stackedMonoPath != null) { val combinedPath = Path.of("${request.outputDirectory}", "$name.LRGB.fits") stacker.combineLuminance(combinedPath, stackedLuminancePath, stackedMonoPath, true) combinedPath @@ -64,8 +83,13 @@ class StackerService { } } - private fun List.stack(request: StackingRequest, stacker: AutoStacker, name: String, group: StackerGroupType): Path? { - return if (size > 1) { + private fun List.stack( + request: StackingRequest, stacker: AutoStacker, + name: String, group: StackerGroupType, cancellationToken: CancellationToken, + ): Path? { + return if (cancellationToken.isCancelled) { + null + } else if (size > 1) { val outputPath = Path.of("${request.outputDirectory}", "$name.$group.fits") if (stacker.stack(map { it.path!! }, outputPath, request.referencePath!!)) outputPath else null } else if (isNotEmpty()) { @@ -75,4 +99,12 @@ class StackerService { null } } + + fun analyze(path: Path): AnalyzedTarget? { + val image = if (path.isFits()) path.fits() + else if (path.isXisf()) path.xisf() + else return null + + return image.use { it.firstOrNull()?.header }?.let(::AnalyzedTarget) + } } diff --git a/api/src/test/kotlin/StackerServiceTest.kt b/api/src/test/kotlin/StackerServiceTest.kt new file mode 100644 index 000000000..abfcbd3b5 --- /dev/null +++ b/api/src/test/kotlin/StackerServiceTest.kt @@ -0,0 +1,69 @@ +import io.kotest.core.annotation.EnabledIf +import io.kotest.matchers.ints.shouldBeExactly +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import nebulosa.api.stacker.* +import nebulosa.fits.fits +import nebulosa.image.Image +import nebulosa.image.algorithms.transformation.AutoScreenTransformFunction +import nebulosa.test.AbstractFitsAndXisfTest +import nebulosa.test.NonGitHubOnlyCondition +import java.nio.file.Path +import kotlin.io.path.createDirectories + +@EnabledIf(NonGitHubOnlyCondition::class) +class StackerServiceTest : AbstractFitsAndXisfTest() { + + init { + val service = StackerService() + + val paths = listOf( + Path.of("$BASE_DIR/20240513.213424625-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213436506-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213448253-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213500627-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213512554-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213524278-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213535967-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213547683-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213559416-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213611421-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213624939-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213636654-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213648389-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213701880-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213713546-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213725316-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213738803-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213750501-LIGHT.fits"), + Path.of("$BASE_DIR/20240513.213802188-LIGHT.fits"), + ) + + val darkPath = Path.of("/home/tiagohm/Imagens/Astrophotos/Dark/2024-06-08/ASI294_BIN4_G120_O80/10-DARK.fits") + + "stack LRGB" { + val targets = paths.map { + val analyzed = service.analyze(it)!! + StackingTarget(true, it, analyzed.group, true) + } + + targets.count { it.group == StackerGroupType.LUMINANCE } shouldBeExactly 10 + targets.count { it.group == StackerGroupType.RED } shouldBeExactly 3 + targets.count { it.group == StackerGroupType.GREEN } shouldBeExactly 3 + targets.count { it.group == StackerGroupType.BLUE } shouldBeExactly 3 + + val request = StackingRequest( + Path.of(BASE_DIR, "stacker").createDirectories(), StackerType.PIXINSIGHT, + Path.of("PixInsight"), darkPath, null, null, false, 1, paths[0], targets + ) + + val image = service.stack(request).shouldNotBeNull().fits().use(Image::open) + image.transform(AutoScreenTransformFunction).save("stacker-lrgb").second shouldBe "465a296bb4582ab2f938757347500eb8" + } + } + + companion object { + + const val BASE_DIR = "/home/tiagohm/Imagens/Astrophotos/Light/Algieba/2024-05-13" + } +} diff --git a/desktop/app/window.manager.ts b/desktop/app/window.manager.ts index 9d25ba4ca..965cf851c 100644 --- a/desktop/app/window.manager.ts +++ b/desktop/app/window.manager.ts @@ -288,13 +288,19 @@ export class WindowManager { const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) if (window) { + const properties: Electron.OpenDialogOptions['properties'] = ['openFile'] + + if (command.multiple) { + properties.push('multiSelections') + } + const ret = await dialog.showOpenDialog(window.browserWindow, { filters: command.filters, - properties: ['openFile'], + properties, defaultPath: command.defaultPath || undefined, }) - return !ret.canceled && ret.filePaths[0] + return !ret.canceled && (command.multiple ? ret.filePaths : ret.filePaths[0]) } else { return false } diff --git a/desktop/src/app/home/home.component.html b/desktop/src/app/home/home.component.html index 3d918cf3f..bbd3239fd 100644 --- a/desktop/src/app/home/home.component.html +++ b/desktop/src/app/home/home.component.html @@ -217,6 +217,15 @@
Auto Focus
+
+ + +
Stacker
+
+
+
+
+
+ + + + +
+
+ +
+
+ + + + +
+
+
diff --git a/desktop/src/app/settings/settings.component.ts b/desktop/src/app/settings/settings.component.ts index 3c5677e8d..79441a195 100644 --- a/desktop/src/app/settings/settings.component.ts +++ b/desktop/src/app/settings/settings.component.ts @@ -7,6 +7,7 @@ import { PrimeService } from '../../shared/services/prime.service' import { EMPTY_LOCATION, Location } from '../../shared/types/atlas.types' import { FrameType, LiveStackerType, LiveStackingRequest } from '../../shared/types/camera.types' import { DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, PlateSolverRequest, PlateSolverType, resetCameraCaptureNamingFormat, SettingsTabKey, StarDetectionRequest, StarDetectorType } from '../../shared/types/settings.types' +import { StackerType, StackingRequest } from '../../shared/types/stacker.types' import { AppComponent } from '../app.component' @Component({ @@ -29,6 +30,9 @@ export class SettingsComponent { liveStackerType: LiveStackerType = 'SIRIL' readonly liveStackers = new Map() + stackerType: StackerType = 'PIXINSIGHT' + readonly stackers = new Map() + readonly cameraCaptureNamingFormat = structuredClone(DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT) constructor( @@ -52,6 +56,9 @@ export class SettingsComponent { for (const type of dropdownOptions.transform('LIVE_STACKER')) { this.liveStackers.set(type, preference.liveStackingRequest(type).get()) } + for (const type of dropdownOptions.transform('STACKER')) { + this.stackers.set(type, preference.stackingRequest(type).get()) + } Object.assign(this.cameraCaptureNamingFormat, preference.cameraCaptureNamingFormatPreference.get(this.cameraCaptureNamingFormat)) } @@ -125,6 +132,9 @@ export class SettingsComponent { for (const type of this.dropdownOptions.transform('LIVE_STACKER')) { this.preference.liveStackingRequest(type).set(this.liveStackers.get(type)) } + for (const type of this.dropdownOptions.transform('STACKER')) { + this.preference.stackingRequest(type).set(this.stackers.get(type)) + } this.preference.cameraCaptureNamingFormatPreference.set(this.cameraCaptureNamingFormat) } diff --git a/desktop/src/app/stacker/stacker.component.html b/desktop/src/app/stacker/stacker.component.html index e69de29bb..e42e550a9 100644 --- a/desktop/src/app/stacker/stacker.component.html +++ b/desktop/src/app/stacker/stacker.component.html @@ -0,0 +1,119 @@ +
+
+ +
+
+ +
+
+ + + + +
+
+
+ {{ item.type }} + +
+ Debayer + +
+
+ Reference + +
+
+ Enabled + +
+
+ @if (item.analyzed) { +
+ EXP: {{ item.analyzed.exposureTime | exposureTime }} + WIDTH: {{ item.analyzed.width }} + HEIGHT: {{ item.analyzed.height }} + BIN: {{ item.analyzed.binX }}x{{ item.analyzed.binY }} + GAIN: {{ item.analyzed.gain }} +
+ } +
+ {{ item.path }} +
+
+
+ +
+
+
+
+
+
+
+
+ + +
+
diff --git a/desktop/src/app/stacker/stacker.component.ts b/desktop/src/app/stacker/stacker.component.ts index 3d2357a8c..c992a7df1 100644 --- a/desktop/src/app/stacker/stacker.component.ts +++ b/desktop/src/app/stacker/stacker.component.ts @@ -1,7 +1,152 @@ -import { Component } from '@angular/core' +import { AfterViewInit, Component } from '@angular/core' +import { dirname } from 'path' +import { ApiService } from '../../shared/services/api.service' +import { BrowserWindowService } from '../../shared/services/browser-window.service' +import { ElectronService } from '../../shared/services/electron.service' +import { PreferenceService } from '../../shared/services/preference.service' +import { StackerGroupType, StackingRequest, StackingTarget } from '../../shared/types/stacker.types' +import { AppComponent } from '../app.component' @Component({ selector: 'neb-stacker', templateUrl: './stacker.component.html', }) -export class StackerComponent {} +export class StackerComponent implements AfterViewInit { + running = false + readonly request: StackingRequest = { + outputDirectory: '', + type: 'PIXINSIGHT', + executablePath: '', + use32Bits: false, + slot: 0, + referencePath: '', + targets: [], + } + + get referenceTarget() { + return this.request.targets.find((e) => e.enabled && e.reference && e.type === 'LIGHT') + } + + get hasReference() { + return !!this.referenceTarget + } + + get canStart() { + return !!this.request.outputDirectory && this.hasReference + } + + constructor( + app: AppComponent, + private readonly electron: ElectronService, + private readonly api: ApiService, + private readonly preference: PreferenceService, + private readonly browserWindow: BrowserWindowService, + ) { + app.title = 'Stacker' + } + + async ngAfterViewInit() { + this.loadPreference() + + this.running = await this.api.stackerIsRunning() + } + + async openImages() { + try { + this.running = true + + const stackerPreference = this.preference.stackerPreference.get() + const images = await this.electron.openImages({ defaultPath: stackerPreference.defaultPath }) + + if (images && images.length) { + const targets: StackingTarget[] = [...this.request.targets] + + for (const path of images) { + const analyzed = await this.api.stackerAnalyze(path) + + if (analyzed) { + targets.push({ + enabled: true, + path, + analyzed, + type: analyzed.type, + group: analyzed.group, + reference: analyzed.type === 'LIGHT' && !targets.length && !this.referenceTarget, + debayer: analyzed.type === 'LIGHT' && analyzed.group === 'RGB', + }) + } + } + + this.request.targets = targets + + stackerPreference.defaultPath = dirname(images[0]) + this.preference.stackerPreference.set(stackerPreference) + } + } finally { + this.running = false + } + } + + targetGroupChanged(target: StackingTarget, group: StackerGroupType) { + if (group === 'RGB') { + target.debayer = true + } + } + + referenceChanged(target: StackingTarget, enabled: boolean) { + if (enabled) { + for (const item of this.request.targets) { + if (item.reference && item !== target) { + item.reference = false + } + } + } + } + + deleteTarget(target: StackingTarget) { + const index = this.request.targets.findIndex((e) => e === target) + + if (index >= 0) { + this.request.targets.splice(index, 1) + } + } + + async startStacking() { + const stackingRequest = this.preference.stackingRequest(this.request.type).get() + this.request.executablePath = stackingRequest.executablePath + this.request.slot = stackingRequest.slot || 1 + this.request.referencePath = this.referenceTarget!.path + + const request: StackingRequest = { + ...this.request, + targets: this.request.targets.filter((e) => e.enabled), + } + + try { + this.running = true + const path = await this.api.stackerStart(request) + + if (path) { + await this.browserWindow.openImage({ path, source: 'STACKER' }) + } + } finally { + this.running = false + } + } + + stopStacking() { + return this.api.stackerStop() + } + + private loadPreference() { + const stackerPreference = this.preference.stackerPreference.get() + + this.request.outputDirectory = stackerPreference.outputDirectory ?? '' + } + + savePreference() { + const stackerPreference = this.preference.stackerPreference.get() + stackerPreference.outputDirectory = this.request.outputDirectory + this.preference.stackerPreference.set(stackerPreference) + } +} diff --git a/desktop/src/shared/pipes/dropdown-options.pipe.ts b/desktop/src/shared/pipes/dropdown-options.pipe.ts index 213b5c4e7..cc5b4c34b 100644 --- a/desktop/src/shared/pipes/dropdown-options.pipe.ts +++ b/desktop/src/shared/pipes/dropdown-options.pipe.ts @@ -7,7 +7,7 @@ import { Bitpix, ImageChannel, ImageFormat, SCNRProtectionMethod } from '../type import { MountRemoteControlType } from '../types/mount.types' import { SequenceCaptureMode } from '../types/sequencer.types' import { PlateSolverType, SettingsTabKey, StarDetectorType } from '../types/settings.types' -import { StackerType } from '../types/stacker.types' +import { StackerGroupType, StackerType } from '../types/stacker.types' export interface DropdownOptions { STAR_DETECTOR: StarDetectorType[] @@ -31,6 +31,7 @@ export interface DropdownOptions { SEQUENCE_CAPTURE_MODE: SequenceCaptureMode[] STACKER: StackerType[] SETTINGS_TAB: SettingsTabKey[] + STACKER_GROUP_TYPE: StackerGroupType[] } @Pipe({ name: 'dropdownOptions' }) @@ -79,6 +80,8 @@ export class DropdownOptionsPipe implements PipeTransform { return ['PIXINSIGHT'] as DropdownOptions[K] case 'SETTINGS_TAB': return ['LOCATION', 'PLATE_SOLVER', 'STAR_DETECTOR', 'LIVE_STACKER', 'STACKER', 'CAPTURE_NAMING_FORMAT'] as DropdownOptions[K] + case 'STACKER_GROUP_TYPE': + return ['LUMINANCE', 'RED', 'GREEN', 'BLUE', 'MONO', 'RGB'] as DropdownOptions[K] } return [] diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts index 3763e9ddb..b7efe8e25 100644 --- a/desktop/src/shared/services/api.service.ts +++ b/desktop/src/shared/services/api.service.ts @@ -16,7 +16,7 @@ import { CelestialLocationType, Mount, MountRemoteControl, MountRemoteControlTyp import { Rotator } from '../types/rotator.types' import { SequencePlan } from '../types/sequencer.types' import { PlateSolverRequest, StarDetectionRequest } from '../types/settings.types' -import { StackingRequest } from '../types/stacker.types' +import { AnalyzedTarget, StackingRequest } from '../types/stacker.types' import { FilterWheel } from '../types/wheel.types' import { Undefinable } from '../utils/types' import { HttpService } from './http.service' @@ -683,8 +683,20 @@ export class ApiService { // STACKER - stacker(request: StackingRequest) { - return this.http.put('stacker', request) + stackerStart(request: StackingRequest) { + return this.http.put('stacker/start', request) + } + + stackerIsRunning() { + return this.http.get('stacker/running') + } + + stackerStop() { + return this.http.put('stacker/stop') + } + + stackerAnalyze(path: string) { + return this.http.put(`stacker/analyze?path=${path}`) } // CONFIRMATION diff --git a/desktop/src/shared/services/browser-window.service.ts b/desktop/src/shared/services/browser-window.service.ts index 201f8877a..9504f266d 100644 --- a/desktop/src/shared/services/browser-window.service.ts +++ b/desktop/src/shared/services/browser-window.service.ts @@ -144,7 +144,7 @@ export class BrowserWindowService { } openStacker(preference: WindowPreference = {}) { - Object.assign(preference, { icon: 'stack', width: 420, height: 400 }) + Object.assign(preference, { icon: 'stack', width: 370, height: 460 }) return this.openWindow({ preference, id: 'stacker', path: 'stacker' }) } diff --git a/desktop/src/shared/services/electron.service.ts b/desktop/src/shared/services/electron.service.ts index f54a7bf0b..06d1637e7 100644 --- a/desktop/src/shared/services/electron.service.ts +++ b/desktop/src/shared/services/electron.service.ts @@ -23,7 +23,12 @@ import { Mount } from '../types/mount.types' import { Rotator } from '../types/rotator.types' import { SequencerEvent } from '../types/sequencer.types' import { FilterWheel, WheelRenamed } from '../types/wheel.types' -import { Undefinable } from '../utils/types' + +export const IMAGE_FILE_FILTER: Electron.FileFilter[] = [ + { name: 'All', extensions: ['fits', 'fit', 'xisf'] }, + { name: 'FITS', extensions: ['fits', 'fit'] }, + { name: 'XISF', extensions: ['xisf'] }, +] interface EventMappedType { NOTIFICATION: NotificationEvent @@ -128,23 +133,31 @@ export class ElectronService { }) } - openFile(data?: OpenFile): Promise> { - return this.send('FILE.OPEN', { ...data, windowId: data?.windowId ?? window.id }) + openFile(data?: OpenFile): Promise { + return this.send('FILE.OPEN', { ...data, windowId: data?.windowId ?? window.id, multiple: false }) + } + + openFiles(data?: OpenFile): Promise { + return this.send('FILE.OPEN', { ...data, windowId: data?.windowId ?? window.id, multiple: true }) } - saveFile(data?: OpenFile): Promise> { + saveFile(data?: OpenFile): Promise { return this.send('FILE.SAVE', { ...data, windowId: data?.windowId ?? window.id }) } - openImage(data?: OpenFile): Promise> { + openImage(data?: OpenFile) { return this.openFile({ ...data, windowId: data?.windowId ?? window.id, - filters: [ - { name: 'All', extensions: ['fits', 'fit', 'xisf'] }, - { name: 'FITS', extensions: ['fits', 'fit'] }, - { name: 'XISF', extensions: ['xisf'] }, - ], + filters: IMAGE_FILE_FILTER, + }) + } + + openImages(data?: OpenFile) { + return this.openFiles({ + ...data, + windowId: data?.windowId ?? window.id, + filters: IMAGE_FILE_FILTER, }) } @@ -166,7 +179,7 @@ export class ElectronService { } async saveJson(data: SaveJson): Promise | false> { - data.path = data.path || (await this.saveFile({ ...data, windowId: data.windowId ?? window.id, filters: [{ name: 'JSON files', extensions: ['json'] }] })) + data.path = data.path || (await this.saveFile({ ...data, windowId: data.windowId ?? window.id, filters: [{ name: 'JSON files', extensions: ['json'] }] })) || undefined if (data.path) { if (await this.writeJson(data)) { diff --git a/desktop/src/shared/services/preference.service.ts b/desktop/src/shared/services/preference.service.ts index a346fb1a5..5d30d03a4 100644 --- a/desktop/src/shared/services/preference.service.ts +++ b/desktop/src/shared/services/preference.service.ts @@ -12,6 +12,7 @@ import { EMPTY_MOUNT_PREFERENCE, Mount, MountPreference } from '../types/mount.t import { Rotator, RotatorPreference } from '../types/rotator.types' import { EMPTY_SEQUENCER_PREFERENCE, SequencerPreference } from '../types/sequencer.types' import { CameraCaptureNamingFormat, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, EMPTY_PLATE_SOLVER_REQUEST, EMPTY_STAR_DETECTION_REQUEST, PlateSolverRequest, PlateSolverType, StarDetectionRequest, StarDetectorType } from '../types/settings.types' +import { EMPTY_STACKER_PREFERENCE, EMPTY_STACKING_REQUEST, StackerPreference, StackerType, StackingRequest } from '../types/stacker.types' import { FilterWheel, WheelPreference } from '../types/wheel.types' import { Undefinable } from '../utils/types' import { LocalStorageService } from './local-storage.service' @@ -84,6 +85,10 @@ export class PreferenceService { return new PreferenceData(this.storage, `liveStacking.${type}`, () => ({ ...EMPTY_LIVE_STACKING_REQUEST, type }) as LiveStackingRequest) } + stackingRequest(type: StackerType) { + return new PreferenceData(this.storage, `stacking.${type}`, () => ({ ...EMPTY_STACKING_REQUEST, type }) as StackingRequest) + } + equipmentForDevice(device: Device) { return new PreferenceData(this.storage, `equipment.${device.name}`, () => ({}) as Equipment) } @@ -112,4 +117,5 @@ export class PreferenceService { readonly autoFocusPreference = new PreferenceData(this.storage, 'autoFocus', () => structuredClone(EMPTY_AUTO_FOCUS_PREFERENCE)) readonly sequencerPreference = new PreferenceData(this.storage, 'sequencer', () => structuredClone(EMPTY_SEQUENCER_PREFERENCE)) readonly cameraCaptureNamingFormatPreference = new PreferenceData(this.storage, 'camera.namingFormat', () => structuredClone(DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT)) + readonly stackerPreference = new PreferenceData(this.storage, 'stacker', () => structuredClone(EMPTY_STACKER_PREFERENCE)) } diff --git a/desktop/src/shared/types/app.types.ts b/desktop/src/shared/types/app.types.ts index a819efe98..5c95403fe 100644 --- a/desktop/src/shared/types/app.types.ts +++ b/desktop/src/shared/types/app.types.ts @@ -80,6 +80,7 @@ export interface OpenDirectory extends WindowCommand { export interface OpenFile extends OpenDirectory { filters?: Electron.FileFilter[] + multiple?: boolean } export interface JsonFile { diff --git a/desktop/src/shared/types/home.types.ts b/desktop/src/shared/types/home.types.ts index 3af6d20fb..14a1c01f3 100644 --- a/desktop/src/shared/types/home.types.ts +++ b/desktop/src/shared/types/home.types.ts @@ -5,7 +5,7 @@ import type { Mount } from './mount.types' import type { Rotator } from './rotator.types' import type { FilterWheel } from './wheel.types' -export type HomeWindowType = DeviceType | 'GUIDER' | 'SKY_ATLAS' | 'ALIGNMENT' | 'SEQUENCER' | 'IMAGE' | 'FRAMING' | 'INDI' | 'SETTINGS' | 'CALCULATOR' | 'ABOUT' | 'FLAT_WIZARD' | 'AUTO_FOCUS' +export type HomeWindowType = DeviceType | 'GUIDER' | 'SKY_ATLAS' | 'ALIGNMENT' | 'SEQUENCER' | 'IMAGE' | 'FRAMING' | 'INDI' | 'SETTINGS' | 'CALCULATOR' | 'ABOUT' | 'FLAT_WIZARD' | 'AUTO_FOCUS' | 'STACKER' export const CONNECTION_TYPES = ['INDI', 'ALPACA'] as const diff --git a/desktop/src/shared/types/image.types.ts b/desktop/src/shared/types/image.types.ts index e9ca592d8..d1b4610d4 100644 --- a/desktop/src/shared/types/image.types.ts +++ b/desktop/src/shared/types/image.types.ts @@ -7,7 +7,7 @@ export type ImageChannel = 'RED' | 'GREEN' | 'BLUE' | 'GRAY' export type SCNRProtectionMethod = 'MAXIMUM_MASK' | 'ADDITIVE_MASK' | 'AVERAGE_NEUTRAL' | 'MAXIMUM_NEUTRAL' | 'MINIMUM_NEUTRAL' -export type ImageSource = 'FRAMING' | 'PATH' | 'CAMERA' | 'FLAT_WIZARD' | 'SEQUENCER' | 'ALIGNMENT' | 'AUTO_FOCUS' +export type ImageSource = 'FRAMING' | 'PATH' | 'CAMERA' | 'FLAT_WIZARD' | 'SEQUENCER' | 'ALIGNMENT' | 'AUTO_FOCUS' | 'STACKER' export type ImageFormat = 'FITS' | 'XISF' | 'PNG' | 'JPG' diff --git a/desktop/src/shared/types/stacker.types.ts b/desktop/src/shared/types/stacker.types.ts index 135f3f371..44d4f4683 100644 --- a/desktop/src/shared/types/stacker.types.ts +++ b/desktop/src/shared/types/stacker.types.ts @@ -1,3 +1,5 @@ +import type { FrameType } from './camera.types' + export type StackerType = 'PIXINSIGHT' export type StackerGroupType = 'LUMINANCE' | 'RED' | 'GREEN' | 'BLUE' | 'MONO' | 'RGB' @@ -15,9 +17,40 @@ export interface StackingRequest { targets: StackingTarget[] } +export const EMPTY_STACKING_REQUEST: StackingRequest = { + outputDirectory: '', + type: 'PIXINSIGHT', + executablePath: '', + use32Bits: false, + slot: 1, + referencePath: '', + targets: [], +} + export interface StackingTarget { enabled: boolean path: string + type: FrameType group: StackerGroupType debayer: boolean + reference: boolean + analyzed?: AnalyzedTarget } + +export interface AnalyzedTarget { + width: number + height: number + binX: number + binY: number + gain: number + exposureTime: number + type: FrameType + group: StackerGroupType +} + +export interface StackerPreference { + outputDirectory?: string + defaultPath?: string +} + +export const EMPTY_STACKER_PREFERENCE: StackerPreference = {} diff --git a/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/cancel/CancellationToken.kt b/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/cancel/CancellationToken.kt index 3ee538fb8..837a300e4 100644 --- a/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/cancel/CancellationToken.kt +++ b/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/cancel/CancellationToken.kt @@ -2,6 +2,7 @@ package nebulosa.common.concurrency.cancel import nebulosa.common.concurrency.latch.Pauser import java.io.Closeable +import java.util.concurrent.CancellationException import java.util.concurrent.CompletableFuture import java.util.concurrent.Future import java.util.concurrent.TimeUnit @@ -43,6 +44,11 @@ class CancellationToken private constructor(private val completable: Completable listeners.remove(listener) } + @Synchronized + fun unlistenAll() { + listeners.clear() + } + fun cancel() { cancel(true) } @@ -74,6 +80,10 @@ class CancellationToken private constructor(private val completable: Completable return completable?.get(timeout, unit) ?: CancellationSource.None } + fun throwIfCancelled() { + if (isCancelled) throw CancellationException() + } + override fun close() { super.close() diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt index 5a2f54ff2..f6e746c39 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt @@ -61,7 +61,9 @@ abstract class AbstractPixInsightScript : PixInsightScript, CommandLineLis } @JvmStatic - internal fun execute(slot: Int, scriptPath: Path, data: Any?): String { + internal fun PixInsightScript<*>.execute(slot: Int, scriptPath: Path, data: Any?): String { + LOG.info("{} will be executed. slot={}, script={}, data={}", this::class.simpleName, slot, scriptPath, data) + return buildString { if (slot > 0) append("$slot:") append("\"$scriptPath") diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt new file mode 100644 index 000000000..024b3aff4 --- /dev/null +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt @@ -0,0 +1,65 @@ +package nebulosa.pixinsight.script + +import nebulosa.io.resource +import nebulosa.io.transferAndClose +import java.nio.file.Files +import java.nio.file.Path +import kotlin.io.path.deleteIfExists +import kotlin.io.path.outputStream +import kotlin.io.path.readText + +data class PixInsightFileFormatConversion( + private val slot: Int, + private val inputPath: Path, + private val outputPath: Path, +) : AbstractPixInsightScript() { + + private data class Input( + @JvmField val inputPath: Path, + @JvmField val outputPath: Path, + @JvmField val statusPath: Path, + ) + + data class Output( + override val success: Boolean = false, + override val errorMessage: String? = null, + @JvmField val outputImage: Path? = null, + ) : PixInsightOutput { + + companion object { + + @JvmStatic val FAILED = Output() + } + } + + private val scriptPath = Files.createTempFile("pi-", ".js") + private val statusPath = Files.createTempFile("pi-", ".txt") + + init { + resource("pixinsight/FileFormatConversion.js")!!.transferAndClose(scriptPath.outputStream()) + } + + override val arguments = + listOf("-x=${execute(slot, scriptPath, Input(inputPath, outputPath, statusPath))}") + + override fun processOnComplete(exitCode: Int): Output { + if (exitCode == 0) { + repeat(30) { + val text = statusPath.readText() + + if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { + return OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), Output::class.java) + } + + Thread.sleep(1000) + } + } + + return Output.FAILED + } + + override fun close() { + scriptPath.deleteIfExists() + statusPath.deleteIfExists() + } +} diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt index ac5028c90..8637dca85 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightAutoStacker.kt @@ -1,10 +1,12 @@ package nebulosa.pixinsight.stacker +import nebulosa.common.concurrency.cancel.CancellationToken import nebulosa.pixinsight.script.PixInsightScript import nebulosa.pixinsight.script.PixInsightScriptRunner import nebulosa.stacker.AutoStacker import java.nio.file.Path -import kotlin.io.path.copyTo +import java.util.concurrent.CancellationException +import java.util.concurrent.atomic.AtomicReference import kotlin.io.path.deleteIfExists data class PixInsightAutoStacker( @@ -16,10 +18,12 @@ data class PixInsightAutoStacker( private val slot: Int = PixInsightScript.UNSPECIFIED_SLOT, ) : AutoStacker { + private val cancellationToken = AtomicReference() private val stacker = PixInsightStacker(runner, workingDirectory, slot) override fun stack(paths: Collection, outputPath: Path, referencePath: Path): Boolean { if (paths.isEmpty()) return false + if (!cancellationToken.compareAndSet(null, CancellationToken())) return false val calibratedPath = Path.of("$workingDirectory", "calibrated.xisf") val alignedPath = Path.of("$workingDirectory", "aligned.xisf") @@ -27,26 +31,52 @@ data class PixInsightAutoStacker( try { var stackCount = 0 - paths.forEach { + val realPaths = paths.map { it.toRealPath() } + val referenceRealPath = referencePath.toRealPath() + + realPaths.forEach { var targetPath = it - if (stacker.calibrate(targetPath, calibratedPath, darkPath, flatPath, biasPath)) { + cancellationToken.get().throwIfCancelled() + + if (calibrate(targetPath, calibratedPath, darkPath, flatPath, biasPath)) { targetPath = calibratedPath } + cancellationToken.get().throwIfCancelled() + if (stackCount > 0) { - if (stacker.align(referencePath, targetPath, alignedPath)) { - stacker.integrate(stackCount, outputPath, alignedPath, outputPath) + if (align(referenceRealPath, targetPath, alignedPath)) { + cancellationToken.get().throwIfCancelled() + integrate(stackCount, outputPath, alignedPath, outputPath) stackCount++ } } else { - targetPath.copyTo(outputPath, true) + if (referenceRealPath != it) { + if (align(referenceRealPath, targetPath, alignedPath)) { + cancellationToken.get().throwIfCancelled() + saveAs(alignedPath, outputPath) + cancellationToken.get().throwIfCancelled() + integrate(0, outputPath, alignedPath, outputPath) + } else { + saveAs(targetPath, outputPath) + } + } else { + saveAs(targetPath, outputPath) + } + stackCount = 1 } + + cancellationToken.get().throwIfCancelled() } + } catch (e: CancellationException) { + return false } finally { calibratedPath.deleteIfExists() alignedPath.deleteIfExists() + + cancellationToken.getAndSet(null) } return true @@ -71,4 +101,12 @@ data class PixInsightAutoStacker( override fun combineLuminance(outputPath: Path, luminancePath: Path, targetPath: Path, mono: Boolean): Boolean { return stacker.combineLuminance(outputPath, luminancePath, targetPath, mono) } + + override fun saveAs(inputPath: Path, outputPath: Path): Boolean { + return stacker.saveAs(inputPath, outputPath) + } + + override fun stop() { + cancellationToken.get()?.cancel() + } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt index 56909d1f6..91a85b51a 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt @@ -48,4 +48,9 @@ data class PixInsightStacker( .use { it.runSync(runner).outputImage != null } } } + + override fun saveAs(inputPath: Path, outputPath: Path): Boolean { + return PixInsightFileFormatConversion(slot, inputPath, outputPath) + .use { it.runSync(runner).outputImage != null } + } } diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/FileFormatConversion.js b/nebulosa-pixinsight/src/main/resources/pixinsight/FileFormatConversion.js new file mode 100644 index 000000000..060a1b4bd --- /dev/null +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/FileFormatConversion.js @@ -0,0 +1,46 @@ +function decodeParams(hex) { + const buffer = new Uint8Array(hex.length / 4) + + for (let i = 0; i < hex.length; i += 4) { + buffer[i / 4] = parseInt(hex.substr(i, 4), 16) + } + + return JSON.parse(String.fromCharCode.apply(null, buffer)) +} + +function fileFormatConversion() { + const data = { + success: true, + errorMessage: null, + outputImage: null, + } + + try { + const input = decodeParams(jsArguments[0]) + + const outputPath = input.outputPath + const statusPath = input.statusPath + const inputPath = input.inputPath + + console.writeln("Format conversion started") + console.writeln("outputPath=" + outputPath) + console.writeln("statusPath=" + statusPath) + console.writeln("inputPath=" + inputPath) + + const window = ImageWindow.open(inputPath)[0] + window.saveAs(outputPath, false, false, false, false) + window.forceClose() + + data.outputImage = outputPath + + console.writeln("Format conversion finished") + } catch (e) { + data.success = false + data.errorMessage = e.message + console.writeln(data.errorMessage) + } finally { + File.writeTextFile(statusPath, "@" + JSON.stringify(data) + "#") + } +} + +fileFormatConversion() diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt index 2e5f8f381..cf1ed2a92 100644 --- a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt @@ -34,89 +34,98 @@ class PixInsightScriptTest : AbstractFitsAndXisfTest() { } "calibrate" { PixInsightCalibrate(UNSPECIFIED_SLOT, workingDirectory, PI_01_LIGHT, PI_DARK, PI_FLAT, PI_BIAS) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-calibrate").second shouldBe "731562ee12f45bf7c1095f4773f70e71" } "align" { PixInsightAlign(UNSPECIFIED_SLOT, workingDirectory, PI_01_LIGHT, PI_02_LIGHT) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-align").second shouldBe "483ebaf15afa5957fe099f3ee2beff78" } "detect stars" { PixInsightDetectStars(UNSPECIFIED_SLOT, PI_FOCUS_0) - .use { it.runSync(runner).also(::println).stars } + .use { it.runSync(runner).stars } .map { it.hfd } .average() shouldBe (8.43 plusOrMinus 1e-2) PixInsightDetectStars(UNSPECIFIED_SLOT, PI_FOCUS_30000) - .use { it.runSync(runner).also(::println).stars } + .use { it.runSync(runner).stars } .map { it.hfd } .average() shouldBe (1.85 plusOrMinus 1e-2) PixInsightDetectStars(UNSPECIFIED_SLOT, PI_FOCUS_100000) - .use { it.runSync(runner).also(::println).stars } + .use { it.runSync(runner).stars } .map { it.hfd } .average() shouldBe (18.35 plusOrMinus 1e-2) } "pixel math" { val outputPath = tempfile("pi-stacked-", ".fits").toPath() PixInsightPixelMath(UNSPECIFIED_SLOT, listOf(PI_01_LIGHT, PI_02_LIGHT), outputPath, "{{0}} + {{1}}") - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-pixelmath").second shouldBe "cafc8138e2ce17614dcfa10edf410b07" } "abe" { val outputPath = tempfile("pi-abe-", ".fits").toPath() PixInsightAutomaticBackgroundExtractor(UNSPECIFIED_SLOT, PI_01_LIGHT, outputPath) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-abe").second shouldBe "bf62207dc17190009ba215da7c011297" } "lrgb combination" { val outputPath = tempfile("pi-lrgb-", ".fits").toPath() PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-lrgb").second shouldBe "99db35d78f7b360e7592217f4179b189" val weights = doubleArrayOf(1.0, 0.2470588, 0.31764705, 0.709803921) // LRGB #3F51B5 PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT, weights) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-weighted-lrgb").second shouldBe "1148ee222fbfb382ad2d708df5b0f79f" PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, null, null) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-lr").second shouldBe "9100d3ce892f05f4b832b2fb5f35b5a1" PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, null, PI_01_LIGHT, null) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-lg").second shouldBe "b4e8d8f7e289db60b41ba2bbe0035344" PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, null, null, PI_01_LIGHT) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-lb").second shouldBe "1760e7cb1d139b63022dd975fe84897d" PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, null, PI_01_LIGHT, PI_01_LIGHT, null) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-rg").second shouldBe "8c59307b5943932aefdf2dedfe1c8178" PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, null, PI_01_LIGHT, null, PI_01_LIGHT) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-rb").second shouldBe "1bdf9cada6a33f76dceaccdaacf30fef" PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, null, null, PI_01_LIGHT, PI_01_LIGHT) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-bg").second shouldBe "4a9c81c71fd37546fd300d1037742fa2" PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, PI_01_LIGHT, null) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-lrg").second shouldBe "06c32c8679d409302423baa3a07fb241" PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, PI_01_LIGHT, null, PI_01_LIGHT) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-lrb").second shouldBe "f6d026cb63f7a58fc325e422c277ff89" PixInsightLRGBCombination(UNSPECIFIED_SLOT, outputPath, PI_01_LIGHT, null, PI_01_LIGHT, PI_01_LIGHT) - .use { it.runSync(runner).also(::println).outputImage.shouldNotBeNull().openAsImage() } + .use { it.runSync(runner).outputImage.shouldNotBeNull().openAsImage() } .transform(AutoScreenTransformFunction).save("pi-lbg").second shouldBe "67f961110fb4b9f0033b3b8dbc8b1638" } + "file format conversion" { + val xisfPath = tempfile("pi-ffc", ".xisf").toPath() + PixInsightFileFormatConversion(UNSPECIFIED_SLOT, PI_01_LIGHT, xisfPath) + .use { it.runSync(runner).outputImage.shouldNotBeNull().isXisf().shouldBeTrue() } + + val fitsPath = tempfile("pi-ffc", ".fits").toPath() + PixInsightFileFormatConversion(UNSPECIFIED_SLOT, xisfPath, fitsPath) + .use { it.runSync(runner).outputImage.shouldNotBeNull().isFits().shouldBeTrue() } + } } companion object { diff --git a/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt index 845c0d96e..d13fa3fc5 100644 --- a/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt +++ b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/AutoStacker.kt @@ -5,4 +5,6 @@ import java.nio.file.Path interface AutoStacker : Stacker { fun stack(paths: Collection, outputPath: Path, referencePath: Path = paths.first()): Boolean + + fun stop() } diff --git a/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt index 76a74fcef..31cf7f719 100644 --- a/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt +++ b/nebulosa-stacker/src/main/kotlin/nebulosa/stacker/Stacker.kt @@ -16,4 +16,6 @@ interface Stacker { fun combineLRGB(outputPath: Path, luminancePath: Path? = null, redPath: Path? = null, greenPath: Path? = null, bluePath: Path? = null): Boolean fun combineLuminance(outputPath: Path, luminancePath: Path, targetPath: Path, mono: Boolean): Boolean + + fun saveAs(inputPath: Path, outputPath: Path): Boolean } From 5e0ae0dc19559b92dbfdc52c6e9fcdb57d9e18c2 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 13 Jul 2024 17:06:42 -0300 Subject: [PATCH 033/104] [api][desktop]: Implement PixInsight Stacker --- .../nebulosa/api/stacker/StackerService.kt | 3 + .../nebulosa/api/stacker/StackingRequest.kt | 9 +++ desktop/README.md | 4 + desktop/src/app/camera/camera.component.html | 6 +- .../src/app/stacker/stacker.component.html | 75 +++++++++++++++--- desktop/src/app/stacker/stacker.component.ts | 39 ++++----- desktop/src/shared/types/stacker.types.ts | 20 ++++- desktop/stacker.png | Bin 0 -> 44140 bytes 8 files changed, 122 insertions(+), 34 deletions(-) create mode 100644 desktop/stacker.png diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt index 36ee93bd1..f56ababd2 100644 --- a/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt @@ -10,6 +10,7 @@ import org.springframework.stereotype.Service import java.nio.file.Path import kotlin.io.path.exists import kotlin.io.path.isDirectory +import kotlin.io.path.isRegularFile @Service class StackerService { @@ -101,6 +102,8 @@ class StackerService { } fun analyze(path: Path): AnalyzedTarget? { + if (!path.exists() || !path.isRegularFile()) return null + val image = if (path.isFits()) path.fits() else if (path.isXisf()) path.xisf() else return null diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackingRequest.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackingRequest.kt index 9afe5a710..66b00312a 100644 --- a/api/src/main/kotlin/nebulosa/api/stacker/StackingRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackingRequest.kt @@ -9,14 +9,19 @@ import nebulosa.stacker.AutoStacker import java.nio.file.Files import java.nio.file.Path import java.util.function.Supplier +import kotlin.io.path.exists +import kotlin.io.path.isRegularFile data class StackingRequest( @JvmField @field:NotNull val outputDirectory: Path? = null, @JvmField val type: StackerType = StackerType.PIXINSIGHT, @JvmField @field:NotNull val executablePath: Path? = null, @JvmField val darkPath: Path? = null, + @JvmField val darkEnabled: Boolean = false, @JvmField val flatPath: Path? = null, + @JvmField val flatEnabled: Boolean = false, @JvmField val biasPath: Path? = null, + @JvmField val biasEnabled: Boolean = false, @JvmField val use32Bits: Boolean = false, @JvmField val slot: Int = 1, @JvmField @field:NotNull val referencePath: Path? = null, @@ -26,6 +31,10 @@ data class StackingRequest( override fun get(): AutoStacker { val workingDirectory = Files.createTempDirectory("as-") + val darkPath = darkPath?.takeIf { darkEnabled && it.exists() && it.isRegularFile() } + val flatPath = flatPath?.takeIf { flatEnabled && it.exists() && it.isRegularFile() } + val biasPath = biasPath?.takeIf { biasEnabled && it.exists() && it.isRegularFile() } + return when (type) { StackerType.PIXINSIGHT -> { val runner = startPixInsight(executablePath!!, slot) diff --git a/desktop/README.md b/desktop/README.md index 2f0bae907..244054bc3 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -58,6 +58,10 @@ The complete integrated solution for all of your astronomical imaging needs. ![](sequencer.png) +## Stacker + +![](stacker.png) + ## INDI ![](indi.png) diff --git a/desktop/src/app/camera/camera.component.html b/desktop/src/app/camera/camera.component.html index 4eed5b90b..ae4338c98 100644 --- a/desktop/src/app/camera/camera.component.html +++ b/desktop/src/app/camera/camera.component.html @@ -608,7 +608,7 @@ [disabled]="!liveStacking.request.enabled" [directory]="false" label="Dark File" - key="LS_DARK_PATH" + key="LIVE_STACKER_DARK_PATH" [(path)]="liveStacking.request.darkPath" class="w-full" (pathChange)="savePreference()" /> @@ -618,7 +618,7 @@ [disabled]="!liveStacking.request.enabled" [directory]="false" label="Flat File" - key="LS_FLAT_PATH" + key="LIVE_STACKER_FLAT_PATH" [(path)]="liveStacking.request.flatPath" class="w-full" (pathChange)="savePreference()" /> @@ -628,7 +628,7 @@ [disabled]="!liveStacking.request.enabled || liveStacking.request.type !== 'PIXINSIGHT'" [directory]="false" label="Bias File" - key="LS_BIAS_PATH" + key="LIVE_STACKER_BIAS_PATH" [(path)]="liveStacking.request.biasPath" class="w-full" (pathChange)="savePreference()" /> diff --git a/desktop/src/app/stacker/stacker.component.html b/desktop/src/app/stacker/stacker.component.html index e42e550a9..086859656 100644 --- a/desktop/src/app/stacker/stacker.component.html +++ b/desktop/src/app/stacker/stacker.component.html @@ -1,7 +1,7 @@
+ leftIcon="mdi mdi-file-multiple"> -
- Debayer - -
Reference + +
+ + +
+
+ + +
+
+ + +
+
+ +
+ + + + +
+
diff --git a/desktop/src/app/stacker/stacker.component.ts b/desktop/src/app/stacker/stacker.component.ts index c992a7df1..4692a91f0 100644 --- a/desktop/src/app/stacker/stacker.component.ts +++ b/desktop/src/app/stacker/stacker.component.ts @@ -4,7 +4,7 @@ import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' -import { StackerGroupType, StackingRequest, StackingTarget } from '../../shared/types/stacker.types' +import { EMPTY_STACKING_REQUEST, StackingRequest, StackingTarget } from '../../shared/types/stacker.types' import { AppComponent } from '../app.component' @Component({ @@ -13,15 +13,7 @@ import { AppComponent } from '../app.component' }) export class StackerComponent implements AfterViewInit { running = false - readonly request: StackingRequest = { - outputDirectory: '', - type: 'PIXINSIGHT', - executablePath: '', - use32Bits: false, - slot: 0, - referencePath: '', - targets: [], - } + readonly request = structuredClone(EMPTY_STACKING_REQUEST) get referenceTarget() { return this.request.targets.find((e) => e.enabled && e.reference && e.type === 'LIGHT') @@ -64,15 +56,14 @@ export class StackerComponent implements AfterViewInit { for (const path of images) { const analyzed = await this.api.stackerAnalyze(path) - if (analyzed) { + if (analyzed && analyzed.type === 'LIGHT') { targets.push({ enabled: true, path, analyzed, type: analyzed.type, group: analyzed.group, - reference: analyzed.type === 'LIGHT' && !targets.length && !this.referenceTarget, - debayer: analyzed.type === 'LIGHT' && analyzed.group === 'RGB', + reference: !targets.length && !this.referenceTarget, }) } } @@ -87,12 +78,6 @@ export class StackerComponent implements AfterViewInit { } } - targetGroupChanged(target: StackingTarget, group: StackerGroupType) { - if (group === 'RGB') { - target.debayer = true - } - } - referenceChanged(target: StackingTarget, enabled: boolean) { if (enabled) { for (const item of this.request.targets) { @@ -122,6 +107,8 @@ export class StackerComponent implements AfterViewInit { targets: this.request.targets.filter((e) => e.enabled), } + this.savePreference() + try { this.running = true const path = await this.api.stackerStart(request) @@ -142,11 +129,25 @@ export class StackerComponent implements AfterViewInit { const stackerPreference = this.preference.stackerPreference.get() this.request.outputDirectory = stackerPreference.outputDirectory ?? '' + this.request.darkPath = stackerPreference.darkPath + this.request.darkEnabled = stackerPreference.darkEnabled ?? false + this.request.flatPath = stackerPreference.flatPath + this.request.flatEnabled = stackerPreference.flatEnabled ?? false + this.request.biasPath = stackerPreference.biasPath + this.request.biasEnabled = stackerPreference.biasEnabled ?? false + this.request.type = stackerPreference.type ?? 'PIXINSIGHT' } savePreference() { const stackerPreference = this.preference.stackerPreference.get() stackerPreference.outputDirectory = this.request.outputDirectory + stackerPreference.darkPath = this.request.darkPath + stackerPreference.darkEnabled = this.request.darkEnabled + stackerPreference.flatPath = this.request.flatPath + stackerPreference.flatEnabled = this.request.flatEnabled + stackerPreference.biasPath = this.request.biasPath + stackerPreference.biasEnabled = this.request.biasEnabled + stackerPreference.type = this.request.type this.preference.stackerPreference.set(stackerPreference) } } diff --git a/desktop/src/shared/types/stacker.types.ts b/desktop/src/shared/types/stacker.types.ts index 44d4f4683..f2971eeff 100644 --- a/desktop/src/shared/types/stacker.types.ts +++ b/desktop/src/shared/types/stacker.types.ts @@ -9,8 +9,11 @@ export interface StackingRequest { type: StackerType executablePath: string darkPath?: string + darkEnabled: boolean flatPath?: string + flatEnabled: boolean biasPath?: string + biasEnabled: boolean use32Bits: boolean slot: number referencePath: string @@ -25,6 +28,9 @@ export const EMPTY_STACKING_REQUEST: StackingRequest = { slot: 1, referencePath: '', targets: [], + darkEnabled: false, + flatEnabled: false, + biasEnabled: false, } export interface StackingTarget { @@ -32,7 +38,6 @@ export interface StackingTarget { path: string type: FrameType group: StackerGroupType - debayer: boolean reference: boolean analyzed?: AnalyzedTarget } @@ -49,8 +54,19 @@ export interface AnalyzedTarget { } export interface StackerPreference { + type?: StackerType outputDirectory?: string defaultPath?: string + darkPath?: string + darkEnabled?: boolean + flatPath?: string + flatEnabled?: boolean + biasPath?: string + biasEnabled?: boolean } -export const EMPTY_STACKER_PREFERENCE: StackerPreference = {} +export const EMPTY_STACKER_PREFERENCE: StackerPreference = { + darkEnabled: false, + flatEnabled: false, + biasEnabled: false, +} diff --git a/desktop/stacker.png b/desktop/stacker.png new file mode 100644 index 0000000000000000000000000000000000000000..f7dabfdd505232d3871b26c38e4836fbe62568f6 GIT binary patch literal 44140 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�rIWLc(LY);tIe}T@A2Rf5b3S~EWFmGksUXP579NeqRzc|`rxpQjG zIww+WSMjTBYeM|}yLhM@^}os_%offc8$Tae5z5XdP_@J(ASCLv|IVEW=r(?IZ35&Z zpnef(ATsC36z46LFRHjIyScbXCl~D7mt<>suBpk%cFvXD>3{gmP7EbF4*dt4h-Bsa z&z~n{jCRDb%kJh^J$KHWwVO7f5xQu80hUv88f&SBhF9@X07C`qmiiM;5t9O|m#V6s zy>Ow6f>NN^sRMkRM34;Fin+Gj&{L{$7pntgt!f%_&hJD3DU_b5s3GF}qp?B#24o3c zn2r7mC1kDUPr<3UFI&-ZYW6woy`iWi8-NVWSQkny`Q(d<Egk3wgNiF2pORzeR0^US?2U-&*phgH z3Ait*`U+f0()xGmWlm=1eQp9GRFrg=&YLpDo%uloidoL3g1(&BAVmj+X~dYhoPItf z;maTVUHY=_sY+uFtH?k5_um?J!&x`t4;oR%t;)QK%y@}2`7KZL@1invkR+{cL{;PPr_-)=qy=j8hjEQjjN#C`XdMFkx1J* z(fQ1EN4;Ep1tZQq6CQi9!8wNtg|rVz?q*3K{x;#4_=afX#xp-xe^{X6PjB{tVWhm>Z!x$NA?Z#&(g?&u*tyh@k!E&5ze&d$%{e_W)g=X7WM`isQMH#%fnp*--pRX{+u!BTv^Qeo-tt z5f5QfaLTk=Nu+n!92lauGus3iB=_&h8__s$dc(au2aUSFU%0A3P+Nt#P?0bS_;I% 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 E0UDMe_y7O^ literal 0 HcmV?d00001 From 7ad094cc608962a048f15b3e52fa0bddfdb2e486 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 13 Jul 2024 17:44:32 -0300 Subject: [PATCH 034/104] [api]: Fix failed tests --- api/src/test/kotlin/SkyAtlasServiceTest.kt | 2 +- api/src/test/kotlin/StackerServiceTest.kt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/api/src/test/kotlin/SkyAtlasServiceTest.kt b/api/src/test/kotlin/SkyAtlasServiceTest.kt index 6a25036af..90ae1268f 100644 --- a/api/src/test/kotlin/SkyAtlasServiceTest.kt +++ b/api/src/test/kotlin/SkyAtlasServiceTest.kt @@ -143,7 +143,7 @@ class SkyAtlasServiceTest : StringSpec() { position.declinationJ2000.formatSignedDMS() shouldBe "-017ยฐ22'47.2\"" position.rightAscension.formatHMS() shouldBe "14h49m00.4s" position.declination.formatSignedDMS() shouldBe "-017ยฐ29'00.1\"" - position.azimuth.formatDMS() shouldBe "144ยฐ36'58.8\"" + position.azimuth.formatDMS() shouldBe "144ยฐ36'58.9\"" position.altitude.formatSignedDMS() shouldBe "-045ยฐ07'44.9\"" position.constellation shouldBe Constellation.LIB position.distance shouldBe (9633.950 plusOrMinus 1e-3) diff --git a/api/src/test/kotlin/StackerServiceTest.kt b/api/src/test/kotlin/StackerServiceTest.kt index abfcbd3b5..77a0f664d 100644 --- a/api/src/test/kotlin/StackerServiceTest.kt +++ b/api/src/test/kotlin/StackerServiceTest.kt @@ -54,7 +54,8 @@ class StackerServiceTest : AbstractFitsAndXisfTest() { val request = StackingRequest( Path.of(BASE_DIR, "stacker").createDirectories(), StackerType.PIXINSIGHT, - Path.of("PixInsight"), darkPath, null, null, false, 1, paths[0], targets + Path.of("PixInsight"), darkPath, true, null, false, null, false, false, + 1, paths[0], targets ) val image = service.stack(request).shouldNotBeNull().fits().use(Image::open) From df6b703c4e5e780323ca795f5017090df34c198c Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 13 Jul 2024 17:56:10 -0300 Subject: [PATCH 035/104] [api]: Bump Gradle from 8.8 to 8.9 --- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6f7a6eb33..dedd5d1e6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a426..b740cf133 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. From dd6222e9b70b57dde0985901aa28c672c8844658 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sun, 14 Jul 2024 13:03:19 -0300 Subject: [PATCH 036/104] [api]: Implement PixInsight Plate Solver --- nebulosa-pixinsight/build.gradle.kts | 1 + .../livestacker/PixInsightLiveStacker.kt | 4 +- .../platesolver/PixInsightPlateSolver.kt | 56 + .../script/AbstractPixInsightScript.kt | 23 +- .../pixinsight/script/PixInsightAlign.kt | 11 +- .../PixInsightAutomaticBackgroundExtractor.kt | 12 +- .../pixinsight/script/PixInsightCalibrate.kt | 15 +- .../script/PixInsightDetectStars.kt | 2 +- .../script/PixInsightFileFormatConversion.kt | 11 +- .../pixinsight/script/PixInsightHelper.kt | 4 +- .../script/PixInsightImageSolver.kt | 78 + .../pixinsight/script/PixInsightIsRunning.kt | 24 +- .../script/PixInsightLRGBCombination.kt | 15 +- .../script/PixInsightLuminanceCombination.kt | 15 +- .../pixinsight/script/PixInsightOutput.kt | 8 - .../pixinsight/script/PixInsightPixelMath.kt | 18 +- .../pixinsight/script/PixInsightScript.kt | 9 +- .../pixinsight/script/PixInsightStartup.kt | 20 +- .../src/main/resources/pixinsight/ABE.js | 2 +- .../src/main/resources/pixinsight/Align.js | 2 +- .../main/resources/pixinsight/Calibrate.js | 2 +- .../main/resources/pixinsight/DetectStars.js | 2 +- .../pixinsight/FileFormatConversion.js | 2 +- .../main/resources/pixinsight/ImageSolver.js | 1434 +++++++++++++++++ .../resources/pixinsight/LRGBCombination.js | 10 +- .../pixinsight/LuminanceCombination.js | 10 +- .../main/resources/pixinsight/PixelMath.js | 2 +- .../test/kotlin/PixInsightPlateSolverTest.kt | 37 + .../src/test/kotlin/PixInsightScriptTest.kt | 46 +- .../nebulosa/test/AbstractFitsAndXisfTest.kt | 220 +-- 30 files changed, 1870 insertions(+), 225 deletions(-) create mode 100644 nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt create mode 100644 nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt delete mode 100644 nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightOutput.kt create mode 100644 nebulosa-pixinsight/src/main/resources/pixinsight/ImageSolver.js create mode 100644 nebulosa-pixinsight/src/test/kotlin/PixInsightPlateSolverTest.kt diff --git a/nebulosa-pixinsight/build.gradle.kts b/nebulosa-pixinsight/build.gradle.kts index 73c3ed243..f22e2d728 100644 --- a/nebulosa-pixinsight/build.gradle.kts +++ b/nebulosa-pixinsight/build.gradle.kts @@ -6,6 +6,7 @@ plugins { dependencies { api(project(":nebulosa-common")) api(project(":nebulosa-math")) + api(project(":nebulosa-platesolver")) api(project(":nebulosa-stardetector")) api(project(":nebulosa-stacker")) api(project(":nebulosa-livestacker")) diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt index 9a4a12f56..2d010cdb2 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt @@ -42,9 +42,9 @@ data class PixInsightLiveStacker( @Synchronized override fun start() { if (!running.get()) { - if (!PixInsightIsRunning(slot).use { it.runSync(runner) }) { + if (!PixInsightIsRunning(slot).use { it.runSync(runner).success }) { try { - check(PixInsightStartup(slot).use { it.runSync(runner) }) + check(PixInsightStartup(slot).use { it.runSync(runner).success }) } catch (e: Throwable) { throw IllegalStateException("unable to start PixInsight") } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt new file mode 100644 index 000000000..22d73486f --- /dev/null +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt @@ -0,0 +1,56 @@ +package nebulosa.pixinsight.platesolver + +import nebulosa.common.concurrency.cancel.CancellationToken +import nebulosa.image.Image +import nebulosa.math.Angle +import nebulosa.math.toArcsec +import nebulosa.pixinsight.script.PixInsightImageSolver +import nebulosa.pixinsight.script.PixInsightScript +import nebulosa.pixinsight.script.PixInsightScriptRunner +import nebulosa.platesolver.PlateSolution +import nebulosa.platesolver.PlateSolver +import java.nio.file.Path +import java.time.Duration + +data class PixInsightPlateSolver( + private val runner: PixInsightScriptRunner, + private val pixelSize: Double, // ยตm + private val resolution: Angle = 0.0, + private val focalDistance: Double = 0.0, // mm + private val slot: Int = PixInsightScript.UNSPECIFIED_SLOT, +) : PlateSolver { + + init { + require(resolution > 0.0 || focalDistance > 0.0) { "resolution or focalDistance are required" } + } + + override fun solve( + path: Path?, image: Image?, + centerRA: Angle, centerDEC: Angle, radius: Angle, + downsampleFactor: Int, timeout: Duration, + cancellationToken: CancellationToken + ): PlateSolution { + require(path != null) { "path must be provided" } + val solver = PixInsightImageSolver(slot, path, centerRA, centerDEC, pixelSize, resolution.toArcsec, focalDistance) + .use { it.runSync(runner) } + + if (solver.success) { + val m = ROTATION_REGEX.find(solver.astrometricSolutionSummary, 0) + val rotation = m?.groupValues?.get(1)?.toDoubleOrNull() ?: 0.0 + + return PlateSolution( + true, rotation, solver.resolution, + solver.rightAscension, solver.declination, + solver.width, solver.height, widthInPixels = solver.imageWidth, + heightInPixels = solver.imageHeight, + ) + } + + return PlateSolution.NO_SOLUTION + } + + companion object { + + @JvmStatic val ROTATION_REGEX = Regex("Rotation\\s*\\.+\\s*([\\d.]+)") + } +} diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt index f6e746c39..5c0c22c04 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt @@ -1,5 +1,6 @@ package nebulosa.pixinsight.script +import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.module.kotlin.jsonMapper import com.fasterxml.jackson.module.kotlin.kotlinModule import nebulosa.common.exec.CommandLine @@ -10,8 +11,9 @@ import nebulosa.log.loggerFor import org.apache.commons.codec.binary.Hex import java.nio.file.Path import java.util.concurrent.CompletableFuture +import kotlin.io.path.readText -abstract class AbstractPixInsightScript : PixInsightScript, CommandLineListener, CompletableFuture() { +abstract class AbstractPixInsightScript : PixInsightScript, CommandLineListener, CompletableFuture() { override fun onLineRead(line: String) = Unit @@ -35,6 +37,9 @@ abstract class AbstractPixInsightScript : PixInsightScript, CommandLineLis if (isDone) return@whenComplete else if (exception != null) completeExceptionally(exception) else complete(processOnComplete(exitCode).also { LOG.info("{} script processed. output={}", this::class.simpleName, it) }) + } catch (e: Throwable) { + LOG.error("{} finished with fatal exception. message={}", this::class.simpleName, e.message) + completeExceptionally(e) } finally { commandLine.unregisterCommandLineListener(this) } @@ -58,6 +63,7 @@ abstract class AbstractPixInsightScript : PixInsightScript, CommandLineLis @JvmStatic internal val OBJECT_MAPPER = jsonMapper { addModule(KOTLIN_MODULE) + disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) } @JvmStatic @@ -81,5 +87,20 @@ abstract class AbstractPixInsightScript : PixInsightScript, CommandLineLis append('"') } } + + @JvmStatic + internal fun Path.parseStatus(type: Class): T? { + val text = readText() + + return if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { + OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), type) + } else { + null + } + } + + internal inline fun Path.parseStatus(): T? { + return parseStatus(T::class.java) + } } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt index 67e17fc19..64b39851c 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt @@ -6,7 +6,6 @@ import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream -import kotlin.io.path.readText data class PixInsightAlign( private val slot: Int, @@ -45,7 +44,7 @@ data class PixInsightAlign( @JvmField val h31: Double = 0.0, @JvmField val h32: Double = 0.0, @JvmField val h33: Double = 0.0, - ) : PixInsightOutput { + ) : PixInsightScript.Output { companion object { @@ -65,13 +64,7 @@ data class PixInsightAlign( override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { repeat(30) { - val text = statusPath.readText() - - if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { - return OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), Output::class.java) - } - - Thread.sleep(1000) + statusPath.parseStatus()?.also { return it } ?: Thread.sleep(1000) } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt index ddd3fd64d..3410e084f 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt @@ -2,11 +2,11 @@ package nebulosa.pixinsight.script import nebulosa.io.resource import nebulosa.io.transferAndClose +import nebulosa.pixinsight.script.PixInsightImageSolver.Output import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream -import kotlin.io.path.readText data class PixInsightAutomaticBackgroundExtractor( private val slot: Int, @@ -24,7 +24,7 @@ data class PixInsightAutomaticBackgroundExtractor( override val success: Boolean = false, override val errorMessage: String? = null, @JvmField val outputImage: Path? = null, - ) : PixInsightOutput { + ) : PixInsightScript.Output { companion object { @@ -44,13 +44,7 @@ data class PixInsightAutomaticBackgroundExtractor( override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { repeat(30) { - val text = statusPath.readText() - - if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { - return OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), Output::class.java) - } - - Thread.sleep(1000) + statusPath.parseStatus()?.also { return it } ?: Thread.sleep(1000) } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt index 9cb328be8..5d541d659 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt @@ -6,7 +6,6 @@ import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream -import kotlin.io.path.readText data class PixInsightCalibrate( private val slot: Int, @@ -34,7 +33,7 @@ data class PixInsightCalibrate( override val success: Boolean = false, override val errorMessage: String? = null, @JvmField val outputImage: Path? = null, - ) : PixInsightOutput { + ) : PixInsightScript.Output { companion object { @@ -49,19 +48,13 @@ data class PixInsightCalibrate( resource("pixinsight/Calibrate.js")!!.transferAndClose(scriptPath.outputStream()) } - override val arguments = - listOf("-x=${execute(slot, scriptPath, Input(targetPath, workingDirectory, statusPath, darkPath, flatPath, biasPath, compress, use32Bit))}") + private val input = Input(targetPath, workingDirectory, statusPath, darkPath, flatPath, biasPath, compress, use32Bit) + override val arguments = listOf("-x=${execute(slot, scriptPath, input)}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { repeat(30) { - val text = statusPath.readText() - - if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { - return OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), Output::class.java) - } - - Thread.sleep(1000) + statusPath.parseStatus()?.also { return it } ?: Thread.sleep(1000) } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt index 199de03a6..ce1d0472a 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt @@ -29,7 +29,7 @@ data class PixInsightDetectStars( override val success: Boolean = false, override val errorMessage: String? = null, @JvmField val stars: List = emptyList(), - ) : PixInsightOutput { + ) : PixInsightScript.Output { override fun toString() = "Output(success=$success, errorMessage=$errorMessage, stars=${stars.size})" diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt index 024b3aff4..e3c105397 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt @@ -6,7 +6,6 @@ import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream -import kotlin.io.path.readText data class PixInsightFileFormatConversion( private val slot: Int, @@ -24,7 +23,7 @@ data class PixInsightFileFormatConversion( override val success: Boolean = false, override val errorMessage: String? = null, @JvmField val outputImage: Path? = null, - ) : PixInsightOutput { + ) : PixInsightScript.Output { companion object { @@ -45,13 +44,7 @@ data class PixInsightFileFormatConversion( override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { repeat(30) { - val text = statusPath.readText() - - if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { - return OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), Output::class.java) - } - - Thread.sleep(1000) + statusPath.parseStatus()?.also { return it } ?: Thread.sleep(1000) } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt index 638bf19fe..3954d1bad 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt @@ -5,8 +5,8 @@ import java.nio.file.Path fun startPixInsight(executablePath: Path, slot: Int): PixInsightScriptRunner { val runner = PixInsightScriptRunner(executablePath) - if (!PixInsightIsRunning(slot).use { it.runSync(runner) }) { - if (!PixInsightStartup(slot).use { it.runSync(runner) }) { + if (!PixInsightIsRunning(slot).use { it.runSync(runner).success }) { + if (!PixInsightStartup(slot).use { it.runSync(runner).success }) { throw IllegalStateException("unable to start PixInsight") } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt new file mode 100644 index 000000000..e9c4cf311 --- /dev/null +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt @@ -0,0 +1,78 @@ +package nebulosa.pixinsight.script + +import nebulosa.io.resource +import nebulosa.io.transferAndClose +import nebulosa.math.Angle +import nebulosa.math.toDegrees +import java.nio.file.Files +import java.nio.file.Path +import kotlin.io.path.deleteIfExists +import kotlin.io.path.outputStream + +data class PixInsightImageSolver( + private val slot: Int, + private val targetPath: Path, + private val centerRA: Angle, + private val centerDEC: Angle, + private val pixelSize: Double = 0.0, // ยตm + private val resolution: Double = 0.0, // arcsec/px + private val focalDistance: Double = 0.0, // mm +) : AbstractPixInsightScript() { + + private data class Input( + @JvmField val targetPath: Path, + @JvmField val statusPath: Path, + @JvmField val centerRA: Double, // deg + @JvmField val centerDEC: Double, // deg + @JvmField val pixelSize: Double = 0.0, + @JvmField val resolution: Double = 0.0, + @JvmField val focalDistance: Double = 0.0, + ) + + data class Output( + override val success: Boolean = false, + override val errorMessage: String? = null, + @JvmField val rightAscension: Angle = 0.0, + @JvmField val declination: Angle = 0.0, + @JvmField val resolution: Angle = 0.0, + @JvmField val pixelSize: Double = 0.0, + @JvmField val focalDistance: Double = 0.0, + @JvmField val width: Angle = 0.0, + @JvmField val height: Angle = 0.0, + // @JvmField val rotation: Angle = 0.0, + @JvmField val imageWidth: Double = 0.0, + @JvmField val imageHeight: Double = 0.0, + @JvmField val astrometricSolutionSummary: String = "", + ) : PixInsightScript.Output { + + companion object { + + @JvmStatic val FAILED = Output() + } + } + + private val scriptPath = Files.createTempFile("pi-", ".js") + private val statusPath = Files.createTempFile("pi-", ".txt") + + init { + resource("pixinsight/ImageSolver.js")!!.transferAndClose(scriptPath.outputStream()) + } + + private val input = Input(targetPath, statusPath, centerRA.toDegrees, centerDEC.toDegrees, pixelSize, resolution, focalDistance) + override val arguments = listOf("-x=${execute(slot, scriptPath, input)}") + + override fun processOnComplete(exitCode: Int): Output { + if (exitCode == 0) { + repeat(30) { + statusPath.parseStatus()?.also { return it } ?: Thread.sleep(1000) + } + } + + return Output.FAILED + } + + override fun close() { + scriptPath.deleteIfExists() + statusPath.deleteIfExists() + } +} diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightIsRunning.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightIsRunning.kt index 4ec4b78ad..3f2ef4afc 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightIsRunning.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightIsRunning.kt @@ -3,7 +3,19 @@ package nebulosa.pixinsight.script import nebulosa.log.debug import nebulosa.log.loggerFor -data class PixInsightIsRunning(private val slot: Int) : AbstractPixInsightScript() { +data class PixInsightIsRunning(private val slot: Int) : AbstractPixInsightScript() { + + data class Output( + override val success: Boolean, + override val errorMessage: String? = null, + ) : PixInsightScript.Output { + + companion object { + + @JvmStatic val SUCCESS = Output(true) + @JvmStatic val FAILED = Output(false) + } + } override val arguments = listOf(if (slot > 0) "-y=$slot" else "-y") @@ -20,16 +32,16 @@ data class PixInsightIsRunning(private val slot: Int) : AbstractPixInsightScript if (slot > 0) { if (line.contains(slotIsNotRunning, true) || line.contains(slotCrashed, true)) { - complete(false) + complete(Output.FAILED) } else if (line.contains(yieldedExecutionInstance, true)) { - complete(true) + complete(Output.SUCCESS) } else { return } } else if (line.contains(YIELDED_EXECUTION_INSTANCE, true)) { - complete(true) + complete(Output.SUCCESS) } else if (line.contains(NO_RUNNING_PROCESS, true)) { - complete(false) + complete(Output.FAILED) } else { return } @@ -37,7 +49,7 @@ data class PixInsightIsRunning(private val slot: Int) : AbstractPixInsightScript LOG.debug { line } } - override fun processOnComplete(exitCode: Int) = false + override fun processOnComplete(exitCode: Int) = Output.FAILED override fun close() = Unit diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt index 9b92c1304..7d1384a87 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt @@ -6,7 +6,6 @@ import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream -import kotlin.io.path.readText @Suppress("ArrayInDataClass") data class PixInsightLRGBCombination( @@ -34,7 +33,7 @@ data class PixInsightLRGBCombination( override val success: Boolean = false, override val errorMessage: String? = null, @JvmField val outputImage: Path? = null, - ) : PixInsightOutput { + ) : PixInsightScript.Output { companion object { @@ -50,19 +49,13 @@ data class PixInsightLRGBCombination( resource("pixinsight/LRGBCombination.js")!!.transferAndClose(scriptPath.outputStream()) } - override val arguments = - listOf("-x=${execute(slot, scriptPath, Input(outputPath, statusPath, luminancePath, redPath, greenPath, bluePath, weights))}") + private val input = Input(outputPath, statusPath, luminancePath, redPath, greenPath, bluePath, weights) + override val arguments = listOf("-x=${execute(slot, scriptPath, input)}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { repeat(30) { - val text = statusPath.readText() - - if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { - return OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), Output::class.java) - } - - Thread.sleep(1000) + statusPath.parseStatus()?.also { return it } ?: Thread.sleep(1000) } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt index 74e2a3015..d300a6314 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt @@ -6,7 +6,6 @@ import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream -import kotlin.io.path.readText data class PixInsightLuminanceCombination( private val slot: Int, @@ -27,7 +26,7 @@ data class PixInsightLuminanceCombination( override val success: Boolean = false, override val errorMessage: String? = null, @JvmField val outputImage: Path? = null, - ) : PixInsightOutput { + ) : PixInsightScript.Output { companion object { @@ -42,19 +41,13 @@ data class PixInsightLuminanceCombination( resource("pixinsight/LuminanceCombination.js")!!.transferAndClose(scriptPath.outputStream()) } - override val arguments = - listOf("-x=${execute(slot, scriptPath, Input(outputPath, statusPath, luminancePath, targetPath, 1.0))}") + private val input = Input(outputPath, statusPath, luminancePath, targetPath, 1.0) + override val arguments = listOf("-x=${execute(slot, scriptPath, input)}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { repeat(30) { - val text = statusPath.readText() - - if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { - return OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), Output::class.java) - } - - Thread.sleep(1000) + statusPath.parseStatus()?.also { return it } ?: Thread.sleep(1000) } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightOutput.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightOutput.kt deleted file mode 100644 index c4d73143a..000000000 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightOutput.kt +++ /dev/null @@ -1,8 +0,0 @@ -package nebulosa.pixinsight.script - -sealed interface PixInsightOutput { - - val success: Boolean - - val errorMessage: String? -} diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt index 7c69ffb33..875957535 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt @@ -2,11 +2,11 @@ package nebulosa.pixinsight.script import nebulosa.io.resource import nebulosa.io.transferAndClose +import nebulosa.pixinsight.script.PixInsightImageSolver.Output import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream -import kotlin.io.path.readText data class PixInsightPixelMath( private val slot: Int, @@ -30,7 +30,7 @@ data class PixInsightPixelMath( override val success: Boolean = false, override val errorMessage: String? = null, @JvmField val outputImage: Path? = null, - ) : PixInsightOutput { + ) : PixInsightScript.Output { companion object { @@ -45,19 +45,13 @@ data class PixInsightPixelMath( resource("pixinsight/PixelMath.js")!!.transferAndClose(scriptPath.outputStream()) } - override val arguments = - listOf("-x=${execute(slot, scriptPath, Input(statusPath, inputPaths, outputPath, expressionRK, expressionG, expressionB))}") + private val input = Input(statusPath, inputPaths, outputPath, expressionRK, expressionG, expressionB) + override val arguments = listOf("-x=${execute(slot, scriptPath, input)}") - override fun processOnComplete(exitCode: Int): Output? { + override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { repeat(30) { - val text = statusPath.readText() - - if (text.startsWith(START_FILE) && text.endsWith(END_FILE)) { - return OBJECT_MAPPER.readValue(text.substring(1, text.length - 1), Output::class.java) - } - - Thread.sleep(1000) + statusPath.parseStatus()?.also { return it } ?: Thread.sleep(1000) } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScript.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScript.kt index 58a39d50e..2434b72da 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScript.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScript.kt @@ -4,7 +4,14 @@ import nebulosa.common.exec.CommandLine import java.io.Closeable import java.util.concurrent.Future -interface PixInsightScript : Future, Closeable { +sealed interface PixInsightScript : Future, Closeable { + + sealed interface Output { + + val success: Boolean + + val errorMessage: String? + } val arguments: Iterable diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightStartup.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightStartup.kt index e410a4ea9..41968725a 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightStartup.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightStartup.kt @@ -8,7 +8,19 @@ import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream import kotlin.io.path.readText -data class PixInsightStartup(private val slot: Int) : AbstractPixInsightScript() { +data class PixInsightStartup(private val slot: Int) : AbstractPixInsightScript() { + + data class Output( + override val success: Boolean, + override val errorMessage: String? = null, + ) : PixInsightScript.Output { + + companion object { + + @JvmStatic val SUCCESS = Output(true) + @JvmStatic val FAILED = Output(false) + } + } private val scriptPath = Files.createTempFile("pi-", ".js") private val outputPath = Files.createTempFile("pi-", ".txt") @@ -24,10 +36,10 @@ data class PixInsightStartup(private val slot: Int) : AbstractPixInsightScript= 60) { - complete(false) + complete(Output.FAILED) cancel() } @@ -35,7 +47,7 @@ data class PixInsightStartup(private val slot: Int) : AbstractPixInsightScript +#include +#include +#include +#include +#include + +#define SOLVERVERSION "6.2.7" +#define STAR_CSV_FILE (File.systemTempDirectory + format("/stars-%03d.csv", CoreApplication.instance)) +#define SETTINGS_MODULE "SOLVER" +#define SETTINGS_MODULE_SCRIPT "SOLVER" + +#include "/opt/PixInsight/src/scripts/AdP/WCSmetadata.jsh" +#include "/opt/PixInsight/src/scripts/AdP/AstronomicalCatalogs.jsh" +#include "/opt/PixInsight/src/scripts/AdP/CatalogDownloader.js" + +function CatalogMode() { } +CatalogMode.prototype.LocalText = 0 +CatalogMode.prototype.Online = 1 +CatalogMode.prototype.Automatic = 2 +CatalogMode.prototype.LocalXPSDServer = 3 + +function SolverConfiguration(module) { + this.__base__ = ObjectWithSettings + this.__base__( + module, + "solver", + new Array( + ["version", DataType_UCString], + ["magnitude", DataType_Float], + ["autoMagnitude", DataType_Boolean], + ["databasePath", DataType_UCString], + ["generateErrorImg", DataType_Boolean], + ["structureLayers", DataType_UInt8], + ["minStructureSize", DataType_UInt8], + ["hotPixelFilterRadius", DataType_UInt8], + ["noiseReductionFilterRadius", DataType_UInt8], + ["sensitivity", DataType_Double], + ["peakResponse", DataType_Double], + ["brightThreshold", DataType_Double], + ["maxStarDistortion", DataType_Double], + ["autoPSF", DataType_Boolean], + ["catalogMode", DataType_UInt8], + ["vizierServer", DataType_UCString], + ["showStars", DataType_Boolean], + ["showStarMatches", DataType_Boolean], + ["showSimplifiedSurfaces", DataType_Boolean], + ["showDistortion", DataType_Boolean], + ["generateDistortModel", DataType_Boolean], + ["catalog", DataType_UCString], + ["distortionCorrection", DataType_Boolean], + ["splineOrder", DataType_UInt8], + ["splineSmoothing", DataType_Float], + ["enableSimplifier", DataType_Boolean], + ["simplifierRejectFraction", DataType_Float], + ["outlierDetectionRadius", DataType_Int32], + ["outlierDetectionMinThreshold", DataType_Float], + ["outlierDetectionSigma", DataType_Float], + ["useDistortionModel", DataType_Boolean], + ["distortionModelPath", DataType_UCString], + ["useActive", DataType_Boolean], + ["outSuffix", DataType_UCString], + ["files", Ext_DataType_StringArray], + ["projection", DataType_UInt8], + ["projectionOriginMode", DataType_UInt8], + ["restrictToHQStars", DataType_Boolean], + ["tryApparentCoordinates", DataType_Boolean] + ) + ) + + this.version = SOLVERVERSION + this.useActive = true + this.files = [] + this.catalogMode = CatalogMode.prototype.Automatic + this.availableCatalogs = [ + new PPMXLCatalog(), + new TychoCatalog(), + new HR_Catalog(), + new GaiaDR2_Catalog() + ] + this.availableXPSDServers = [ + new GaiaDR3XPSDCatalog(), + new GaiaEDR3XPSDCatalog(), + new GaiaDR2XPSDCatalog() + ] + this.vizierServer = "https://vizier.cds.unistra.fr/" + this.magnitude = 12 + this.maxIterations = 100 + this.structureLayers = 5 + this.minStructureSize = 0 + this.hotPixelFilterRadius = 1 + this.noiseReductionFilterRadius = 0 + this.sensitivity = 0.5 + this.peakResponse = 0.5 + this.brightThreshold = 3.0 + this.maxStarDistortion = 0.6 + this.autoPSF = false + this.generateErrorImg = false + this.showStars = false + this.catalog = "PPMXL" + this.autoMagnitude = true + this.showStarMatches = false + this.showSimplifiedSurfaces = false + this.showDistortion = false + this.distortionCorrection = true + this.splineOrder = 2 + this.splineSmoothing = 0.005 + this.enableSimplifier = true + this.simplifierRejectFraction = 0.10 + this.outlierDetectionRadius = 160 + this.outlierDetectionMinThreshold = 4.0 + this.outlierDetectionSigma = 5.0 + this.generateDistortModel = false + this.useDistortionModel = false + this.distortionModelPath = null + this.outSuffix = "_ast" + this.projection = 0 + this.projectionOriginMode = 0 + this.restrictToHQStars = false + this.tryApparentCoordinates = true + + this.ResetSettings = function () { + Settings.remove(SETTINGS_MODULE) + } +} + +SolverConfiguration.prototype = new ObjectWithSettings + +function ImageSolver() { + this.config = new SolverConfiguration(SETTINGS_MODULE_SCRIPT) + this.metadata = new ImageMetadata(SETTINGS_MODULE_SCRIPT) + + this.config.catalogMode = 2 + this.config.vizierServer = "https://vizier.cds.unistra.fr/" + this.config.magnitude = 12 + this.config.maxIterations = 100 + this.config.structureLayers = 5 + this.config.minStructureSize = 0 + this.config.hotPixelFilterRadius = 1 + this.config.noiseReductionFilterRadius = 0 + this.config.sensitivity = 0.5 + this.config.peakResponse = 0.5 + this.config.brightThreshold = 3 + this.config.maxStarDistortion = 0.6 + this.config.autoPSF = false + this.config.generateErrorImg = false + this.config.showStars = false + this.config.catalog = "PPMXL" + this.config.autoMagnitude = true + this.config.showStarMatches = false + this.config.showSimplifiedSurfaces = false + this.config.showDistortion = false + this.config.distortionCorrection = true + this.config.splineOrder = 2 + this.config.splineSmoothing = 0.005 + this.config.enableSimplifier = true + this.config.simplifierRejectFraction = 0.10 + this.config.outlierDetectionRadius = 160 + this.config.outlierDetectionMinThreshold = 4 + this.config.outlierDetectionSigma = 5 + this.config.generateDistortModel = false + this.config.useDistortionModel = false + this.config.distortionModelPath = null + this.config.outSuffix = "_ast" + this.config.projection = 0 + this.config.projectionOriginMode = 0 + this.config.restrictToHQStars = false + this.config.tryApparentCoordinates = true + + /* + * Initializes the image solver. If the parameter prioritizeSettings is + * defined and is true, the solver will use the values stored in preferences + * instead of the values obtained from the image. + */ + this.Init = function (window, prioritizeSettings) { + if (prioritizeSettings) + if (window && window.isWindow) + this.metadata.ExtractMetadata(window) + + this.metadata.LoadSettings() + this.metadata.LoadParameters() + + if (!prioritizeSettings) + if (window && window.isWindow) + this.metadata.ExtractMetadata(window) + + this.metadata.ensureValidReferenceSystemForSolution() + } + + this.InitialAlignment = function (window) { + const SA = new StarAlignment + SA.referenceImage = STAR_CSV_FILE + SA.referenceIsFile = true + SA.mode = StarAlignment.prototype.OutputMatrix + SA.writeKeywords = false + SA.structureLayers = this.config.structureLayers + SA.minStructureSize = this.config.minStructureSize + SA.hotPixelFilterRadius = this.config.hotPixelFilterRadius + SA.noiseReductionFilterRadius = this.config.noiseReductionFilterRadius + SA.sensitivity = this.config.sensitivity + SA.peakResponse = this.config.peakResponse + SA.brightThreshold = this.config.brightThreshold + SA.maxStarDistortion = this.config.maxStarDistortion + SA.allowClusteredSources = true; // because we want it to match as many stars as possible at this stage + SA.ransacTolerance = 2 + SA.ransacMaxIterations = 5000 + SA.ransacMaximizeInliers = 1 + SA.ransacMaximizeOverlapping = 0 + SA.ransacMaximizeRegularity = 0 + SA.ransacMinimizeError = 0 + SA.useTriangles = false + SA.polygonSides = 7 + SA.descriptorsPerStar = 100 + SA.restrictToPreviews = false + + if (this.config.useDistortionModel) { + SA.distortionModel = this.config.distortionModelPath + SA.undistortedReference = true + } + + if (!SA.executeOn(window.currentView, false)) { + /* + * If we are using polygonal descriptors, try again using triangle + * similarity, just in case we have a mirrored image. + */ + console.noteln("
* Previous attempt with polygonal descriptors failed - trying with triangle similarity.") + SA.useTriangles = true + if (!SA.executeOn(window.currentView, false)) + return null + } + + let numPairs = Math.min(SA.outputData[0][2], 4000) + let pairs = { + pS: new Array(numPairs), + pI: new Array(numPairs) + } + + for (let i = 0; i < numPairs; ++i) { + pairs.pS[i] = new Point(SA.outputData[0][29][i], SA.outputData[0][30][i]) + pairs.pI[i] = new Point(SA.outputData[0][31][i] + 0.5, SA.outputData[0][32][i] + 0.5) + } + + return pairs + } + + this.GenerateTemplate = function (metadata, templateGeom) { + if (this.config.catalogMode == CatalogMode.prototype.LocalText) { + this.catalog = new CustomCatalog(this.config.databasePath) + } else { + this.catalog = __catalogRegister__.GetCatalog(this.catalogName) + this.catalog.magMax = this.limitMagnitude + this.catalog.restrictToHQStars = this.config.restrictToHQStars + } + + this.catalog.Load(metadata, this.config.vizierServer) + + if (this.catalog.objects == null) + throw "Catalog error: " + this.catalogName + + let ref_G_S = templateGeom.ref_S_G.inverse() + + let file = File.createFileForWriting(STAR_CSV_FILE) + file.outTextLn(templateGeom.width + "," + templateGeom.height) + let elements = this.catalog.objects + let numStars = 0 + let clipRectS = templateGeom.clipRectS || new Rect(0, 0, templateGeom.width, templateGeom.height) + + for (let i = 0; i < elements.length; ++i) + if (elements[i]) { + let flux = (elements[i].magnitude == null) ? 0 : Math.pow(2.512, -1.5 - elements[i].magnitude) + let pos_G = templateGeom.projection.Direct(elements[i].posRD) + + if (pos_G) { + let pos_S = ref_G_S.apply(pos_G) + + if (pos_S.x > clipRectS.left + && pos_S.x < clipRectS.right + && pos_S.y > clipRectS.top + && pos_S.y < clipRectS.bottom) { + file.outTextLn(format("%.4f,%.4f,%.3e", pos_S.x, pos_S.y, flux)) + numStars++ + } + } + } + + file.close() + + if (numStars < 8) + throw "Found too few stars. The magnitude filter could be too strict, or the catalog server could be malfunctioning." + } + + this.DoIterationSA = function (window, metadata) { + try { + /* + * Render a star field around the original coordinates. + */ + let templateSize = Math.max(metadata.width, metadata.height) + let templateGeom = { + ref_S_G: new Matrix(-metadata.resolution, 0, metadata.resolution * templateSize / 2, + 0, -metadata.resolution, metadata.resolution * templateSize / 2, + 0, 0, 1), + projection: ProjectionFactory(this.config, metadata.ra, metadata.dec), + width: templateSize, + height: templateSize, + clipRectS: null + } + + this.GenerateTemplate(metadata, templateGeom) + + /* + * Perform the initial image registration using a projective + * transformation. + */ + let pairs = this.InitialAlignment(window) + + if (pairs === null) { + /* + * Some image acquisition applications store apparent or 'of the + * date' coordinates in image metadata without providing the + * required metadata items to let us know. If the corresponding + * option is enabled, make a second attempt assuming that the + * center coordinates are apparent. + */ + if (this.config.tryApparentCoordinates) + if (metadata.mightBeApparent) { + console.noteln("
* Previous attempt failed - trying again assuming apparent coordinates.") + metadata.convertRADecFromApparentToAstrometric() + metadata.mightBeApparent = false + templateGeom.projection = ProjectionFactory(this.config, metadata.ra, metadata.dec) + this.GenerateTemplate(metadata, templateGeom) + pairs = this.InitialAlignment(window) + + if (pairs === null) { + if (!console.isAborted) { + console.criticalln("
*** Error: The image could not be aligned with the reference star field.") + console.writeln( + "" + + "

Please check the following items:

" + + "
    " + + "
  • The initial center coordinates should be inside the image.
  • " + + "
  • The initial image resolution should be within a factor of 2 from the correct value.
  • " + + "
  • If you use an online star catalog through the VizieR service, consider using " + + "the Gaia DR3 catalog with local XPSD databases instead.
  • " + + "
  • If the image has extreme noise levels, bad tracking, or is poorly focused, you may " + + "need to adjust some star detection parameters.
  • " + + "
" + + "") + } + throw "" + } + else { + console.warningln("
** Warning: The image provides apparent or 'of the date' coordinates in " + + "image metadata but does not include the appropriate Observation:CelestialReferenceSystem XISF property " + + "or RADESYS FITS keyword. We suggest you inform the authors of your image acquisition application about " + + "this error, which they should fix.") + } + } + } + + /* + * Adjust to a projection with the origin at the center of the image. + */ + let pG = pairs.pS.map(p => templateGeom.ref_S_G.apply(p)) + let ref_S_G = Math.homography(pairs.pI, pG) + let centerRD = templateGeom.projection.Inverse(ref_S_G.apply(new Point(metadata.width / 2, metadata.height / 2))) + let newProjection = ProjectionFactory(this.config, centerRD.x, centerRD.y) + pairs.pG = pG.map(p => newProjection.Direct(templateGeom.projection.Inverse(p))) + templateGeom.projection = newProjection + + /* + * Initialize a new metadata structure appropriate for the selected + * working mode. + */ + let newMetadata = metadata.Clone() + newMetadata.projection = templateGeom.projection + + if (this.config.distortionCorrection) { + // Using surface splines. + newMetadata.ref_I_G_linear = Math.homography(pairs.pI, pairs.pG) + + newMetadata.ref_I_G = new ReferSpline(pairs.pI, pairs.pG, + this.config.splineOrder, + this.config.splineSmoothing, + this.config.enableSimplifier, + this.config.simplifierRejectFraction) + processEvents() + + newMetadata.ref_G_I = new ReferSpline(pairs.pG, pairs.pI, + this.config.splineOrder, + this.config.splineSmoothing, + this.config.enableSimplifier, + this.config.simplifierRejectFraction) + processEvents() + + newMetadata.controlPoints = { + pI: pairs.pI, + pG: pairs.pG + } + } + else { + // Using a linear solution. + newMetadata.ref_I_G = Math.homography(pairs.pI, pairs.pG) + newMetadata.ref_I_G_linear = newMetadata.ref_I_G + newMetadata.ref_G_I = newMetadata.ref_I_G.inverse() + newMetadata.controlPoints = null + } + + /* + * Find the celestial coordinates (RD) of the center of the original + * image. First transform from I to G and then unproject the native + * projection coordinates (G) to celestial (RD). + */ + let centerI = new Point(metadata.width / 2, metadata.height / 2) + let centerG = newMetadata.ref_I_G.apply(centerI) + centerRD = newMetadata.projection.Inverse(centerG) + while (centerRD.x < 0) + centerRD.x += 360 + while (centerRD.x >= 360) + centerRD.x -= 360 + newMetadata.ra = centerRD.x + newMetadata.dec = centerRD.y + let ref = newMetadata.ref_I_G_linear + let resx = Math.sqrt(ref.at(0, 0) * ref.at(0, 0) + ref.at(0, 1) * ref.at(0, 1)) + let resy = Math.sqrt(ref.at(1, 0) * ref.at(1, 0) + ref.at(1, 1) * ref.at(1, 1)) + newMetadata.resolution = (resx + resy) / 2 + newMetadata.focal = newMetadata.FocalFromResolution(newMetadata.resolution) + newMetadata.useFocal = false + + return newMetadata + } + catch (ex) { + if (!console.isAborted) + if (ex.length === undefined || ex.length > 0) + console.criticalln("*** Error: ", ex.toString()) + return null + } + finally { + try { + if (File.exists(STAR_CSV_FILE)) + File.remove(STAR_CSV_FILE) + } + catch (x) { + // Propagate no further filesystem exceptions here. + } + } + } + + this.MatchStars = function (window, predictedCoords) { + /* + * Putative point matches by proximity search. + */ + let actualCoords = new Array(predictedCoords.length) + for (let i = 0; i < predictedCoords.length; ++i) { + let p = predictedCoords[i] + if (p) { + let s = this.starTree.search({ + x0: p.x - this.psfSearchRadius, + y0: p.y - this.psfSearchRadius, + x1: p.x + this.psfSearchRadius, + y1: p.y + this.psfSearchRadius + }) + if (s.length > 0) { + let j = 0 + if (s.length > 1) { + let star = this.starTree.objects[s[0]] + let dx = star.x - p.x + let dy = star.y - p.y + let d2 = dx * dx + dy * dy + for (let i = 1; i < s.length; ++i) { + let star = this.starTree.objects[s[i]] + let dx = star.x - p.x + let dy = star.y - p.y + let d2i = dx * dx + dy * dy + if (d2i < d2) { + j = i + d2 = d2i + } + } + } + let star = this.starTree.objects[s[j]] + actualCoords[i] = new Point(star.x, star.y) + } + } + } + + if (!this.config.distortionCorrection) + return { matchedPoints: actualCoords, meanSparsity: 0, sigmaSparsity: 0, rejectionThreshold: 0 } + + /* + * Adaptive spline outlier rejection based on local sparsity estimation. + * In this context, outliers are wrongly extrapolated points that can + * prevent modeling non-convex surfaces and regions of strongly varying + * distortion by stalling surface spline generation in subsequent + * iterations. + */ + let P = [] + for (let i = 0; i < actualCoords.length; ++i) { + let p = actualCoords[i] + if (p) + P.push({ + x: p.x, y: p.y, + rect: { + x0: p.x - 0.5, y0: p.y - 0.5, + x1: p.x + 0.5, y1: p.y + 0.5 + }, + idx: i + }) + } + let T = new BRQuadTree(P, 256/*bucketSize*/) + let S = new Float32Array(P.length) + for (let i = 0; i < P.length; ++i) { + let p = P[i] + let r = { + x0: p.x - this.config.outlierDetectionRadius, + y0: p.y - this.config.outlierDetectionRadius, + x1: p.x + this.config.outlierDetectionRadius, + y1: p.y + this.config.outlierDetectionRadius + } + let s1 = this.starTree.search(r) + let s2 = T.search(r) + S[i] = s1.length / s2.length + } + let m = Math.median(S) + let s = 1.1926 * Math.Sn(S) + let d = Math.max(this.config.outlierDetectionMinThreshold, + m + this.config.outlierDetectionSigma * s) + for (let i = 0; i < P.length; ++i) + if (S[i] > d) + P[i] = null; // outlier removed + + /* + * Output coordinates. + */ + let Q = new Array(predictedCoords.length) + for (let i = 0; i < P.length; ++i) { + let p = P[i] + if (p) + Q[p.idx] = actualCoords[p.idx] + } + return { matchedPoints: Q, meanSparsity: m, sigmaSparsity: s, rejectionThreshold: d } + } + + // This warning is now silenced. + this.showedWarningOnTruncatedInputSet = true; //false + + this.DetectStars = function (window, metadata) { + /* + * Load reference stars. + */ + if (!this.catalog) + if (this.config.catalogMode == CatalogMode.prototype.LocalText) { + this.catalog = new CustomCatalog(this.config.databasePath) + } + else { + this.catalog = __catalogRegister__.GetCatalog(this.catalogName) + this.catalog.magMax = this.limitMagnitude + this.catalog.restrictToHQStars = this.config.restrictToHQStars + } + this.catalog.Load(metadata, this.config.vizierServer) + let catalogObjects = this.catalog.objects + if (catalogObjects == null) + throw "Catalog error: " + this.catalogName + if (catalogObjects.length < 10) + throw "Insufficient stars found in catalog: " + this.catalogName + if (catalogObjects.length > WCS_MAX_STARS_IN_SOLUTION) + if (!this.showedWarningOnTruncatedInputSet) { + console.warningln("** Warning: Exceeded the maximum number of stars allowed. " + + "Truncating the input set to the ", WCS_MAX_STARS_IN_SOLUTION, " brightest stars.") + this.showedWarningOnTruncatedInputSet = true + } + + /* + * Sort reference stars by magnitude in ascending order (brighter stars + * first). Possible objects with undefined magnitudes are packed at the + * tail of the array. + */ + catalogObjects.sort((a, b) => a.magnitude ? (b.magnitude ? a.magnitude - b.magnitude : -1) : (b.magnitude ? +1 : 0)) + + /* + * Calculate image coordinates of catalog stars with the current + * transformation. + */ + let result = { + projection: ProjectionFactory(this.config, metadata.ra, metadata.dec), + starCoords: [], + coordsG: [], + magnitudes: [], + actualCoords: null + } + let predictedCoords = [] + { + let posRD = [], magnitudes = [] + for (let i = 0, n = Math.min(WCS_MAX_STARS_IN_SOLUTION, catalogObjects.length); i < n; ++i) + if (catalogObjects[i]) { + posRD.push(catalogObjects[i].posRD) + magnitudes.push(catalogObjects[i].magnitude) + } + let posI = metadata.Convert_RD_I_Points(posRD, true/*unscaled*/) + + for (let i = 0; i < posI.length; ++i) { + let pI = posI[i] + if (pI && + pI.x >= 0 && + pI.y >= 0 && + pI.x <= metadata.width && + pI.y <= metadata.height) { + let pG = result.projection.Direct(posRD[i]) + if (pG) { + result.coordsG.push(pG) + result.starCoords.push(posRD[i]) + result.magnitudes.push(magnitudes[i]) + predictedCoords.push(pI) + } + } + } + } + + if (predictedCoords.length < 4) + throw "Unable to define a valid set of reference star positions." + + /* + * Find the stars in the image using predictedCoords as starting point. + */ + let matches = this.MatchStars(window, predictedCoords) + + result.actualCoords = matches.matchedPoints + + /* + * Remove control points with identical coordinates. + */ + { + let A = [] + for (let i = 0; i < result.actualCoords.length; ++i) + if (result.actualCoords[i]) + A.push({ i: i, x: result.actualCoords[i].x, y: result.actualCoords[i].y }) + A.sort((a, b) => (a.x != b.x) ? a.x - b.x : a.y - b.y) + for (let i = 1; i < A.length; ++i) + if (A[i].x == A[i - 1].x) + if (A[i].y == A[i - 1].y) { + result.actualCoords[A[i].i] = null + result.coordsG[A[i].i] = null + } + A = [] + for (let i = 0; i < result.coordsG.length; ++i) + if (result.coordsG[i]) + A.push({ i: i, x: result.coordsG[i].x, y: result.coordsG[i].y }) + A.sort((a, b) => (a.x != b.x) ? a.x - b.x : a.y - b.y) + for (let i = 1; i < A.length; ++i) + if (A[i].x == A[i - 1].x) + if (A[i].y == A[i - 1].y) { + result.actualCoords[A[i].i] = null + result.coordsG[A[i].i] = null + } + } + + /* + * Gather information on matching errors. + */ + result.errors = new Array(predictedCoords.length) + result.numValid = 0 + let meanError, sigmaError, peakError = 0, sum2 = 0 + { + let E = [] + for (let i = 0; i < predictedCoords.length; ++i) + if (result.actualCoords[i]) { + let ex = predictedCoords[i].x - result.actualCoords[i].x + let ey = predictedCoords[i].y - result.actualCoords[i].y + let e = Math.sqrt(ex * ex + ey * ey) + result.errors[i] = e + E.push(e) + if (e > peakError) + peakError = e + result.numValid++ + sum2 += e * e + } + + meanError = Math.median(E) + sigmaError = Math.sqrt(Math.biweightMidvariance(E, meanError)) + } + result.rms = (result.numValid > 0) ? Math.sqrt(sum2 / result.numValid) : 0 + result.score = Math.roundTo(result.numValid / (1 + result.rms), 3) + + if (this.config.distortionCorrection) + console.writeln(format("Surface sparsity : median = %.2f, sigma = %.2f, threshold = %.2f", + matches.meanSparsity, matches.sigmaSparsity, matches.rejectionThreshold)) + console.writeln(format("Matching errors : median = %.2f px, sigma = %.2f px, peak = %.2f px", + meanError, sigmaError, peakError)) + console.writeln(format("Matched stars : %d (%.2f%%)", + result.numValid, 100.0 * result.numValid / predictedCoords.length)) + console.flush() + + return result + } + + this.DoIterationLinear = function (metadata, stars) { + console.flush() + processEvents() + + /* + * Find linear transformations. + */ + let newMetadata = metadata.Clone() + newMetadata.projection = stars.projection + newMetadata.ref_I_G = Math.homography(stars.actualCoords, stars.coordsG) + newMetadata.ref_I_G_linear = newMetadata.ref_I_G + newMetadata.ref_G_I = newMetadata.ref_I_G.inverse() + newMetadata.controlPoints = null + + /* + * Find the celestial coordinates (RD) of the center of the original + * image. First transform from I to G and then unproject from native + * projection coordinates (G) to celestial (RD). + */ + let centerI = new Point(metadata.width / 2, metadata.height / 2) + let centerG = newMetadata.ref_I_G.apply(centerI) + let centerRD = newMetadata.projection.Inverse(centerG) + while (centerRD.x < 0) + centerRD.x += 360 + while (centerRD.x >= 360) + centerRD.x -= 360 + newMetadata.ra = (Math.abs(metadata.ra - centerRD.x) < 1) ? (metadata.ra + centerRD.x * 2) / 3 : centerRD.x + newMetadata.dec = (Math.abs(metadata.dec - centerRD.y) < 1) ? (metadata.dec + centerRD.y * 2) / 3 : centerRD.y + let ref = newMetadata.ref_I_G_linear + let resx = Math.sqrt(ref.at(0, 0) * ref.at(0, 0) + ref.at(0, 1) * ref.at(0, 1)) + let resy = Math.sqrt(ref.at(1, 0) * ref.at(1, 0) + ref.at(1, 1) * ref.at(1, 1)) + newMetadata.resolution = (resx + resy) / 2 + newMetadata.focal = newMetadata.FocalFromResolution(newMetadata.resolution) + newMetadata.useFocal = false + + return newMetadata + } + + this.DoIterationSpline = function (metadata, stars) { + console.flush() + processEvents() + + /* + * Build surface splines. + */ + let newMetadata = metadata.Clone() + newMetadata.projection = stars.projection + newMetadata.ref_I_G_linear = Math.homography(stars.actualCoords, stars.coordsG) + + newMetadata.ref_I_G = new ReferSpline(stars.actualCoords, stars.coordsG, + this.config.splineOrder, + this.config.splineSmoothing, + this.config.enableSimplifier, + this.config.simplifierRejectFraction) + processEvents() + + newMetadata.ref_G_I = new ReferSpline(stars.coordsG, stars.actualCoords, + this.config.splineOrder, + this.config.splineSmoothing, + this.config.enableSimplifier, + this.config.simplifierRejectFraction) + processEvents() + + newMetadata.controlPoints = { + pI: stars.actualCoords, + pG: stars.coordsG, + weights: null + } + + /* + * Find the celestial coordinates (RD) of the center of the original + * image. First transform from I to G and then unproject from native + * projection coordinates (G) to celestial (RD). + */ + let centerI = new Point(metadata.width / 2, metadata.height / 2) + let centerG = newMetadata.ref_I_G.apply(centerI) + let centerRD = newMetadata.projection.Inverse(centerG) + while (centerRD.x < 0) + centerRD.x += 360 + while (centerRD.x >= 360) + centerRD.x -= 360 + newMetadata.ra = (Math.abs(metadata.ra - centerRD.x) < 1) ? (metadata.ra + centerRD.x * 2) / 3 : centerRD.x + newMetadata.dec = (Math.abs(metadata.dec - centerRD.y) < 1) ? (metadata.dec + centerRD.y * 2) / 3 : centerRD.y + let ref = newMetadata.ref_I_G_linear + let resx = Math.sqrt(ref.at(0, 0) * ref.at(0, 0) + ref.at(0, 1) * ref.at(0, 1)) + let resy = Math.sqrt(ref.at(1, 0) * ref.at(1, 0) + ref.at(1, 1) * ref.at(1, 1)) + newMetadata.resolution = (resx + resy) / 2 + newMetadata.focal = newMetadata.FocalFromResolution(newMetadata.resolution) + newMetadata.useFocal = false + + return newMetadata + } + + this.GenerateWorkingImage = function (targetWindow) { + // Convert the image to grayscale. + // The chrominance is not necessary for the astrometry. + let grayscaleImage = new Image + grayscaleImage.assign(targetWindow.mainView.image) + grayscaleImage.colorSpace = ColorSpace_HSI + grayscaleImage.selectedChannel = 2; // intensity component + + let workingWindow = new ImageWindow(grayscaleImage.width, grayscaleImage.height, + 1/*channels*/, 32/*bits*/, true/*float*/, false/*color*/, + targetWindow.mainView.id + "_working") + workingWindow.mainView.beginProcess(UndoFlag_NoSwapFile) + workingWindow.mainView.image.apply(grayscaleImage) + workingWindow.mainView.endProcess() + + // Deallocate now, don't wait for garbage collection. + grayscaleImage.free() + + return workingWindow + } + + this.MetadataDelta = function (metadata1, metadata2, pI) { + /* + * Calculate the difference between the last two iterations using the + * displacement between the center and the given point pI. + */ + let pRD2 = metadata2.Convert_I_RD(pI) + let pRD1 = metadata1.ref_I_G ? metadata1.Convert_I_RD(pI) : pRD2 + let delta1 = 0 + if (pRD1) + delta1 = Math.sqrt(Math.pow((pRD1.x - pRD2.x) * Math.cos(Math.rad(pRD2.y)), 2) + + Math.pow(pRD1.y - pRD2.y, 2)) * 3600 + let delta2 = Math.sqrt(Math.pow((metadata2.ra - metadata1.ra) * Math.cos(Math.rad(metadata2.dec)), 2) + + Math.pow(metadata2.dec - metadata1.dec, 2)) * 3600 + return Math.max(delta1, delta2) + } + + this.OptimizeSolution = function (workingWindow, currentMetadata, stars) { + let finished = false + let iteration = 1 + let numItersWithoutImprovement = 0 + let maxItersWithoutImprovement = 4 + let bestMetadata = currentMetadata + let bestScore = stars.score + let bestRMS = stars.rms + let bestStarCount = stars.numValid + let converged = false + + do { + console.abortEnabled = true + + let result + try { + if (this.config.distortionCorrection) + result = this.DoIterationSpline(currentMetadata, stars) + else + result = this.DoIterationLinear(currentMetadata, stars) + + if (result == null) + throw "" + } + catch (ex) { + let haveException = !console.isAborted && (ex.length === undefined || ex.length > 0) + if (haveException) + console.criticalln("
*** Error: " + ex.toString()) + console.criticalln("" + + (haveException ? "" : "
*** Error: ") + + "The image could not be fully solved. We have tagged it with the latest known valid solution.") + console.abortEnabled = false + break + } + + stars = this.DetectStars(workingWindow, result) + + /* + * Calculate the difference between the current and previous + * iterations using the displacements between the center and eight + * points located on the image borders. Report the maximum difference. + */ + let delta = Math.max(this.MetadataDelta(currentMetadata, result, new Point(0, 0)), + this.MetadataDelta(currentMetadata, result, new Point(result.width, 0)), + this.MetadataDelta(currentMetadata, result, new Point(0, result.height)), + this.MetadataDelta(currentMetadata, result, new Point(result.width, result.height)), + this.MetadataDelta(currentMetadata, result, new Point(result.width / 2, 0)), + this.MetadataDelta(currentMetadata, result, new Point(result.width / 2, result.height)), + this.MetadataDelta(currentMetadata, result, new Point(0, result.height / 2)), + this.MetadataDelta(currentMetadata, result, new Point(result.width, result.height / 2))) + let deltaPx = delta / (result.resolution * 3600) + + console.writeln("
*****") + console.writeln(format("Iteration %d, delta = %.3f as (%.2f px)", iteration, delta, deltaPx)) + console.writeln("Image center ... RA: ", DMSangle.FromAngle(result.ra / 15).ToString(true), + " Dec: ", DMSangle.FromAngle(result.dec).ToString()) + console.writeln(format("Resolution ..... %.2f as/px", result.resolution * 3600)) + console.writeln(format("RMS error ...... %.3f px (%d stars)", stars.rms, stars.numValid)) + + converged = deltaPx < 0.005 && Math.abs(stars.rms - bestRMS) < 0.01 + if (converged || stars.numValid > bestStarCount && (stars.rms <= bestRMS || stars.rms - bestRMS < 0.01)) + stars.score = Math.max(stars.score, bestScore + 1) + + if (stars.score > bestScore) + console.writeln(format("Score .......... \x1b[38;2;128;255;128m%.3f\x1b[0m", stars.score)) + else + console.writeln(format("Score .......... %.3f", stars.score)) + console.writeln("*****") + + /* + * Prevent degenerate cases where we cannot match any stars. This + * happens, among other causes, when projection systems are used + * beyond their capabilities. + */ + if (stars.numValid < 4) { + console.criticalln("*** Error: Unable to find a valid set of star pair matches.") + break + } + + currentMetadata = result + + // Store the best model so far + if (stars.score > bestScore) { + numItersWithoutImprovement = 0 + bestMetadata = result + bestScore = stars.score + bestRMS = stars.rms + bestStarCount = stars.numValid + } + else { + if (iteration == 1) + bestMetadata = result + numItersWithoutImprovement++ + } + + // Finish condition + finished = true + if (converged || numItersWithoutImprovement > maxItersWithoutImprovement) { + if (this.distortModel) { + converged = false + numItersWithoutImprovement = 0 + finished = false + this.distortModel = null + console.noteln("* The solution with distortion model has converged. Trying to optimize it without the model.") + } + else if (converged) + console.noteln(format("* Convergence reached after %d iterations.", iteration)) + else + console.warningln(format("** Warning: Process stalled after %d iterations.", iteration)) + } + else if (iteration > this.config.maxIterations) + console.warningln("** Warning: Reached maximum number of iterations without convergence.") + else + finished = false + + ++iteration + + console.abortEnabled = true + processEvents() + if (console.abortRequested) { + finished = true + console.criticalln("*** User requested abort ***") + } + gc(true) + } + while (!finished) + + if (converged) + console.noteln(format("* Successful astrometry optimization. Score = %.3f", bestScore)) + else + console.warningln(format("** Partial astrometry optimization. Score = %.3f", bestScore)) + console.writeln() + + return bestMetadata + } + + this.SolveImage = function (targetWindow) { + this.error = false + + let abortableBackup = jsAbortable + jsAbortable = true + let auxWindow = null + + try { + console.show() + console.abortEnabled = true + + let workingWindow = targetWindow + if (targetWindow.mainView.image.isColor) + auxWindow = workingWindow = this.GenerateWorkingImage(targetWindow) + + /* + * Build a bucket region quadtree structure with all detected stars in + * the image for fast star matching. + */ + try { + /* + * Step 1 - Star detection + */ + let D = new StarDetector + D.structureLayers = this.config.structureLayers + D.hotPixelFilterRadius = this.config.hotPixelFilterRadius + D.noiseReductionFilterRadius = this.config.noiseReductionFilterRadius + D.sensitivity = this.config.sensitivity + D.peakResponse = this.config.peakResponse + D.allowClusteredSources = false + D.maxDistortion = this.config.maxStarDistortion + D.brightThreshold = this.config.brightThreshold + D.minStructureSize = this.config.minStructureSize + let lastProgressPc = 0 + D.progressCallback = + (count, total) => { + if (count == 0) { + console.write("Detecting stars: 0%") + lastProgressPc = 0 + processEvents() + } + else { + let pc = Math.round(100 * count / total) + if (pc > lastProgressPc) { + console.write(format("\b\b\b\b%3d%%", pc)) + lastProgressPc = pc + processEvents() + } + } + return true + } + + let S = D.stars(workingWindow.mainView.image) + this.numberOfDetectedStars = S.length + if (this.numberOfDetectedStars < 6) + throw "Insufficient stars detected: found " + this.numberOfDetectedStars.toString() + ", at least 6 are required." + + + console.writeln(format("%d stars found ", this.numberOfDetectedStars)) + console.flush() + + /* + * Step 2 - PSF fitting + */ + let stars = [] + let minStructSize = Number.POSITIVE_INFINITY + for (let i = 0; i < S.length; ++i) { + let p = S[i].pos + let r = S[i].rect + stars.push([0, 0, DynamicPSF.prototype.Star_DetectedOk, + r.x0, r.y0, r.x1, r.y1, + p.x, p.y]) + let m = Math.max(r.x1 - r.x0, r.y1 - r.y0) + if (m < minStructSize) + minStructSize = m + } + + let P = new DynamicPSF + P.views = [[workingWindow.mainView.id]] + P.stars = stars + P.astrometry = false + P.autoAperture = true + P.searchRadius = minStructSize + P.circularPSF = false + P.autoPSF = this.config.autoPSF + P.gaussianPSF = true + P.moffatPSF = P.moffat10PSF = P.moffat8PSF = + P.moffat6PSF = P.moffat4PSF = P.moffat25PSF = + P.moffat15PSF = P.lorentzianPSF = this.config.autoPSF + P.variableShapePSF = false + if (!P.executeGlobal()) + throw "Unable to execute DynamicPSF process." + + console.flush() + + stars = [] + for (let psf = P.psf, i = 0; i < psf.length; ++i) { + let p = psf[i] + if (p[3] == DynamicPSF.prototype.PSF_FittedOk) { + let x = p[6] + let y = p[7] + let rx = p[8] / 2 + let ry = p[9] / 2 + stars.push({ + x: x, y: y, + rect: { + x0: x - rx, y0: y - ry, + x1: x + rx, y1: y + ry + } + }) + } + } + + /* + * Step 3 - Remove potential duplicate objects + */ + this.starTree = new BRQuadTree(stars.slice(), 256/*bucketSize*/) + stars = [] + for (let i = 0; i < this.starTree.objects.length; ++i) { + let o = this.starTree.objects[i] + let s = this.starTree.search({ + x0: o.x - 1, y0: o.y - 1, + x1: o.x + 1, y1: o.y + 1 + }) + if (s.length == 1) + stars.push(o) + } + if (stars.length < 6) + throw "Insufficient number of objects: found " + stars.length.toString() + ", at least 6 are required." + + console.write(format("* Removed %d conflicting sources (%.2f %%)", + this.starTree.objects.length - stars.length, 100 * (this.starTree.objects.length - stars.length) / stars.length)) + + /* + * Step 4 - Quadtree generation + */ + this.starTree.build(stars.slice(), 256/*bucketSize*/) + console.write(format("* Search quadtree generated with %d objects, %d node(s), height = %d", + this.starTree.objects.length, this.starTree.numberOfNodes(), this.starTree.height())) + + /* + * Step 5 - Calculate search and matching tolerances + */ + this.psfMinimumDistance = Math.min(stars[0].rect.x1 - stars[0].rect.x0, + stars[0].rect.y1 - stars[0].rect.y0) + for (let i = 1; i < stars.length; ++i) { + let s = stars[i] + let d = Math.min(stars[i].rect.x1 - stars[i].rect.x0, + stars[i].rect.y1 - stars[i].rect.y0) + if (d < this.psfMinimumDistance) + this.psfMinimumDistance = d + } + this.psfMinimumDistance = Math.max(2, Math.trunc(0.75 * (this.psfMinimumDistance - 2))); // StarDetector inflates detection regions + this.psfSearchRadius = 1.0 * this.psfMinimumDistance + console.writeln(format("* Star matching tolerance: %d px", this.psfMinimumDistance)) + console.flush() + } + catch (ex) { + this.starTree = null + gc() + throw ex + } + + /* + * Find limit magnitude. + */ + if (this.config.autoMagnitude || this.config.catalogMode == CatalogMode.prototype.Automatic) { + let fov = this.metadata.resolution * Math.max(this.metadata.width, this.metadata.height) + // Empiric formula for 1000 stars at 20 deg of galactic latitude + let m = 14.5 * Math.pow(fov, -0.179) + m = Math.round(100 * Math.min(20, Math.max(7, m))) / 100 + + /* + * Identify a local XPSD server and use it if available to find an + * optimal magnitude limit adaptively. + */ + let xpsd = ((typeof Gaia) != 'undefined') ? (new Gaia) : null + if (xpsd) { + xpsd.command = "get-info" + xpsd.dataRelease = Gaia.prototype.DataRelease_BestAvailable + xpsd.executeGlobal() + if (xpsd.isValid) { + if (this.config.autoMagnitude) { + let radiusPx = Math.SQRT2 * Math.sqrt(this.metadata.width * this.metadata.height) / 2 + let targetStarCount = this.numberOfDetectedStars * 1.25 + + console.writeln(format("
Searching for optimal magnitude limit. Target: %u stars", targetStarCount)) + + xpsd.command = "search" + xpsd.centerRA = this.metadata.ra + xpsd.centerDec = this.metadata.dec + xpsd.radius = this.metadata.resolution * radiusPx + xpsd.magnitudeLow = -1.5 + xpsd.sourceLimit = 0; // do not retrieve objects, just count them. + xpsd.exclusionFlags = GaiaFlag_NoPM + xpsd.inclusionFlags = this.config.restrictToHQStars ? GaiaFlag_GoodAstrometry : 0 + xpsd.verbosity = 0; // work quietly + xpsd.generateTextOutput = false + + const MAX_AUTOMAG_ITER = 100; // prevent a hypothetical case where the loop might stall + for (let m0 = 7, m1 = xpsd.databaseMagnitudeHigh, i = 0; i < MAX_AUTOMAG_ITER; ++i) { + xpsd.magnitudeHigh = m + xpsd.executeGlobal() + console.writeln(format("m = %.2f, %u stars", m, xpsd.excessCount)) + if (xpsd.excessCount < targetStarCount) { + if (m1 - m < 0.05) + break + m0 = m + m += (m1 - m) / 2 + } + else if (xpsd.excessCount > 1.05 * targetStarCount) { + if (m - m0 < 0.05) + break + m1 = m + m -= (m - m0) / 2 + } + else + break + } + } + } + else { + /* + * We have a local XPSD server, but either it is not well + * configured, or there are no database files available. + */ + xpsd = null + } + } + + if (this.config.autoMagnitude) { + this.limitMagnitude = m + console.noteln("
* Using an automatically calculated limit magnitude of " + format("%.2f", m) + ".") + } + else + this.limitMagnitude = this.config.magnitude + + if (this.config.catalogMode == CatalogMode.prototype.Automatic) { + /* + * - For magnitude limits below 8, use the Bright Stars catalog. + * - Otherwise: + * - Use a local XPSD server when available. + * - Otherwise: + * - Use the online Gaia DR2 catalog if FOV <= 3 deg. + * - Use the online TYCHO-2 catalog if FOV > 3 deg. + */ + if (this.limitMagnitude < 8) + this.catalogName = "Bright Stars" + else if (fov > 3 && !xpsd) + this.catalogName = "TYCHO-2" + else if (xpsd) { + switch (xpsd.outputDataRelease) { + default: + case Gaia.prototype.DataRelease_3: + this.catalogName = "GaiaDR3_XPSD" + break + case Gaia.prototype.DataRelease_E3: + this.catalogName = "GaiaEDR3_XPSD" + break + case Gaia.prototype.DataRelease_2: + this.catalogName = "GaiaDR2_XPSD" + break + } + } + else + this.catalogName = "GaiaDR2" + + console.noteln("* Using the automatically selected " + this.catalogName + " catalog.") + } + else + this.catalogName = this.config.catalog + } + else { + this.limitMagnitude = this.config.magnitude + this.catalogName = this.config.catalog + } + + console.writeln("Seed parameters for plate solving:") + console.writeln(" Center coordinates: RA = ", + DMSangle.FromAngle(this.metadata.ra / 15).ToString(true), ", Dec = ", + DMSangle.FromAngle(this.metadata.dec).ToString()) + console.writeln(format(" Resolution: %.3f as/px", this.metadata.resolution * 3600)) + console.writeln() + + let stars = null + + this.distortModel = null + + /* + * Initial Alignment. + */ + try { + let result = this.DoIterationSA(targetWindow, this.metadata) + if (!result) + throw "" + this.metadata = result + + stars = this.DetectStars(workingWindow, this.metadata) + + console.writeln("
*****") + console.writeln("Initial alignment") + console.writeln("Image center ... RA: ", DMSangle.FromAngle(this.metadata.ra / 15).ToString(true), + " Dec: ", DMSangle.FromAngle(this.metadata.dec).ToString()) + console.writeln(format("Resolution ..... %.2f as/px", this.metadata.resolution * 3600)) + console.writeln(format("RMS error ...... %.3f px (%d stars)", stars.rms, stars.numValid)) + console.writeln(format("Score .......... %.3f", stars.score)) + console.writeln("*****") + } + catch (ex) { + if (!console.isAborted) + if (ex.length === undefined || ex.length > 0) + console.criticalln("
*** Error: " + ex.toString()) + this.error = true + return false + } + + /* + * Optimize the solution. + */ + this.metadata = this.OptimizeSolution(workingWindow, this.metadata, stars) + + /* + * Update metadata and regenerate the astrometric solution. + */ + targetWindow.mainView.beginProcess(UndoFlag_Keywords | UndoFlag_AstrometricSolution) + this.metadata.SaveKeywords(targetWindow, false/*beginProcess*/) + this.metadata.SaveProperties(targetWindow, "ImageSolver " + SOLVERVERSION, this.catalog.name) + targetWindow.regenerateAstrometricSolution() + targetWindow.mainView.endProcess() + + return true + } + catch (ex) { + this.error = true + throw ex + } + finally { + jsAbortable = abortableBackup + + if (auxWindow) + auxWindow.forceClose() + } + } +} + +function decodeParams(hex) { + const buffer = new Uint8Array(hex.length / 4) + + for (let i = 0; i < hex.length; i += 4) { + buffer[i / 4] = parseInt(hex.substr(i, 4), 16) + } + + return JSON.parse(String.fromCharCode.apply(null, buffer)) +} + +function imageSolver() { + const data = { + success: true, + errorMessage: null, + outputImage: null, + } + + try { + const input = decodeParams(jsArguments[0]) + + const targetPath = input.targetPath + const statusPath = input.statusPath + const centerRA = input.centerRA + const centerDEC = input.centerDEC + const pixelSize = input.pixelSize + const resolution = input.resolution // arcsec/px + const focalDistance = input.focalDistance + + console.writeln("image solver started") + console.writeln("targetPath=" + targetPath) + console.writeln("statusPath=" + statusPath) + console.writeln("centerRA=" + centerRA) + console.writeln("centerDEC=" + centerDEC) + console.writeln("pixelSize=" + pixelSize) + console.writeln("resolution=" + resolution) + console.writeln("focalDistance=" + focalDistance) + + const P = new ImageSolver + + const targetWindow = ImageWindow.open(targetPath)[0] + + P.Init(targetWindow) + + P.metadata.topocentric = false + P.metadata.referenceSystem = "ICRS" + P.metadata.ra = centerRA + P.metadata.dec = centerDEC + + if (focalDistance > 0) { + P.metadata.useFocal = false + P.metadata.focal = focalDistance + P.metadata.resolution = pixelSize / focalDistance * 0.18 / Math.PI + } else { + P.metadata.useFocal = false + P.metadata.resolution = resolution / 3600 // deg? + } + + P.metadata.xpixsz = pixelSize + + P.metadata.width = targetWindow.mainView.image.width + P.metadata.height = targetWindow.mainView.image.height + + if (P.SolveImage(targetWindow, false)) { + console.writeln(targetWindow.astrometricSolutionSummary()) + data.resolution = P.metadata.resolution * Math.PI / 180.0 + data.pixelSize = P.metadata.xpixsz + data.focalDistance = P.metadata.focal + data.rightAscension = P.metadata.ra * Math.PI / 180.0 + data.declination = P.metadata.dec * Math.PI / 180.0 + data.imageWidth = P.metadata.width + data.imageHeight = P.metadata.height + data.width = data.resolution * data.imageWidth + data.height = data.resolution * data.imageHeight + data.rotation = 0 + data.astrometricSolutionSummary = targetWindow.astrometricSolutionSummary() + } else { + data.success = false + data.errorMessage = "the image could not be plate solved" + console.criticalln(data.errorMessage) + } + + console.writeln("image solver finished") + } catch (e) { + data.success = false + data.errorMessage = e.message + console.criticalln(data.errorMessage) + } finally { + if (targetWindow) + targetWindow.forceClose() + + File.writeTextFile(statusPath, "@" + JSON.stringify(data) + "#") + gc(true) + } +} + +imageSolver() diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js b/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js index 455d9b6ab..e069cf329 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/LRGBCombination.js @@ -42,10 +42,10 @@ function lrgbCombination() { var P = new LRGBCombination P.channels = [ // enabled, id, k - [!!redPath, redWindow ? redWindow.mainView.id : "", channelWeights[1]], - [!!greenPath, greenWindow ? greenWindow.mainView.id : "", channelWeights[2]], - [!!bluePath, blueWindow ? blueWindow.mainView.id : "", channelWeights[3]], - [!!luminancePath, luminanceWindow ? luminanceWindow.mainView.id : "", channelWeights[0]] + [!!redPath, redWindow ? redWindow.mainView.id : "", channelWeights[1]], + [!!greenPath, greenWindow ? greenWindow.mainView.id : "", channelWeights[2]], + [!!bluePath, blueWindow ? blueWindow.mainView.id : "", channelWeights[3]], + [!!luminancePath, luminanceWindow ? luminanceWindow.mainView.id : "", channelWeights[0]] ] P.mL = 0.500 P.mc = 0.500 @@ -72,7 +72,7 @@ function lrgbCombination() { } catch (e) { data.success = false data.errorMessage = e.message - console.writeln(data.errorMessage) + console.criticalln(data.errorMessage) } finally { File.writeTextFile(statusPath, "@" + JSON.stringify(data) + "#") } diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/LuminanceCombination.js b/nebulosa-pixinsight/src/main/resources/pixinsight/LuminanceCombination.js index e70684726..4dc36858a 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/LuminanceCombination.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/LuminanceCombination.js @@ -36,10 +36,10 @@ function luminanceCombination() { var P = new LRGBCombination P.channels = [ // enabled, id, k - [false, "", 1.0], - [false, "", 1.0], - [false, "", 1.0], - [true, luminanceWindow.mainView.id, weight] + [false, "", 1.0], + [false, "", 1.0], + [false, "", 1.0], + [true, luminanceWindow.mainView.id, weight] ] P.mL = 0.500 P.mc = 0.500 @@ -62,7 +62,7 @@ function luminanceCombination() { } catch (e) { data.success = false data.errorMessage = e.message - console.writeln(data.errorMessage) + console.criticalln(data.errorMessage) } finally { File.writeTextFile(statusPath, "@" + JSON.stringify(data) + "#") } diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/PixelMath.js b/nebulosa-pixinsight/src/main/resources/pixinsight/PixelMath.js index b3ad983a2..048aa1813 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/PixelMath.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/PixelMath.js @@ -94,7 +94,7 @@ function pixelMath() { } catch (e) { data.success = false data.errorMessage = e.message - console.writeln(data.errorMessage) + console.criticalln(data.errorMessage) } finally { File.writeTextFile(statusPath, "@" + JSON.stringify(data) + "#") } diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightPlateSolverTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightPlateSolverTest.kt new file mode 100644 index 000000000..52794a061 --- /dev/null +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightPlateSolverTest.kt @@ -0,0 +1,37 @@ +import io.kotest.core.annotation.EnabledIf +import io.kotest.matchers.doubles.plusOrMinus +import io.kotest.matchers.ints.shouldBeExactly +import io.kotest.matchers.shouldBe +import nebulosa.math.* +import nebulosa.pixinsight.platesolver.PixInsightPlateSolver +import nebulosa.pixinsight.script.PixInsightScriptRunner +import nebulosa.test.AbstractFitsAndXisfTest +import nebulosa.test.NonGitHubOnlyCondition +import java.nio.file.Path +import kotlin.math.roundToInt + +@EnabledIf(NonGitHubOnlyCondition::class) +class PixInsightPlateSolverTest : AbstractFitsAndXisfTest() { + + init { + "solver" { + val runner = PixInsightScriptRunner(Path.of("PixInsight")) + val pixelSize = 6.58 + val resolution = 6.78.arcsec + val solver = PixInsightPlateSolver(runner, pixelSize, resolution = resolution) + val path = download("https://nova.astrometry.net/image/14603", "jpg") + val centerRA = "06 40 51".hours + val centerDEC = "09 49 53".deg + + val solution = solver.solve(path, null, centerRA, centerDEC) + + solution.scale.toArcsec shouldBe (6.774 plusOrMinus 1e-3) + solution.rightAscension.formatHMS() shouldBe "06h40m51.8s" + solution.declination.formatSignedDMS() shouldBe "+009ยฐ49'53.6\"" + solution.width.toArcmin shouldBe (90.321 plusOrMinus 1e-3) + solution.height.toArcmin shouldBe (59.386 plusOrMinus 1e-3) + solution.widthInPixels.roundToInt() shouldBeExactly 800 + solution.heightInPixels.roundToInt() shouldBeExactly 526 + } + } +} diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt index cf1ed2a92..343a8b0c2 100644 --- a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt @@ -3,12 +3,14 @@ import io.kotest.engine.spec.tempdir import io.kotest.engine.spec.tempfile import io.kotest.matchers.booleans.shouldBeTrue import io.kotest.matchers.doubles.plusOrMinus +import io.kotest.matchers.ints.shouldBeExactly import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe import nebulosa.fits.fits import nebulosa.fits.isFits import nebulosa.image.Image import nebulosa.image.algorithms.transformation.AutoScreenTransformFunction +import nebulosa.math.* import nebulosa.pixinsight.script.* import nebulosa.pixinsight.script.PixInsightScript.Companion.UNSPECIFIED_SLOT import nebulosa.test.AbstractFitsAndXisfTest @@ -16,6 +18,7 @@ import nebulosa.test.NonGitHubOnlyCondition import nebulosa.xisf.isXisf import nebulosa.xisf.xisf import java.nio.file.Path +import kotlin.math.roundToInt @EnabledIf(NonGitHubOnlyCondition::class) class PixInsightScriptTest : AbstractFitsAndXisfTest() { @@ -26,11 +29,11 @@ class PixInsightScriptTest : AbstractFitsAndXisfTest() { "!startup" { PixInsightStartup(PixInsightScript.DEFAULT_SLOT) - .use { it.runSync(runner).shouldBeTrue() } + .use { it.runSync(runner).success.shouldBeTrue() } } "!is running" { PixInsightIsRunning(PixInsightScript.DEFAULT_SLOT) - .use { it.runSync(runner).shouldBeTrue() } + .use { it.runSync(runner).success.shouldBeTrue() } } "calibrate" { PixInsightCalibrate(UNSPECIFIED_SLOT, workingDirectory, PI_01_LIGHT, PI_DARK, PI_FLAT, PI_BIAS) @@ -126,6 +129,45 @@ class PixInsightScriptTest : AbstractFitsAndXisfTest() { PixInsightFileFormatConversion(UNSPECIFIED_SLOT, xisfPath, fitsPath) .use { it.runSync(runner).outputImage.shouldNotBeNull().isFits().shouldBeTrue() } } + "image solver" { + // https://nova.astrometry.net/user_images/10373761 + val path = download("https://nova.astrometry.net/image/14603", "jpg") + val resolution = 6.78 // arcsec/px + val centerRA = "06 40 51".hours + val centerDEC = "09 49 53".deg + + // Estimated to match resolution = (pixelSize / focalDistance) * 206.265 + val focalDistance = 200.0 // mm + val pixelSize = 6.58 + + with(PixInsightImageSolver(UNSPECIFIED_SLOT, path, centerRA, centerDEC, pixelSize = pixelSize, resolution = resolution) + .use { it.runSync(runner) }) { + success.shouldBeTrue() + this.focalDistance shouldBe (200.355 plusOrMinus 1e-5) + this.pixelSize shouldBe (6.58 plusOrMinus 1e-2) + this.resolution.toArcsec shouldBe (6.774 plusOrMinus 1e-3) + rightAscension.formatHMS() shouldBe "06h40m51.8s" + declination.formatSignedDMS() shouldBe "+009ยฐ49'53.6\"" + width.toArcmin shouldBe (90.321 plusOrMinus 1e-3) + height.toArcmin shouldBe (59.386 plusOrMinus 1e-3) + imageWidth.roundToInt() shouldBeExactly 800 + imageHeight.roundToInt() shouldBeExactly 526 + } + + with(PixInsightImageSolver(UNSPECIFIED_SLOT, path, centerRA, centerDEC, pixelSize = pixelSize, focalDistance = focalDistance) + .use { it.runSync(runner) }) { + success.shouldBeTrue() + this.focalDistance shouldBe (200.355 plusOrMinus 1e-5) + this.pixelSize shouldBe (6.58 plusOrMinus 1e-2) + this.resolution.toArcsec shouldBe (6.774 plusOrMinus 1e-3) + rightAscension.formatHMS() shouldBe "06h40m51.8s" + declination.formatSignedDMS() shouldBe "+009ยฐ49'53.6\"" + width.toArcmin shouldBe (90.321 plusOrMinus 1e-3) + height.toArcmin shouldBe (59.386 plusOrMinus 1e-3) + imageWidth.roundToInt() shouldBeExactly 800 + imageHeight.roundToInt() shouldBeExactly 526 + } + } } companion object { diff --git a/nebulosa-test/src/main/kotlin/nebulosa/test/AbstractFitsAndXisfTest.kt b/nebulosa-test/src/main/kotlin/nebulosa/test/AbstractFitsAndXisfTest.kt index f14f90738..2ef1bcedc 100644 --- a/nebulosa-test/src/main/kotlin/nebulosa/test/AbstractFitsAndXisfTest.kt +++ b/nebulosa-test/src/main/kotlin/nebulosa/test/AbstractFitsAndXisfTest.kt @@ -30,104 +30,104 @@ import kotlin.io.path.* @Suppress("PropertyName") abstract class AbstractFitsAndXisfTest : StringSpec() { - protected val M82_MONO_8_LZ4_XISF by lazy { download("M82.Mono.8.LZ4.xisf", GITHUB_XISF_URL) } - protected val M82_MONO_8_LZ4_HC_XISF by lazy { download("M82.Mono.8.LZ4-HC.xisf", GITHUB_XISF_URL) } - protected val M82_MONO_8_XISF by lazy { download("M82.Mono.8.xisf", GITHUB_XISF_URL) } - protected val M82_MONO_8_ZLIB_XISF by lazy { download("M82.Mono.8.ZLib.xisf", GITHUB_XISF_URL) } - protected val M82_MONO_8_ZSTANDARD_XISF by lazy { download("M82.Mono.8.ZStandard.xisf", GITHUB_XISF_URL) } - protected val M82_MONO_16_XISF by lazy { download("M82.Mono.16.xisf", GITHUB_XISF_URL) } - protected val M82_MONO_32_XISF by lazy { download("M82.Mono.32.xisf", GITHUB_XISF_URL) } - protected val M82_MONO_F32_XISF by lazy { download("M82.Mono.F32.xisf", GITHUB_XISF_URL) } - protected val M82_MONO_F64_XISF by lazy { download("M82.Mono.F64.xisf", GITHUB_XISF_URL) } - - protected val M82_COLOR_8_LZ4_XISF by lazy { download("M82.Color.8.LZ4.xisf", GITHUB_XISF_URL) } - protected val M82_COLOR_8_LZ4_HC_XISF by lazy { download("M82.Color.8.LZ4-HC.xisf", GITHUB_XISF_URL) } - protected val M82_COLOR_8_XISF by lazy { download("M82.Color.8.xisf", GITHUB_XISF_URL) } - protected val M82_COLOR_8_ZLIB_XISF by lazy { download("M82.Color.8.ZLib.xisf", GITHUB_XISF_URL) } - protected val M82_COLOR_8_ZSTANDARD_XISF by lazy { download("M82.Color.8.ZStandard.xisf", GITHUB_XISF_URL) } - protected val M82_COLOR_16_XISF by lazy { download("M82.Color.16.xisf", GITHUB_XISF_URL) } - protected val M82_COLOR_32_XISF by lazy { download("M82.Color.32.xisf", GITHUB_XISF_URL) } - protected val M82_COLOR_F32_XISF by lazy { download("M82.Color.F32.xisf", GITHUB_XISF_URL) } - protected val M82_COLOR_F64_XISF by lazy { download("M82.Color.F64.xisf", GITHUB_XISF_URL) } - protected val DEBAYER_XISF_PATH by lazy { download("Debayer.xisf", GITHUB_XISF_URL) } - - protected val NGC3344_MONO_8_FITS by lazy { download("NGC3344.Mono.8.fits", GITHUB_FITS_URL) } - protected val NGC3344_MONO_16_FITS by lazy { download("NGC3344.Mono.16.fits", GITHUB_FITS_URL) } - protected val NGC3344_MONO_32_FITS by lazy { download("NGC3344.Mono.32.fits", GITHUB_FITS_URL) } - protected val NGC3344_MONO_F32_FITS by lazy { download("NGC3344.Mono.F32.fits", GITHUB_FITS_URL) } - protected val NGC3344_MONO_F64_FITS by lazy { download("NGC3344.Mono.F64.fits", GITHUB_FITS_URL) } - - protected val NGC3344_COLOR_8_FITS by lazy { download("NGC3344.Color.8.fits", GITHUB_FITS_URL) } - protected val NGC3344_COLOR_16_FITS by lazy { download("NGC3344.Color.16.fits", GITHUB_FITS_URL) } - protected val NGC3344_COLOR_32_FITS by lazy { download("NGC3344.Color.32.fits", GITHUB_FITS_URL) } - protected val NGC3344_COLOR_F32_FITS by lazy { download("NGC3344.Color.F32.fits", GITHUB_FITS_URL) } - protected val NGC3344_COLOR_F64_FITS by lazy { download("NGC3344.Color.F64.fits", GITHUB_FITS_URL) } - - protected val PALETTE_MONO_8_FITS by lazy { download("PALETTE.Mono.8.fits", GITHUB_FITS_URL) } - protected val PALETTE_MONO_16_FITS by lazy { download("PALETTE.Mono.16.fits", GITHUB_FITS_URL) } - protected val PALETTE_MONO_32_FITS by lazy { download("PALETTE.Mono.32.fits", GITHUB_FITS_URL) } - protected val PALETTE_MONO_F32_FITS by lazy { download("PALETTE.Mono.F32.fits", GITHUB_FITS_URL) } - protected val PALETTE_MONO_F64_FITS by lazy { download("PALETTE.Mono.F64.fits", GITHUB_FITS_URL) } - - protected val PALETTE_COLOR_8_FITS by lazy { download("PALETTE.Color.8.fits", GITHUB_FITS_URL) } - protected val PALETTE_COLOR_16_FITS by lazy { download("PALETTE.Color.16.fits", GITHUB_FITS_URL) } - protected val PALETTE_COLOR_32_FITS by lazy { download("PALETTE.Color.32.fits", GITHUB_FITS_URL) } - protected val PALETTE_COLOR_F32_FITS by lazy { download("PALETTE.Color.F32.fits", GITHUB_FITS_URL) } - protected val PALETTE_COLOR_F64_FITS by lazy { download("PALETTE.Color.F64.fits", GITHUB_FITS_URL) } - - protected val PALETTE_MONO_8_XISF by lazy { download("PALETTE.Mono.8.xisf", GITHUB_XISF_URL) } - protected val PALETTE_MONO_16_XISF by lazy { download("PALETTE.Mono.16.xisf", GITHUB_XISF_URL) } - protected val PALETTE_MONO_32_XISF by lazy { download("PALETTE.Mono.32.xisf", GITHUB_XISF_URL) } - protected val PALETTE_MONO_F32_XISF by lazy { download("PALETTE.Mono.F32.xisf", GITHUB_XISF_URL) } - protected val PALETTE_MONO_F64_XISF by lazy { download("PALETTE.Mono.F64.xisf", GITHUB_XISF_URL) } - - protected val PALETTE_COLOR_8_XISF by lazy { download("PALETTE.Color.8.xisf", GITHUB_XISF_URL) } - protected val PALETTE_COLOR_16_XISF by lazy { download("PALETTE.Color.16.xisf", GITHUB_XISF_URL) } - protected val PALETTE_COLOR_32_XISF by lazy { download("PALETTE.Color.32.xisf", GITHUB_XISF_URL) } - protected val PALETTE_COLOR_F32_XISF by lazy { download("PALETTE.Color.F32.xisf", GITHUB_XISF_URL) } - protected val PALETTE_COLOR_F64_XISF by lazy { download("PALETTE.Color.F64.xisf", GITHUB_XISF_URL) } - - protected val DEBAYER_FITS by lazy { download("Debayer.fits", GITHUB_FITS_URL) } - protected val M6707HH by lazy { download("M6707HH.fits", ASTROPY_PHOTOMETRY_URL) } + protected val M82_MONO_8_LZ4_XISF by lazy { download("$GITHUB_XISF_URL/M82.Mono.8.LZ4.xisf") } + protected val M82_MONO_8_LZ4_HC_XISF by lazy { download("$GITHUB_XISF_URL/M82.Mono.8.LZ4-HC.xisf") } + protected val M82_MONO_8_XISF by lazy { download("$GITHUB_XISF_URL/M82.Mono.8.xisf") } + protected val M82_MONO_8_ZLIB_XISF by lazy { download("$GITHUB_XISF_URL/M82.Mono.8.ZLib.xisf") } + protected val M82_MONO_8_ZSTANDARD_XISF by lazy { download("$GITHUB_XISF_URL/M82.Mono.8.ZStandard.xisf") } + protected val M82_MONO_16_XISF by lazy { download("$GITHUB_XISF_URL/M82.Mono.16.xisf") } + protected val M82_MONO_32_XISF by lazy { download("$GITHUB_XISF_URL/M82.Mono.32.xisf") } + protected val M82_MONO_F32_XISF by lazy { download("$GITHUB_XISF_URL/M82.Mono.F32.xisf") } + protected val M82_MONO_F64_XISF by lazy { download("$GITHUB_XISF_URL/M82.Mono.F64.xisf") } + + protected val M82_COLOR_8_LZ4_XISF by lazy { download("$GITHUB_XISF_URL/M82.Color.8.LZ4.xisf") } + protected val M82_COLOR_8_LZ4_HC_XISF by lazy { download("$GITHUB_XISF_URL/M82.Color.8.LZ4-HC.xisf") } + protected val M82_COLOR_8_XISF by lazy { download("$GITHUB_XISF_URL/M82.Color.8.xisf") } + protected val M82_COLOR_8_ZLIB_XISF by lazy { download("$GITHUB_XISF_URL/M82.Color.8.ZLib.xisf") } + protected val M82_COLOR_8_ZSTANDARD_XISF by lazy { download("$GITHUB_XISF_URL/M82.Color.8.ZStandard.xisf") } + protected val M82_COLOR_16_XISF by lazy { download("$GITHUB_XISF_URL/M82.Color.16.xisf") } + protected val M82_COLOR_32_XISF by lazy { download("$GITHUB_XISF_URL/M82.Color.32.xisf") } + protected val M82_COLOR_F32_XISF by lazy { download("$GITHUB_XISF_URL/M82.Color.F32.xisf") } + protected val M82_COLOR_F64_XISF by lazy { download("$GITHUB_XISF_URL/M82.Color.F64.xisf") } + protected val DEBAYER_XISF_PATH by lazy { download("$GITHUB_XISF_URL/Debayer.xisf") } + + protected val NGC3344_MONO_8_FITS by lazy { download("$GITHUB_FITS_URL/NGC3344.Mono.8.fits") } + protected val NGC3344_MONO_16_FITS by lazy { download("$GITHUB_FITS_URL/NGC3344.Mono.16.fits") } + protected val NGC3344_MONO_32_FITS by lazy { download("$GITHUB_FITS_URL/NGC3344.Mono.32.fits") } + protected val NGC3344_MONO_F32_FITS by lazy { download("$GITHUB_FITS_URL/NGC3344.Mono.F32.fits") } + protected val NGC3344_MONO_F64_FITS by lazy { download("$GITHUB_FITS_URL/NGC3344.Mono.F64.fits") } + + protected val NGC3344_COLOR_8_FITS by lazy { download("$GITHUB_FITS_URL/NGC3344.Color.8.fits") } + protected val NGC3344_COLOR_16_FITS by lazy { download("$GITHUB_FITS_URL/NGC3344.Color.16.fits") } + protected val NGC3344_COLOR_32_FITS by lazy { download("$GITHUB_FITS_URL/NGC3344.Color.32.fits") } + protected val NGC3344_COLOR_F32_FITS by lazy { download("$GITHUB_FITS_URL/NGC3344.Color.F32.fits") } + protected val NGC3344_COLOR_F64_FITS by lazy { download("$GITHUB_FITS_URL/NGC3344.Color.F64.fits") } + + protected val PALETTE_MONO_8_FITS by lazy { download("$GITHUB_FITS_URL/PALETTE.Mono.8.fits") } + protected val PALETTE_MONO_16_FITS by lazy { download("$GITHUB_FITS_URL/PALETTE.Mono.16.fits") } + protected val PALETTE_MONO_32_FITS by lazy { download("$GITHUB_FITS_URL/PALETTE.Mono.32.fits") } + protected val PALETTE_MONO_F32_FITS by lazy { download("$GITHUB_FITS_URL/PALETTE.Mono.F32.fits") } + protected val PALETTE_MONO_F64_FITS by lazy { download("$GITHUB_FITS_URL/PALETTE.Mono.F64.fits") } + + protected val PALETTE_COLOR_8_FITS by lazy { download("$GITHUB_FITS_URL/PALETTE.Color.8.fits") } + protected val PALETTE_COLOR_16_FITS by lazy { download("$GITHUB_FITS_URL/PALETTE.Color.16.fits") } + protected val PALETTE_COLOR_32_FITS by lazy { download("$GITHUB_FITS_URL/PALETTE.Color.32.fits") } + protected val PALETTE_COLOR_F32_FITS by lazy { download("$GITHUB_FITS_URL/PALETTE.Color.F32.fits") } + protected val PALETTE_COLOR_F64_FITS by lazy { download("$GITHUB_FITS_URL/PALETTE.Color.F64.fits") } + + protected val PALETTE_MONO_8_XISF by lazy { download("$GITHUB_XISF_URL/PALETTE.Mono.8.xisf") } + protected val PALETTE_MONO_16_XISF by lazy { download("$GITHUB_XISF_URL/PALETTE.Mono.16.xisf") } + protected val PALETTE_MONO_32_XISF by lazy { download("$GITHUB_XISF_URL/PALETTE.Mono.32.xisf") } + protected val PALETTE_MONO_F32_XISF by lazy { download("$GITHUB_XISF_URL/PALETTE.Mono.F32.xisf") } + protected val PALETTE_MONO_F64_XISF by lazy { download("$GITHUB_XISF_URL/PALETTE.Mono.F64.xisf") } + + protected val PALETTE_COLOR_8_XISF by lazy { download("$GITHUB_XISF_URL/PALETTE.Color.8.xisf") } + protected val PALETTE_COLOR_16_XISF by lazy { download("$GITHUB_XISF_URL/PALETTE.Color.16.xisf") } + protected val PALETTE_COLOR_32_XISF by lazy { download("$GITHUB_XISF_URL/PALETTE.Color.32.xisf") } + protected val PALETTE_COLOR_F32_XISF by lazy { download("$GITHUB_XISF_URL/PALETTE.Color.F32.xisf") } + protected val PALETTE_COLOR_F64_XISF by lazy { download("$GITHUB_XISF_URL/PALETTE.Color.F64.xisf") } + + protected val DEBAYER_FITS by lazy { download("$GITHUB_FITS_URL/Debayer.fits") } + protected val M6707HH by lazy { download("$ASTROPY_PHOTOMETRY_URL/M6707HH.fits") } protected val M31_FITS by lazy { download("00 42 44.3".hours, "41 16 9".deg, 3.deg) } - protected val STAR_FOCUS_1 by lazy { download("STAR.FOCUS.1.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_2 by lazy { download("STAR.FOCUS.2.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_3 by lazy { download("STAR.FOCUS.3.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_4 by lazy { download("STAR.FOCUS.4.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_5 by lazy { download("STAR.FOCUS.5.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_6 by lazy { download("STAR.FOCUS.6.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_7 by lazy { download("STAR.FOCUS.7.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_8 by lazy { download("STAR.FOCUS.8.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_9 by lazy { download("STAR.FOCUS.9.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_10 by lazy { download("STAR.FOCUS.10.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_11 by lazy { download("STAR.FOCUS.11.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_12 by lazy { download("STAR.FOCUS.12.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_13 by lazy { download("STAR.FOCUS.13.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_14 by lazy { download("STAR.FOCUS.14.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_15 by lazy { download("STAR.FOCUS.15.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_16 by lazy { download("STAR.FOCUS.16.fits", GITHUB_FITS_URL) } - protected val STAR_FOCUS_17 by lazy { download("STAR.FOCUS.17.fits", GITHUB_FITS_URL) } - - protected val PI_01_LIGHT by lazy { download("PI.01.LIGHT.fits", GITHUB_FITS_URL) } - protected val PI_02_LIGHT by lazy { download("PI.02.LIGHT.fits", GITHUB_FITS_URL) } - protected val PI_03_LIGHT by lazy { download("PI.03.LIGHT.fits", GITHUB_FITS_URL) } - protected val PI_04_LIGHT by lazy { download("PI.04.LIGHT.fits", GITHUB_FITS_URL) } - protected val PI_05_LIGHT by lazy { download("PI.05.LIGHT.fits", GITHUB_FITS_URL) } - protected val PI_06_LIGHT by lazy { download("PI.06.LIGHT.fits", GITHUB_FITS_URL) } - protected val PI_07_LIGHT by lazy { download("PI.07.LIGHT.fits", GITHUB_FITS_URL) } - protected val PI_08_LIGHT by lazy { download("PI.08.LIGHT.fits", GITHUB_FITS_URL) } - protected val PI_09_LIGHT by lazy { download("PI.09.LIGHT.fits", GITHUB_FITS_URL) } - protected val PI_10_LIGHT by lazy { download("PI.10.LIGHT.fits", GITHUB_FITS_URL) } - protected val PI_BIAS by lazy { download("PI.BIAS.fits", GITHUB_FITS_URL) } - protected val PI_DARK by lazy { download("PI.DARK.fits", GITHUB_FITS_URL) } - protected val PI_FLAT by lazy { download("PI.FLAT.fits", GITHUB_FITS_URL) } - - protected val PI_FOCUS_0 by lazy { download("PI.FOCUS.0.fits", GITHUB_FITS_URL) } - protected val PI_FOCUS_10000 by lazy { download("PI.FOCUS.10000.fits", GITHUB_FITS_URL) } - protected val PI_FOCUS_20000 by lazy { download("PI.FOCUS.20000.fits", GITHUB_FITS_URL) } - protected val PI_FOCUS_30000 by lazy { download("PI.FOCUS.30000.fits", GITHUB_FITS_URL) } - protected val PI_FOCUS_100000 by lazy { download("PI.FOCUS.100000.fits", GITHUB_FITS_URL) } + protected val STAR_FOCUS_1 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.1.fits") } + protected val STAR_FOCUS_2 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.2.fits") } + protected val STAR_FOCUS_3 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.3.fits") } + protected val STAR_FOCUS_4 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.4.fits") } + protected val STAR_FOCUS_5 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.5.fits") } + protected val STAR_FOCUS_6 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.6.fits") } + protected val STAR_FOCUS_7 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.7.fits") } + protected val STAR_FOCUS_8 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.8.fits") } + protected val STAR_FOCUS_9 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.9.fits") } + protected val STAR_FOCUS_10 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.10.fits") } + protected val STAR_FOCUS_11 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.11.fits") } + protected val STAR_FOCUS_12 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.12.fits") } + protected val STAR_FOCUS_13 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.13.fits") } + protected val STAR_FOCUS_14 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.14.fits") } + protected val STAR_FOCUS_15 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.15.fits") } + protected val STAR_FOCUS_16 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.16.fits") } + protected val STAR_FOCUS_17 by lazy { download("$GITHUB_FITS_URL/STAR.FOCUS.17.fits") } + + protected val PI_01_LIGHT by lazy { download("$GITHUB_FITS_URL/PI.01.LIGHT.fits") } + protected val PI_02_LIGHT by lazy { download("$GITHUB_FITS_URL/PI.02.LIGHT.fits") } + protected val PI_03_LIGHT by lazy { download("$GITHUB_FITS_URL/PI.03.LIGHT.fits") } + protected val PI_04_LIGHT by lazy { download("$GITHUB_FITS_URL/PI.04.LIGHT.fits") } + protected val PI_05_LIGHT by lazy { download("$GITHUB_FITS_URL/PI.05.LIGHT.fits") } + protected val PI_06_LIGHT by lazy { download("$GITHUB_FITS_URL/PI.06.LIGHT.fits") } + protected val PI_07_LIGHT by lazy { download("$GITHUB_FITS_URL/PI.07.LIGHT.fits") } + protected val PI_08_LIGHT by lazy { download("$GITHUB_FITS_URL/PI.08.LIGHT.fits") } + protected val PI_09_LIGHT by lazy { download("$GITHUB_FITS_URL/PI.09.LIGHT.fits") } + protected val PI_10_LIGHT by lazy { download("$GITHUB_FITS_URL/PI.10.LIGHT.fits") } + protected val PI_BIAS by lazy { download("$GITHUB_FITS_URL/PI.BIAS.fits") } + protected val PI_DARK by lazy { download("$GITHUB_FITS_URL/PI.DARK.fits") } + protected val PI_FLAT by lazy { download("$GITHUB_FITS_URL/PI.FLAT.fits") } + + protected val PI_FOCUS_0 by lazy { download("$GITHUB_FITS_URL/PI.FOCUS.0.fits") } + protected val PI_FOCUS_10000 by lazy { download("$GITHUB_FITS_URL/PI.FOCUS.10000.fits") } + protected val PI_FOCUS_20000 by lazy { download("$GITHUB_FITS_URL/PI.FOCUS.20000.fits") } + protected val PI_FOCUS_30000 by lazy { download("$GITHUB_FITS_URL/PI.FOCUS.30000.fits") } + protected val PI_FOCUS_100000 by lazy { download("$GITHUB_FITS_URL/PI.FOCUS.100000.fits") } private val afterEach = AfterEach() @@ -147,24 +147,24 @@ abstract class AbstractFitsAndXisfTest : StringSpec() { return path to md5 } - protected fun ByteArray.md5(): String { - return toByteString().md5().hex() - } + protected fun ByteArray.md5() = toByteString().md5().hex() - protected fun Path.md5(): String { - return readBytes().md5() - } + protected fun Path.md5() = readBytes().md5() - protected fun download(name: String, baseUrl: String): Path { - return synchronize(name) { - val path = Path.of(System.getProperty("java.io.tmpdir"), name) + protected val String.extensionFromUrl + get() = if (endsWith(".fits", true)) "fits" + else if (endsWith(".xisf", true)) "xisf" + else "" - if (!path.exists() || path.fileSize() <= 0L) { - val request = Request.Builder() - .get() - .url("$baseUrl/$name") - .build() + protected fun download(url: String, extension: String = url.extensionFromUrl): Path { + require(extension.isNotBlank()) + + return synchronize(url) { + val name = url.toByteArray().md5() + val path = Path.of(System.getProperty("java.io.tmpdir"), "$name.$extension") + if (!path.exists() || path.fileSize() <= 0L) { + val request = Request.Builder().get().url(url).build() val call = HTTP_CLIENT.newCall(request) call.execute().use { From 8b2a38def2a62e87629fe785040900be02de87b6 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sun, 14 Jul 2024 13:18:09 -0300 Subject: [PATCH 037/104] [api]: Use Regex find method instead of matchEntire --- .../alpaca/discovery/AlpacaDiscoveryProtocol.kt | 4 ++-- .../platesolver/LocalAstrometryNetPlateSolver.kt | 16 ++++++++-------- .../platesolver/PixInsightPlateSolver.kt | 2 +- .../kotlin/nebulosa/siril/command/PlateSolve.kt | 8 ++++---- .../nebulosa/skycatalog/stellarium/Nebula.kt | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/nebulosa-alpaca-discovery-protocol/src/main/kotlin/nebulosa/alpaca/discovery/AlpacaDiscoveryProtocol.kt b/nebulosa-alpaca-discovery-protocol/src/main/kotlin/nebulosa/alpaca/discovery/AlpacaDiscoveryProtocol.kt index 4fd35fd1e..f4ebbb2d4 100644 --- a/nebulosa-alpaca-discovery-protocol/src/main/kotlin/nebulosa/alpaca/discovery/AlpacaDiscoveryProtocol.kt +++ b/nebulosa-alpaca-discovery-protocol/src/main/kotlin/nebulosa/alpaca/discovery/AlpacaDiscoveryProtocol.kt @@ -84,7 +84,7 @@ class AlpacaDiscoveryProtocol : Runnable, Closeable { } val message = packet.data.decodeToString(0, packet.length) - val port = ALPACA_PORT_REGEX.matchEntire(message)?.groupValues?.get(1)?.toIntOrNull() ?: continue + val port = ALPACA_PORT_REGEX.find(message)?.groupValues?.get(1)?.toIntOrNull() ?: continue LOG.info("server found at {}:{}", packet.address, port) listeners.forEach { it.onServerFound(packet.address, port) } } @@ -100,7 +100,7 @@ class AlpacaDiscoveryProtocol : Runnable, Closeable { private const val ALPACA_DISCOVERY_MESSAGE = "alpacadiscovery1" - @JvmStatic private val ALPACA_PORT_REGEX = Regex("\\{\"AlpacaPort\":(\\d+)\\}") + @JvmStatic private val ALPACA_PORT_REGEX = Regex("\\{\"AlpacaPort\":(\\d+)}") @JvmStatic private val LOG = loggerFor() } } diff --git a/nebulosa-astrometrynet/src/main/kotlin/nebulosa/astrometrynet/platesolver/LocalAstrometryNetPlateSolver.kt b/nebulosa-astrometrynet/src/main/kotlin/nebulosa/astrometrynet/platesolver/LocalAstrometryNetPlateSolver.kt index 2cdda406a..03b14705e 100644 --- a/nebulosa-astrometrynet/src/main/kotlin/nebulosa/astrometrynet/platesolver/LocalAstrometryNetPlateSolver.kt +++ b/nebulosa-astrometrynet/src/main/kotlin/nebulosa/astrometrynet/platesolver/LocalAstrometryNetPlateSolver.kt @@ -99,32 +99,32 @@ data class LocalAstrometryNetPlateSolver(private val executablePath: Path) : Pla private const val NUMBER_REGEX = "([\\d.+-]+)" - @JvmStatic private val FIELD_CENTER_REGEX = Regex(".*Field center: \\(RA,Dec\\) = \\($NUMBER_REGEX, $NUMBER_REGEX\\).*") - @JvmStatic private val FIELD_SIZE_REGEX = Regex(".*Field size: $NUMBER_REGEX x $NUMBER_REGEX arcminutes.*") - @JvmStatic private val FIELD_ROTATION_REGEX = Regex(".*Field rotation angle: up is $NUMBER_REGEX degrees.*") - @JvmStatic private val PIXEL_SCALE_REGEX = Regex(".*pixel scale $NUMBER_REGEX arcsec/pix.*") + @JvmStatic private val FIELD_CENTER_REGEX = Regex("Field center: \\(RA,Dec\\) = \\($NUMBER_REGEX, $NUMBER_REGEX\\)") + @JvmStatic private val FIELD_SIZE_REGEX = Regex("Field size: $NUMBER_REGEX x $NUMBER_REGEX arcminutes") + @JvmStatic private val FIELD_ROTATION_REGEX = Regex("Field rotation angle: up is $NUMBER_REGEX degrees") + @JvmStatic private val PIXEL_SCALE_REGEX = Regex("pixel scale $NUMBER_REGEX arcsec/pix") @JvmStatic private fun fieldCenter(line: String): DoubleArray? { - return FIELD_CENTER_REGEX.matchEntire(line) + return FIELD_CENTER_REGEX.find(line) ?.let { doubleArrayOf(it.groupValues[1].toDouble().deg, it.groupValues[2].toDouble().deg) } } @JvmStatic private fun fieldSize(line: String): DoubleArray? { - return FIELD_SIZE_REGEX.matchEntire(line) + return FIELD_SIZE_REGEX.find(line) ?.let { doubleArrayOf(it.groupValues[1].toDouble().arcmin, it.groupValues[2].toDouble().arcmin) } } @JvmStatic private fun fieldRotation(line: String): Angle? { - return FIELD_ROTATION_REGEX.matchEntire(line) + return FIELD_ROTATION_REGEX.find(line) ?.let { it.groupValues[1].toDouble().deg } } @JvmStatic private fun pixelScale(line: String): Angle? { - return PIXEL_SCALE_REGEX.matchEntire(line) + return PIXEL_SCALE_REGEX.find(line) ?.let { it.groupValues[1].toDouble().arcsec } } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt index 22d73486f..34b87aa09 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt @@ -35,7 +35,7 @@ data class PixInsightPlateSolver( .use { it.runSync(runner) } if (solver.success) { - val m = ROTATION_REGEX.find(solver.astrometricSolutionSummary, 0) + val m = ROTATION_REGEX.find(solver.astrometricSolutionSummary) val rotation = m?.groupValues?.get(1)?.toDoubleOrNull() ?: 0.0 return PlateSolution( diff --git a/nebulosa-siril/src/main/kotlin/nebulosa/siril/command/PlateSolve.kt b/nebulosa-siril/src/main/kotlin/nebulosa/siril/command/PlateSolve.kt index df72d7bd3..20b39c4b5 100644 --- a/nebulosa-siril/src/main/kotlin/nebulosa/siril/command/PlateSolve.kt +++ b/nebulosa-siril/src/main/kotlin/nebulosa/siril/command/PlateSolve.kt @@ -104,7 +104,7 @@ data class PlateSolve( } private fun String.matchesOrientation(): Boolean { - val m = ORIENTATION_REGEX.matchEntire(this) ?: return false + val m = ORIENTATION_REGEX.find(this) ?: return false orientation = m.groupValues[1].toDouble().deg parity = if ("flipped" in this) Parity.FLIPPED else Parity.NORMAL return true @@ -120,13 +120,13 @@ data class PlateSolve( } private fun String.matchesResolution(): Boolean { - val m = RESOLUTION_REGEX.matchEntire(this) ?: return false + val m = RESOLUTION_REGEX.find(this) ?: return false resolution = m.groupValues[1].toDouble().arcsec return true } private fun String.matchesFOV(): Boolean { - val m = FOV_REGEX.matchEntire(this) ?: return false + val m = FOV_REGEX.find(this) ?: return false val (_, width, height) = m.groupValues fovWidth = width.parseFovInDHMS() fovHeight = height.parseFovInDHMS() @@ -134,7 +134,7 @@ data class PlateSolve( } private fun String.matchesImageCenter(): Boolean { - val m = IMAGE_CENTER_REGEX.matchEntire(this) ?: return false + val m = IMAGE_CENTER_REGEX.find(this) ?: return false val (_, alpha, delta) = m.groupValues imageCenterRA = alpha.hours imageCenterDEC = delta.deg diff --git a/nebulosa-skycatalog-stellarium/src/main/kotlin/nebulosa/skycatalog/stellarium/Nebula.kt b/nebulosa-skycatalog-stellarium/src/main/kotlin/nebulosa/skycatalog/stellarium/Nebula.kt index db16bb05e..7969817ad 100644 --- a/nebulosa-skycatalog-stellarium/src/main/kotlin/nebulosa/skycatalog/stellarium/Nebula.kt +++ b/nebulosa-skycatalog-stellarium/src/main/kotlin/nebulosa/skycatalog/stellarium/Nebula.kt @@ -132,7 +132,7 @@ class Nebula : SkyCatalog(94661) { companion object { - @JvmStatic private val DSO_NAME_REGEX = Regex(".*_\\(\"(.*?)\"\\).*") + @JvmStatic private val DSO_NAME_REGEX = Regex("_\\(\"(.*?)\"\\)") @Suppress("NOTHING_TO_INLINE") private inline fun BufferedSource.readString(): String { @@ -154,7 +154,7 @@ class Nebula : SkyCatalog(94661) { val prefix = prefixFor(line.substring(0..4).trim()) val id = line.substring(5..19).trim() - val name = DSO_NAME_REGEX.matchEntire(line.substring(20))?.groupValues?.get(1) ?: continue + val name = DSO_NAME_REGEX.find(line.substring(20))?.groupValues?.get(1) ?: continue val key = if (prefix.isEmpty()) id else "$prefix$id" names.add(Name(key, name)) } From d792603d60f259a90b7271b131ad09484c78a6d2 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sun, 14 Jul 2024 13:18:47 -0300 Subject: [PATCH 038/104] [api]: Use toRealPath method on tests --- api/src/test/kotlin/APITest.kt | 2 +- .../src/test/kotlin/LibAstrometryNetTest.kt | 2 +- nebulosa-siril/src/test/kotlin/SirilTest.kt | 2 +- nebulosa-watney/src/test/kotlin/QuadDatabaseTest.kt | 3 +-- nebulosa-watney/src/test/kotlin/WatnetPlateSolverTest.kt | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/api/src/test/kotlin/APITest.kt b/api/src/test/kotlin/APITest.kt index 0166af1d2..b170d126c 100644 --- a/api/src/test/kotlin/APITest.kt +++ b/api/src/test/kotlin/APITest.kt @@ -166,7 +166,7 @@ class APITest : StringSpec() { private const val FOCUSER_NAME = "ZWO Focuser (1)" @JvmStatic private val EXPOSURE_TIME = Duration.ofSeconds(5) - @JvmStatic private val CAPTURES_PATH = Path.of("/home/tiagohm/Git/nebulosa/data/captures") + @JvmStatic private val CAPTURES_PATH = Path.of("../data/captures").toRealPath() @JvmStatic private val STAR_DETECTION_OPTIONS = StarDetectionRequest(executablePath = Path.of("astap")) diff --git a/nebulosa-astrometrynet-jna/src/test/kotlin/LibAstrometryNetTest.kt b/nebulosa-astrometrynet-jna/src/test/kotlin/LibAstrometryNetTest.kt index c382f5ae8..d9466c71b 100644 --- a/nebulosa-astrometrynet-jna/src/test/kotlin/LibAstrometryNetTest.kt +++ b/nebulosa-astrometrynet-jna/src/test/kotlin/LibAstrometryNetTest.kt @@ -22,7 +22,7 @@ class LibAstrometryNetTest : StringSpec(), Solver.RecordMatchCallback { val lib = LibAstrometryNet.INSTANCE // http://data.astrometry.net/ - val indexDir = Path.of("/home/tiagohm/Downloads/Index Files") + val indexDir = Path.of("~/Downloads/Index Files").toRealPath() "structure sizes" { val tan = Tan.ByValue() diff --git a/nebulosa-siril/src/test/kotlin/SirilTest.kt b/nebulosa-siril/src/test/kotlin/SirilTest.kt index 7da243822..b28545f92 100644 --- a/nebulosa-siril/src/test/kotlin/SirilTest.kt +++ b/nebulosa-siril/src/test/kotlin/SirilTest.kt @@ -24,7 +24,7 @@ class SirilTest : AbstractFitsAndXisfTest() { val executablePath = Path.of("siril-cli") "live stacking" { - val workingDirectory = Path.of("/home/tiagohm/Git/nebulosa/data/siril") + val workingDirectory = Path.of("../data/siril").toRealPath() SirilLiveStacker(executablePath, workingDirectory).use { it.start() diff --git a/nebulosa-watney/src/test/kotlin/QuadDatabaseTest.kt b/nebulosa-watney/src/test/kotlin/QuadDatabaseTest.kt index 30525a065..b9762074f 100644 --- a/nebulosa-watney/src/test/kotlin/QuadDatabaseTest.kt +++ b/nebulosa-watney/src/test/kotlin/QuadDatabaseTest.kt @@ -14,12 +14,11 @@ import nebulosa.watney.platesolver.quad.CompactQuadDatabase import nebulosa.watney.platesolver.quad.QuadDatabaseCellFileIndex import java.nio.file.Path -@Suppress("NestedLambdaShadowedImplicitParameter") @EnabledIf(NonGitHubOnlyCondition::class) class QuadDatabaseTest : StringSpec() { init { - val quadDir = Path.of("/home/tiagohm/Downloads/watneyqdb") + val quadDir = Path.of("~/Downloads/watneyqdb").toRealPath() "cell index file" { val source = Path.of("$quadDir", "gaia2-00-07-20.qdbindex") diff --git a/nebulosa-watney/src/test/kotlin/WatnetPlateSolverTest.kt b/nebulosa-watney/src/test/kotlin/WatnetPlateSolverTest.kt index ab76a4cee..7ea19313a 100644 --- a/nebulosa-watney/src/test/kotlin/WatnetPlateSolverTest.kt +++ b/nebulosa-watney/src/test/kotlin/WatnetPlateSolverTest.kt @@ -17,7 +17,7 @@ import java.nio.file.Path class WatnetPlateSolverTest : AbstractFitsAndXisfTest() { init { - val quadDir = Path.of("/home/tiagohm/Downloads/watneyqdb") + val quadDir = Path.of("~/Downloads/watneyqdb").toRealPath() val quadDatabase = CompactQuadDatabase(quadDir) val solver = WatneyPlateSolver(quadDatabase) From a04fa652242e860ace5d3c086907e8ad0dcc46b5 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sun, 14 Jul 2024 13:33:37 -0300 Subject: [PATCH 039/104] [api]: Prevent start PixInsight with slot 0 --- .../main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt index 3954d1bad..1ab52282f 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightHelper.kt @@ -1,12 +1,13 @@ package nebulosa.pixinsight.script import java.nio.file.Path +import kotlin.math.max fun startPixInsight(executablePath: Path, slot: Int): PixInsightScriptRunner { val runner = PixInsightScriptRunner(executablePath) if (!PixInsightIsRunning(slot).use { it.runSync(runner).success }) { - if (!PixInsightStartup(slot).use { it.runSync(runner).success }) { + if (!PixInsightStartup(max(1, slot)).use { it.runSync(runner).success }) { throw IllegalStateException("unable to start PixInsight") } } From 1ab274a2426ba23cbf7ca082338d54747fb3fb13 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sun, 14 Jul 2024 16:13:46 -0300 Subject: [PATCH 040/104] [api][desktop]: Support PixInsight Plate Solver --- .../api/platesolver/PlateSolverController.kt | 9 ++- .../api/platesolver/PlateSolverRequest.kt | 10 ++- .../api/platesolver/PlateSolverService.kt | 13 +++- .../api/platesolver/PlateSolverType.kt | 1 + .../src/app/alignment/alignment.component.ts | 2 +- desktop/src/app/image/image.component.html | 16 +++-- desktop/src/app/image/image.component.ts | 12 +++- .../src/app/settings/settings.component.html | 72 ++++++++++++------- .../src/app/settings/settings.component.ts | 4 +- .../src/shared/pipes/dropdown-options.pipe.ts | 6 +- desktop/src/shared/pipes/enum.pipe.ts | 4 +- desktop/src/shared/services/api.service.ts | 11 ++- .../src/shared/services/preference.service.ts | 4 +- desktop/src/shared/types/alignment.types.ts | 2 +- desktop/src/shared/types/autofocus.type.ts | 4 +- desktop/src/shared/types/image.types.ts | 3 +- desktop/src/shared/types/platesolver.types.ts | 25 +++++++ desktop/src/shared/types/settings.types.ts | 40 ----------- .../src/shared/types/stardetector.types.ts | 19 +++++ .../concurrency/cancel/CancellationToken.kt | 2 + .../platesolver/PixInsightPlateSolver.kt | 22 ++++-- .../script/AbstractPixInsightScript.kt | 2 +- .../pixinsight/script/PixInsightAlign.kt | 4 +- .../PixInsightAutomaticBackgroundExtractor.kt | 4 +- .../pixinsight/script/PixInsightCalibrate.kt | 4 +- .../script/PixInsightDetectStars.kt | 4 +- .../script/PixInsightFileFormatConversion.kt | 5 +- .../script/PixInsightImageSolver.kt | 23 ++++-- .../pixinsight/script/PixInsightIsRunning.kt | 2 +- .../script/PixInsightLRGBCombination.kt | 4 +- .../script/PixInsightLuminanceCombination.kt | 4 +- .../pixinsight/script/PixInsightPixelMath.kt | 4 +- .../pixinsight/script/PixInsightScript.kt | 2 + .../script/PixInsightScriptRunner.kt | 2 + .../pixinsight/script/PixInsightStartup.kt | 4 +- .../main/resources/pixinsight/ImageSolver.js | 70 ++++++++++++------ .../src/test/kotlin/PixInsightScriptTest.kt | 6 +- 37 files changed, 274 insertions(+), 151 deletions(-) create mode 100644 desktop/src/shared/types/platesolver.types.ts create mode 100644 desktop/src/shared/types/stardetector.types.ts diff --git a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverController.kt b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverController.kt index b21d1c08d..2d4ed2456 100644 --- a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverController.kt +++ b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverController.kt @@ -12,8 +12,8 @@ class PlateSolverController( private val plateSolverService: PlateSolverService, ) { - @PutMapping - fun solveImage( + @PutMapping("start") + fun startSolver( @RequestParam path: Path, @RequestBody @Valid solver: PlateSolverRequest, @RequestParam(required = false, defaultValue = "true") blind: Boolean, @@ -21,4 +21,9 @@ class PlateSolverController( @AngleParam(required = false, defaultValue = "0.0") centerDEC: Angle, @AngleParam(required = false, defaultValue = "4.0") radius: Angle, ) = plateSolverService.solveImage(solver, path, centerRA, centerDEC, if (blind) 0.0 else radius) + + @PutMapping("stop") + fun stopSolver() { + plateSolverService.stopSolver() + } } diff --git a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverRequest.kt b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverRequest.kt index dfd73f7d0..7dba84bbe 100644 --- a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverRequest.kt @@ -4,6 +4,8 @@ import nebulosa.astap.platesolver.AstapPlateSolver import nebulosa.astrometrynet.nova.NovaAstrometryNetService import nebulosa.astrometrynet.platesolver.LocalAstrometryNetPlateSolver import nebulosa.astrometrynet.platesolver.NovaAstrometryNetPlateSolver +import nebulosa.pixinsight.platesolver.PixInsightPlateSolver +import nebulosa.pixinsight.script.startPixInsight import nebulosa.siril.platesolver.SirilPlateSolver import okhttp3.OkHttpClient import org.hibernate.validator.constraints.time.DurationMax @@ -23,6 +25,7 @@ data class PlateSolverRequest( @JvmField val apiKey: String = "", @field:DurationMin(seconds = 0) @field:DurationMax(minutes = 5) @field:DurationUnit(ChronoUnit.SECONDS) @JvmField val timeout: Duration = Duration.ZERO, + @JvmField val slot: Int = 1, ) { fun get(httpClient: OkHttpClient? = null) = with(this) { @@ -30,11 +33,14 @@ data class PlateSolverRequest( PlateSolverType.ASTAP -> AstapPlateSolver(executablePath!!) PlateSolverType.ASTROMETRY_NET -> LocalAstrometryNetPlateSolver(executablePath!!) PlateSolverType.ASTROMETRY_NET_ONLINE -> { - val key = "$apiUrl@$apiKey" - val service = NOVA_ASTROMETRY_NET_CACHE.getOrPut(key) { NovaAstrometryNetService(apiUrl, httpClient) } + val service = NOVA_ASTROMETRY_NET_CACHE.getOrPut(apiUrl) { NovaAstrometryNetService(apiUrl, httpClient) } NovaAstrometryNetPlateSolver(service, apiKey) } PlateSolverType.SIRIL -> SirilPlateSolver(executablePath!!, focalLength, pixelSize) + PlateSolverType.PIXINSIGHT -> { + val runner = startPixInsight(executablePath!!, slot) + PixInsightPlateSolver(runner, pixelSize, 0.0, focalLength, slot) + } } } diff --git a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverService.kt b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverService.kt index aa7fbb45c..890f40922 100644 --- a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverService.kt +++ b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverService.kt @@ -2,10 +2,12 @@ package nebulosa.api.platesolver import nebulosa.api.image.ImageBucket import nebulosa.api.image.ImageSolved +import nebulosa.common.concurrency.cancel.CancellationToken import nebulosa.math.Angle import okhttp3.OkHttpClient import org.springframework.stereotype.Service import java.nio.file.Path +import java.util.concurrent.atomic.AtomicReference @Service class PlateSolverService( @@ -13,6 +15,8 @@ class PlateSolverService( private val httpClient: OkHttpClient, ) { + private val cancellationToken = AtomicReference() + fun solveImage( options: PlateSolverRequest, path: Path, centerRA: Angle, centerDEC: Angle, radius: Angle, @@ -26,5 +30,12 @@ class PlateSolverService( fun solve( options: PlateSolverRequest, path: Path, centerRA: Angle = 0.0, centerDEC: Angle = 0.0, radius: Angle = 0.0, - ) = options.get(httpClient).solve(path, null, centerRA, centerDEC, radius, options.downsampleFactor, options.timeout) + ) = CancellationToken().use { + cancellationToken.set(it) + options.get(httpClient).solve(path, null, centerRA, centerDEC, radius, options.downsampleFactor, options.timeout, it) + } + + fun stopSolver() { + cancellationToken.get()?.cancel() + } } diff --git a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverType.kt b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverType.kt index 3c85a9a86..13efe930d 100644 --- a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverType.kt +++ b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverType.kt @@ -5,4 +5,5 @@ enum class PlateSolverType { ASTROMETRY_NET, ASTROMETRY_NET_ONLINE, SIRIL, + PIXINSIGHT, } diff --git a/desktop/src/app/alignment/alignment.component.ts b/desktop/src/app/alignment/alignment.component.ts index 9079195ba..7dabe42a7 100644 --- a/desktop/src/app/alignment/alignment.component.ts +++ b/desktop/src/app/alignment/alignment.component.ts @@ -10,7 +10,7 @@ import { Angle } from '../../shared/types/atlas.types' import { Camera, EMPTY_CAMERA, EMPTY_CAMERA_START_CAPTURE, ExposureTimeUnit, updateCameraStartCaptureFromCamera } from '../../shared/types/camera.types' import { EMPTY_GUIDE_OUTPUT, GuideDirection, GuideOutput } from '../../shared/types/guider.types' import { EMPTY_MOUNT, Mount } from '../../shared/types/mount.types' -import { EMPTY_PLATE_SOLVER_REQUEST } from '../../shared/types/settings.types' +import { EMPTY_PLATE_SOLVER_REQUEST } from '../../shared/types/platesolver.types' import { deviceComparator } from '../../shared/utils/comparators' import { AppComponent } from '../app.component' import { CameraComponent } from '../camera/camera.component' diff --git a/desktop/src/app/image/image.component.html b/desktop/src/app/image/image.component.html index 9142038e3..6cdbd71d5 100644 --- a/desktop/src/app/image/image.component.html +++ b/desktop/src/app/image/image.component.html @@ -400,7 +400,7 @@
@@ -431,7 +431,7 @@
Radius (ยฐ)
- @if (solver.type === 'SIRIL') { + @if (solver.type === 'SIRIL' || solver.type === 'PIXINSIGHT') {
+ diff --git a/desktop/src/app/image/image.component.ts b/desktop/src/app/image/image.component.ts index 3fa3510ca..c1af659cf 100644 --- a/desktop/src/app/image/image.component.ts +++ b/desktop/src/app/image/image.component.ts @@ -500,7 +500,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } get canPlateSolve() { - return this.solver.type !== 'SIRIL' || (this.solver.focalLength > 0 && this.solver.pixelSize > 0) + return (this.solver.type !== 'SIRIL' && this.solver.type !== 'PIXINSIGHT') || (this.solver.focalLength > 0 && this.solver.pixelSize > 0) } private readonly liveStackingMenuItem: MenuItem = { @@ -1227,7 +1227,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } } - async solveImage() { + async solverStart() { const path = this.imagePath if (path) { @@ -1235,7 +1235,9 @@ export class ImageComponent implements AfterViewInit, OnDestroy { try { const solver = this.preference.plateSolverRequest(this.solver.type).get() - const solved = await this.api.solveImage(solver, path, this.solver.blind, this.solver.centerRA, this.solver.centerDEC, this.solver.radius) + solver.pixelSize = this.solver.pixelSize + solver.focalLength = this.solver.focalLength + const solved = await this.api.solverStart(solver, path, this.solver.blind, this.solver.centerRA, this.solver.centerDEC, this.solver.radius) this.savePreference() this.updateImageSolved(solved) @@ -1251,6 +1253,10 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } } + solverStop() { + return this.api.solverStop() + } + private updateImageSolved(solved?: ImageSolved) { Object.assign(this.solver.solved, solved ?? EMPTY_IMAGE_SOLVED) this.annotationMenuItem.disabled = !this.solver.solved.solved diff --git a/desktop/src/app/settings/settings.component.html b/desktop/src/app/settings/settings.component.html index c63e3bc61..a739d2731 100644 --- a/desktop/src/app/settings/settings.component.html +++ b/desktop/src/app/settings/settings.component.html @@ -108,32 +108,52 @@
} -
- - - - -
-
- - - - -
+ @if (plateSolverType !== 'PIXINSIGHT') { +
+ + + + +
+
+ + + + +
+ } + @if (plateSolverType === 'PIXINSIGHT') { +
+ + + + +
+ }
(`plate-solver?${query}`, solver) + return this.http.put(`plate-solver/start?${query}`, solver) + } + + solverStop() { + return this.http.put('plate-solver/stop') } // AUTO FOCUS diff --git a/desktop/src/shared/services/preference.service.ts b/desktop/src/shared/services/preference.service.ts index 5d30d03a4..c410e4917 100644 --- a/desktop/src/shared/services/preference.service.ts +++ b/desktop/src/shared/services/preference.service.ts @@ -9,10 +9,12 @@ import { Focuser, FocuserPreference } from '../types/focuser.types' import { ConnectionDetails, Equipment, HomePreference } from '../types/home.types' import { EMPTY_IMAGE_PREFERENCE, FOV, ImagePreference } from '../types/image.types' import { EMPTY_MOUNT_PREFERENCE, Mount, MountPreference } from '../types/mount.types' +import { EMPTY_PLATE_SOLVER_REQUEST, PlateSolverRequest, PlateSolverType } from '../types/platesolver.types' import { Rotator, RotatorPreference } from '../types/rotator.types' import { EMPTY_SEQUENCER_PREFERENCE, SequencerPreference } from '../types/sequencer.types' -import { CameraCaptureNamingFormat, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, EMPTY_PLATE_SOLVER_REQUEST, EMPTY_STAR_DETECTION_REQUEST, PlateSolverRequest, PlateSolverType, StarDetectionRequest, StarDetectorType } from '../types/settings.types' +import { CameraCaptureNamingFormat, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT } from '../types/settings.types' import { EMPTY_STACKER_PREFERENCE, EMPTY_STACKING_REQUEST, StackerPreference, StackerType, StackingRequest } from '../types/stacker.types' +import { EMPTY_STAR_DETECTION_REQUEST, StarDetectionRequest, StarDetectorType } from '../types/stardetector.types' import { FilterWheel, WheelPreference } from '../types/wheel.types' import { Undefinable } from '../utils/types' import { LocalStorageService } from './local-storage.service' diff --git a/desktop/src/shared/types/alignment.types.ts b/desktop/src/shared/types/alignment.types.ts index 40e91d669..3752c29ab 100644 --- a/desktop/src/shared/types/alignment.types.ts +++ b/desktop/src/shared/types/alignment.types.ts @@ -1,7 +1,7 @@ import type { Angle } from './atlas.types' import type { Camera, CameraCaptureEvent, CameraStartCapture } from './camera.types' import type { GuideDirection } from './guider.types' -import type { PlateSolverRequest, PlateSolverType } from './settings.types' +import type { PlateSolverRequest, PlateSolverType } from './platesolver.types' export type Hemisphere = 'NORTHERN' | 'SOUTHERN' diff --git a/desktop/src/shared/types/autofocus.type.ts b/desktop/src/shared/types/autofocus.type.ts index ee0156c74..2e1357061 100644 --- a/desktop/src/shared/types/autofocus.type.ts +++ b/desktop/src/shared/types/autofocus.type.ts @@ -1,7 +1,7 @@ import type { Point } from 'electron' import type { CameraCaptureEvent, CameraStartCapture } from './camera.types' -import type { StarDetectionRequest } from './settings.types' -import { EMPTY_STAR_DETECTION_REQUEST } from './settings.types' +import type { StarDetectionRequest } from './stardetector.types' +import { EMPTY_STAR_DETECTION_REQUEST } from './stardetector.types' export type AutoFocusState = 'IDLE' | 'MOVING' | 'EXPOSURING' | 'EXPOSURED' | 'ANALYSING' | 'ANALYSED' | 'CURVE_FITTED' | 'FAILED' | 'FINISHED' diff --git a/desktop/src/shared/types/image.types.ts b/desktop/src/shared/types/image.types.ts index d1b4610d4..e425d26f9 100644 --- a/desktop/src/shared/types/image.types.ts +++ b/desktop/src/shared/types/image.types.ts @@ -1,7 +1,8 @@ import type { Point, Size } from 'electron' import type { Angle, AstronomicalObject, DeepSkyObject, EquatorialCoordinateJ2000, Star } from './atlas.types' import type { Camera, CameraStartCapture } from './camera.types' -import type { PlateSolverRequest, StarDetectionRequest } from './settings.types' +import type { PlateSolverRequest } from './platesolver.types' +import type { StarDetectionRequest } from './stardetector.types' export type ImageChannel = 'RED' | 'GREEN' | 'BLUE' | 'GRAY' diff --git a/desktop/src/shared/types/platesolver.types.ts b/desktop/src/shared/types/platesolver.types.ts new file mode 100644 index 000000000..e803b1a39 --- /dev/null +++ b/desktop/src/shared/types/platesolver.types.ts @@ -0,0 +1,25 @@ +export type PlateSolverType = 'ASTROMETRY_NET' | 'ASTROMETRY_NET_ONLINE' | 'ASTAP' | 'SIRIL' | 'PIXINSIGHT' + +export interface PlateSolverRequest { + type: PlateSolverType + executablePath: string + downsampleFactor: number + apiUrl: string + apiKey: string + timeout: number + slot: number + pixelSize?: number + focalLength?: number +} + +export const NOVA_ASTROMETRY_NET_URL = 'https://nova.astrometry.net/' + +export const EMPTY_PLATE_SOLVER_REQUEST: PlateSolverRequest = { + type: 'ASTAP', + executablePath: '', + downsampleFactor: 0, + apiUrl: NOVA_ASTROMETRY_NET_URL, + apiKey: '', + timeout: 300, + slot: 1, +} diff --git a/desktop/src/shared/types/settings.types.ts b/desktop/src/shared/types/settings.types.ts index c906522dd..402676bb3 100644 --- a/desktop/src/shared/types/settings.types.ts +++ b/desktop/src/shared/types/settings.types.ts @@ -1,45 +1,5 @@ import type { FrameType } from './camera.types' -export type PlateSolverType = 'ASTROMETRY_NET' | 'ASTROMETRY_NET_ONLINE' | 'ASTAP' | 'SIRIL' - -export interface PlateSolverRequest { - type: PlateSolverType - executablePath: string - downsampleFactor: number - apiUrl: string - apiKey: string - timeout: number -} - -export const EMPTY_PLATE_SOLVER_REQUEST: PlateSolverRequest = { - type: 'ASTAP', - executablePath: '', - downsampleFactor: 0, - apiUrl: 'https://nova.astrometry.net/', - apiKey: '', - timeout: 300, -} - -export type StarDetectorType = 'ASTAP' | 'PIXINSIGHT' | 'SIRIL' - -export interface StarDetectionRequest { - type: StarDetectorType - executablePath: string - timeout: number - minSNR?: number - maxStars?: number - slot: number -} - -export const EMPTY_STAR_DETECTION_REQUEST: StarDetectionRequest = { - type: 'ASTAP', - executablePath: '', - timeout: 300, - minSNR: 0, - maxStars: 0, - slot: 1, -} - export interface CameraCaptureNamingFormat { light?: string dark?: string diff --git a/desktop/src/shared/types/stardetector.types.ts b/desktop/src/shared/types/stardetector.types.ts new file mode 100644 index 000000000..d0d344c41 --- /dev/null +++ b/desktop/src/shared/types/stardetector.types.ts @@ -0,0 +1,19 @@ +export type StarDetectorType = 'ASTAP' | 'PIXINSIGHT' | 'SIRIL' + +export interface StarDetectionRequest { + type: StarDetectorType + executablePath: string + timeout: number + minSNR?: number + maxStars?: number + slot: number +} + +export const EMPTY_STAR_DETECTION_REQUEST: StarDetectionRequest = { + type: 'ASTAP', + executablePath: '', + timeout: 300, + minSNR: 0, + maxStars: 0, + slot: 1, +} diff --git a/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/cancel/CancellationToken.kt b/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/cancel/CancellationToken.kt index 837a300e4..d371b9ea0 100644 --- a/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/cancel/CancellationToken.kt +++ b/nebulosa-common/src/main/kotlin/nebulosa/common/concurrency/cancel/CancellationToken.kt @@ -90,6 +90,8 @@ class CancellationToken private constructor(private val completable: Completable if (!isDone) { completable?.complete(CancellationSource.Close) } + + unlistenAll() } companion object { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt index 34b87aa09..8625a6a65 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/platesolver/PixInsightPlateSolver.kt @@ -1,8 +1,10 @@ package nebulosa.pixinsight.platesolver +import nebulosa.common.concurrency.cancel.CancellationListener import nebulosa.common.concurrency.cancel.CancellationToken import nebulosa.image.Image import nebulosa.math.Angle +import nebulosa.math.deg import nebulosa.math.toArcsec import nebulosa.pixinsight.script.PixInsightImageSolver import nebulosa.pixinsight.script.PixInsightScript @@ -16,12 +18,12 @@ data class PixInsightPlateSolver( private val runner: PixInsightScriptRunner, private val pixelSize: Double, // ยตm private val resolution: Angle = 0.0, - private val focalDistance: Double = 0.0, // mm + private val focalLength: Double = 0.0, // mm private val slot: Int = PixInsightScript.UNSPECIFIED_SLOT, ) : PlateSolver { init { - require(resolution > 0.0 || focalDistance > 0.0) { "resolution or focalDistance are required" } + require(resolution > 0.0 || focalLength > 0.0) { "resolution or focalDistance are required" } } override fun solve( @@ -31,12 +33,20 @@ data class PixInsightPlateSolver( cancellationToken: CancellationToken ): PlateSolution { require(path != null) { "path must be provided" } - val solver = PixInsightImageSolver(slot, path, centerRA, centerDEC, pixelSize, resolution.toArcsec, focalDistance) - .use { it.runSync(runner) } + + val script = PixInsightImageSolver(slot, path, centerRA, centerDEC, pixelSize, resolution.toArcsec, focalLength, timeout, cancellationToken) + val cancellationListener = CancellationListener { runner.abort(script) } + + val solver = try { + cancellationToken.listen(cancellationListener) + script.use { it.runSync(runner) } + } finally { + cancellationToken.unlisten(cancellationListener) + } if (solver.success) { val m = ROTATION_REGEX.find(solver.astrometricSolutionSummary) - val rotation = m?.groupValues?.get(1)?.toDoubleOrNull() ?: 0.0 + val rotation = m?.groupValues?.get(1)?.toDoubleOrNull()?.deg ?: 0.0 return PlateSolution( true, rotation, solver.resolution, @@ -51,6 +61,6 @@ data class PixInsightPlateSolver( companion object { - @JvmStatic val ROTATION_REGEX = Regex("Rotation\\s*\\.+\\s*([\\d.]+)") + @JvmStatic val ROTATION_REGEX = Regex("Rotation\\s*\\.+\\s*([-+\\d.]+)") } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt index 5c0c22c04..a0de3c09d 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/AbstractPixInsightScript.kt @@ -67,7 +67,7 @@ abstract class AbstractPixInsightScript : PixInsigh } @JvmStatic - internal fun PixInsightScript<*>.execute(slot: Int, scriptPath: Path, data: Any?): String { + internal fun PixInsightScript<*>.execute(scriptPath: Path, data: Any?, slot: Int = this.slot): String { LOG.info("{} will be executed. slot={}, script={}, data={}", this::class.simpleName, slot, scriptPath, data) return buildString { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt index 64b39851c..a96fedaac 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAlign.kt @@ -8,7 +8,7 @@ import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream data class PixInsightAlign( - private val slot: Int, + override val slot: Int, private val workingDirectory: Path, private val referencePath: Path, private val targetPath: Path, @@ -59,7 +59,7 @@ data class PixInsightAlign( resource("pixinsight/Align.js")!!.transferAndClose(scriptPath.outputStream()) } - override val arguments = listOf("-x=${execute(slot, scriptPath, Input(referencePath, targetPath, workingDirectory, statusPath))}") + override val arguments = listOf("-x=${execute(scriptPath, Input(referencePath, targetPath, workingDirectory, statusPath))}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt index 3410e084f..7bd437755 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightAutomaticBackgroundExtractor.kt @@ -9,7 +9,7 @@ import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream data class PixInsightAutomaticBackgroundExtractor( - private val slot: Int, + override val slot: Int, private val targetPath: Path, private val outputPath: Path, ) : AbstractPixInsightScript() { @@ -39,7 +39,7 @@ data class PixInsightAutomaticBackgroundExtractor( resource("pixinsight/ABE.js")!!.transferAndClose(scriptPath.outputStream()) } - override val arguments = listOf("-x=${execute(slot, scriptPath, Input(targetPath, outputPath, statusPath))}") + override val arguments = listOf("-x=${execute(scriptPath, Input(targetPath, outputPath, statusPath))}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt index 5d541d659..21a29ca21 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightCalibrate.kt @@ -8,7 +8,7 @@ import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream data class PixInsightCalibrate( - private val slot: Int, + override val slot: Int, private val workingDirectory: Path, private val targetPath: Path, private val darkPath: Path? = null, @@ -49,7 +49,7 @@ data class PixInsightCalibrate( } private val input = Input(targetPath, workingDirectory, statusPath, darkPath, flatPath, biasPath, compress, use32Bit) - override val arguments = listOf("-x=${execute(slot, scriptPath, input)}") + override val arguments = listOf("-x=${execute(scriptPath, input)}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt index ce1d0472a..6f45c2a92 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightDetectStars.kt @@ -11,7 +11,7 @@ import kotlin.io.path.outputStream import kotlin.io.path.readText data class PixInsightDetectStars( - private val slot: Int, + override val slot: Int, private val targetPath: Path, private val minSNR: Double = 0.0, private val invert: Boolean = false, @@ -62,7 +62,7 @@ data class PixInsightDetectStars( resource("pixinsight/DetectStars.js")!!.transferAndClose(scriptPath.outputStream()) } - override val arguments = listOf("-x=${execute(slot, scriptPath, Input(targetPath, statusPath, minSNR, invert))}") + override val arguments = listOf("-x=${execute(scriptPath, Input(targetPath, statusPath, minSNR, invert))}") override fun processOnComplete(exitCode: Int): Output { val timeoutInMillis = timeout.toMillis() diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt index e3c105397..9192893f0 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightFileFormatConversion.kt @@ -8,7 +8,7 @@ import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream data class PixInsightFileFormatConversion( - private val slot: Int, + override val slot: Int, private val inputPath: Path, private val outputPath: Path, ) : AbstractPixInsightScript() { @@ -38,8 +38,7 @@ data class PixInsightFileFormatConversion( resource("pixinsight/FileFormatConversion.js")!!.transferAndClose(scriptPath.outputStream()) } - override val arguments = - listOf("-x=${execute(slot, scriptPath, Input(inputPath, outputPath, statusPath))}") + override val arguments = listOf("-x=${execute(scriptPath, Input(inputPath, outputPath, statusPath))}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt index e9c4cf311..70ae33a5a 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt @@ -1,22 +1,28 @@ package nebulosa.pixinsight.script +import nebulosa.common.concurrency.cancel.CancellationToken import nebulosa.io.resource import nebulosa.io.transferAndClose import nebulosa.math.Angle import nebulosa.math.toDegrees import java.nio.file.Files import java.nio.file.Path +import java.time.Duration import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream +import kotlin.math.max +import kotlin.math.min data class PixInsightImageSolver( - private val slot: Int, + override val slot: Int, private val targetPath: Path, private val centerRA: Angle, private val centerDEC: Angle, private val pixelSize: Double = 0.0, // ยตm private val resolution: Double = 0.0, // arcsec/px - private val focalDistance: Double = 0.0, // mm + private val focalLength: Double = 0.0, // mm + private val timeout: Duration = Duration.ZERO, + private val cancellationToken: CancellationToken = CancellationToken.NONE, ) : AbstractPixInsightScript() { private data class Input( @@ -26,7 +32,7 @@ data class PixInsightImageSolver( @JvmField val centerDEC: Double, // deg @JvmField val pixelSize: Double = 0.0, @JvmField val resolution: Double = 0.0, - @JvmField val focalDistance: Double = 0.0, + @JvmField val focalLength: Double = 0.0, ) data class Output( @@ -36,7 +42,7 @@ data class PixInsightImageSolver( @JvmField val declination: Angle = 0.0, @JvmField val resolution: Angle = 0.0, @JvmField val pixelSize: Double = 0.0, - @JvmField val focalDistance: Double = 0.0, + @JvmField val focalLength: Double = 0.0, @JvmField val width: Angle = 0.0, @JvmField val height: Angle = 0.0, // @JvmField val rotation: Angle = 0.0, @@ -58,12 +64,15 @@ data class PixInsightImageSolver( resource("pixinsight/ImageSolver.js")!!.transferAndClose(scriptPath.outputStream()) } - private val input = Input(targetPath, statusPath, centerRA.toDegrees, centerDEC.toDegrees, pixelSize, resolution, focalDistance) - override val arguments = listOf("-x=${execute(slot, scriptPath, input)}") + private val input = Input(targetPath, statusPath, centerRA.toDegrees, centerDEC.toDegrees, pixelSize, resolution, focalLength) + override val arguments = listOf("-x=${execute(scriptPath, input)}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { - repeat(30) { + val seconds = timeout.toSeconds().toInt() + + repeat(max(30, min(seconds, 300))) { + if (cancellationToken.isCancelled) return@repeat statusPath.parseStatus()?.also { return it } ?: Thread.sleep(1000) } } diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightIsRunning.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightIsRunning.kt index 3f2ef4afc..2ea09cc5b 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightIsRunning.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightIsRunning.kt @@ -3,7 +3,7 @@ package nebulosa.pixinsight.script import nebulosa.log.debug import nebulosa.log.loggerFor -data class PixInsightIsRunning(private val slot: Int) : AbstractPixInsightScript() { +data class PixInsightIsRunning(override val slot: Int) : AbstractPixInsightScript() { data class Output( override val success: Boolean, diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt index 7d1384a87..3af4274c8 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLRGBCombination.kt @@ -9,7 +9,7 @@ import kotlin.io.path.outputStream @Suppress("ArrayInDataClass") data class PixInsightLRGBCombination( - private val slot: Int, + override val slot: Int, private val outputPath: Path, private val luminancePath: Path? = null, private val redPath: Path? = null, @@ -50,7 +50,7 @@ data class PixInsightLRGBCombination( } private val input = Input(outputPath, statusPath, luminancePath, redPath, greenPath, bluePath, weights) - override val arguments = listOf("-x=${execute(slot, scriptPath, input)}") + override val arguments = listOf("-x=${execute(scriptPath, input)}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt index d300a6314..3ae858446 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightLuminanceCombination.kt @@ -8,7 +8,7 @@ import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream data class PixInsightLuminanceCombination( - private val slot: Int, + override val slot: Int, private val outputPath: Path, private val luminancePath: Path, private val targetPath: Path, @@ -42,7 +42,7 @@ data class PixInsightLuminanceCombination( } private val input = Input(outputPath, statusPath, luminancePath, targetPath, 1.0) - override val arguments = listOf("-x=${execute(slot, scriptPath, input)}") + override val arguments = listOf("-x=${execute(scriptPath, input)}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt index 875957535..30b4820e3 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightPixelMath.kt @@ -9,7 +9,7 @@ import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream data class PixInsightPixelMath( - private val slot: Int, + override val slot: Int, private val inputPaths: List, private val outputPath: Path, private val expressionRK: String? = null, @@ -46,7 +46,7 @@ data class PixInsightPixelMath( } private val input = Input(statusPath, inputPaths, outputPath, expressionRK, expressionG, expressionB) - override val arguments = listOf("-x=${execute(slot, scriptPath, input)}") + override val arguments = listOf("-x=${execute(scriptPath, input)}") override fun processOnComplete(exitCode: Int): Output { if (exitCode == 0) { diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScript.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScript.kt index 2434b72da..52811810d 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScript.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScript.kt @@ -6,6 +6,8 @@ import java.util.concurrent.Future sealed interface PixInsightScript : Future, Closeable { + val slot: Int + sealed interface Output { val success: Boolean diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScriptRunner.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScriptRunner.kt index 6becf6d2b..d7a6e7a7a 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScriptRunner.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightScriptRunner.kt @@ -18,6 +18,8 @@ data class PixInsightScriptRunner(private val executablePath: Path) { script.startCommandLine(commandLine) } + fun abort(script: PixInsightScript<*>) = Unit + companion object { @JvmStatic private val DEFAULT_ARGS = arrayOf("--automation-mode", "--no-startup-scripts") diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightStartup.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightStartup.kt index 41968725a..713170b19 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightStartup.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightStartup.kt @@ -8,7 +8,7 @@ import kotlin.io.path.deleteIfExists import kotlin.io.path.outputStream import kotlin.io.path.readText -data class PixInsightStartup(private val slot: Int) : AbstractPixInsightScript() { +data class PixInsightStartup(override val slot: Int) : AbstractPixInsightScript() { data class Output( override val success: Boolean, @@ -29,7 +29,7 @@ data class PixInsightStartup(private val slot: Int) : AbstractPixInsightScript

0) "-n=$slot" else "-n") + override val arguments = listOf("-r=${execute(scriptPath, outputPath, 0)}", if (slot > 0) "-n=$slot" else "-n") override fun beforeRun() { var count = 0 diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/ImageSolver.js b/nebulosa-pixinsight/src/main/resources/pixinsight/ImageSolver.js index 37d6f495a..9aafaa76b 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/ImageSolver.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/ImageSolver.js @@ -45,7 +45,6 @@ #include "/opt/PixInsight/src/scripts/AdP/WCSmetadata.jsh" #include "/opt/PixInsight/src/scripts/AdP/AstronomicalCatalogs.jsh" -#include "/opt/PixInsight/src/scripts/AdP/CatalogDownloader.js" function CatalogMode() { } CatalogMode.prototype.LocalText = 0 @@ -200,6 +199,17 @@ function ImageSolver() { this.config.restrictToHQStars = false this.config.tryApparentCoordinates = true + this.finished = false + + let listener = new MessageListener + listener.onMessage = function (instance, uniqueId, message) { + console.writeln("Received message: " + message) + + if (message === "ABORTED") { + this.finished = true + } + } + /* * Initializes the image solver. If the parameter prioritizeSettings is * defined and is true, the solver will use the values stored in preferences @@ -574,7 +584,7 @@ function ImageSolver() { } // This warning is now silenced. - this.showedWarningOnTruncatedInputSet = true; //false + this.showedWarningOnTruncatedInputSet = true //false this.DetectStars = function (window, metadata) { /* @@ -824,7 +834,7 @@ function ImageSolver() { let grayscaleImage = new Image grayscaleImage.assign(targetWindow.mainView.image) grayscaleImage.colorSpace = ColorSpace_HSI - grayscaleImage.selectedChannel = 2; // intensity component + grayscaleImage.selectedChannel = 2 // intensity component let workingWindow = new ImageWindow(grayscaleImage.width, grayscaleImage.height, 1/*channels*/, 32/*bits*/, true/*float*/, false/*color*/, @@ -856,7 +866,6 @@ function ImageSolver() { } this.OptimizeSolution = function (workingWindow, currentMetadata, stars) { - let finished = false let iteration = 1 let numItersWithoutImprovement = 0 let maxItersWithoutImprovement = 4 @@ -866,6 +875,10 @@ function ImageSolver() { let bestStarCount = stars.numValid let converged = false + if (this.finished) { + return + } + do { console.abortEnabled = true @@ -878,8 +891,7 @@ function ImageSolver() { if (result == null) throw "" - } - catch (ex) { + } catch (ex) { let haveException = !console.isAborted && (ex.length === undefined || ex.length > 0) if (haveException) console.criticalln("
*** Error: " + ex.toString()) @@ -892,6 +904,14 @@ function ImageSolver() { stars = this.DetectStars(workingWindow, result) + processEvents() + + if (console.abortRequested || this.finished) { + this.finished = true + console.criticalln("*** User requested abort ***") + break + } + /* * Calculate the difference between the current and previous * iterations using the displacements between the center and eight @@ -951,12 +971,13 @@ function ImageSolver() { } // Finish condition - finished = true + this.finished = true + if (converged || numItersWithoutImprovement > maxItersWithoutImprovement) { if (this.distortModel) { converged = false numItersWithoutImprovement = 0 - finished = false + this.finished = false this.distortModel = null console.noteln("* The solution with distortion model has converged. Trying to optimize it without the model.") } @@ -968,25 +989,26 @@ function ImageSolver() { else if (iteration > this.config.maxIterations) console.warningln("** Warning: Reached maximum number of iterations without convergence.") else - finished = false + this.finished = false ++iteration console.abortEnabled = true + processEvents() + if (console.abortRequested) { - finished = true + this.finished = true console.criticalln("*** User requested abort ***") } + gc(true) - } - while (!finished) + } while (!this.finished) if (converged) console.noteln(format("* Successful astrometry optimization. Score = %.3f", bestScore)) else console.warningln(format("** Partial astrometry optimization. Score = %.3f", bestScore)) - console.writeln() return bestMetadata } @@ -1143,7 +1165,7 @@ function ImageSolver() { if (d < this.psfMinimumDistance) this.psfMinimumDistance = d } - this.psfMinimumDistance = Math.max(2, Math.trunc(0.75 * (this.psfMinimumDistance - 2))); // StarDetector inflates detection regions + this.psfMinimumDistance = Math.max(2, Math.trunc(0.75 * (this.psfMinimumDistance - 2))) // StarDetector inflates detection regions this.psfSearchRadius = 1.0 * this.psfMinimumDistance console.writeln(format("* Star matching tolerance: %d px", this.psfMinimumDistance)) console.flush() @@ -1184,13 +1206,13 @@ function ImageSolver() { xpsd.centerDec = this.metadata.dec xpsd.radius = this.metadata.resolution * radiusPx xpsd.magnitudeLow = -1.5 - xpsd.sourceLimit = 0; // do not retrieve objects, just count them. + xpsd.sourceLimit = 0 // do not retrieve objects, just count them. xpsd.exclusionFlags = GaiaFlag_NoPM xpsd.inclusionFlags = this.config.restrictToHQStars ? GaiaFlag_GoodAstrometry : 0 - xpsd.verbosity = 0; // work quietly + xpsd.verbosity = 0 // work quietly xpsd.generateTextOutput = false - const MAX_AUTOMAG_ITER = 100; // prevent a hypothetical case where the loop might stall + const MAX_AUTOMAG_ITER = 100 // prevent a hypothetical case where the loop might stall for (let m0 = 7, m1 = xpsd.databaseMagnitudeHigh, i = 0; i < MAX_AUTOMAG_ITER; ++i) { xpsd.magnitudeHigh = m xpsd.executeGlobal() @@ -1362,7 +1384,7 @@ function imageSolver() { const centerDEC = input.centerDEC const pixelSize = input.pixelSize const resolution = input.resolution // arcsec/px - const focalDistance = input.focalDistance + const focalLength = input.focalLength console.writeln("image solver started") console.writeln("targetPath=" + targetPath) @@ -1371,7 +1393,7 @@ function imageSolver() { console.writeln("centerDEC=" + centerDEC) console.writeln("pixelSize=" + pixelSize) console.writeln("resolution=" + resolution) - console.writeln("focalDistance=" + focalDistance) + console.writeln("focalLength=" + focalLength) const P = new ImageSolver @@ -1384,10 +1406,10 @@ function imageSolver() { P.metadata.ra = centerRA P.metadata.dec = centerDEC - if (focalDistance > 0) { + if (focalLength > 0) { P.metadata.useFocal = false - P.metadata.focal = focalDistance - P.metadata.resolution = pixelSize / focalDistance * 0.18 / Math.PI + P.metadata.focal = focalLength + P.metadata.resolution = pixelSize / focalLength * 0.18 / Math.PI } else { P.metadata.useFocal = false P.metadata.resolution = resolution / 3600 // deg? @@ -1402,7 +1424,7 @@ function imageSolver() { console.writeln(targetWindow.astrometricSolutionSummary()) data.resolution = P.metadata.resolution * Math.PI / 180.0 data.pixelSize = P.metadata.xpixsz - data.focalDistance = P.metadata.focal + data.focalLength = P.metadata.focal data.rightAscension = P.metadata.ra * Math.PI / 180.0 data.declination = P.metadata.dec * Math.PI / 180.0 data.imageWidth = P.metadata.width @@ -1417,6 +1439,8 @@ function imageSolver() { console.criticalln(data.errorMessage) } + data.success = !this.finished + console.writeln("image solver finished") } catch (e) { data.success = false diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt index 343a8b0c2..2e61a9a2d 100644 --- a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt @@ -143,7 +143,7 @@ class PixInsightScriptTest : AbstractFitsAndXisfTest() { with(PixInsightImageSolver(UNSPECIFIED_SLOT, path, centerRA, centerDEC, pixelSize = pixelSize, resolution = resolution) .use { it.runSync(runner) }) { success.shouldBeTrue() - this.focalDistance shouldBe (200.355 plusOrMinus 1e-5) + this.focalLength shouldBe (200.355 plusOrMinus 1e-5) this.pixelSize shouldBe (6.58 plusOrMinus 1e-2) this.resolution.toArcsec shouldBe (6.774 plusOrMinus 1e-3) rightAscension.formatHMS() shouldBe "06h40m51.8s" @@ -154,10 +154,10 @@ class PixInsightScriptTest : AbstractFitsAndXisfTest() { imageHeight.roundToInt() shouldBeExactly 526 } - with(PixInsightImageSolver(UNSPECIFIED_SLOT, path, centerRA, centerDEC, pixelSize = pixelSize, focalDistance = focalDistance) + with(PixInsightImageSolver(UNSPECIFIED_SLOT, path, centerRA, centerDEC, pixelSize = pixelSize, focalLength = focalDistance) .use { it.runSync(runner) }) { success.shouldBeTrue() - this.focalDistance shouldBe (200.355 plusOrMinus 1e-5) + this.focalLength shouldBe (200.355 plusOrMinus 1e-5) this.pixelSize shouldBe (6.58 plusOrMinus 1e-2) this.resolution.toArcsec shouldBe (6.774 plusOrMinus 1e-3) rightAscension.formatHMS() shouldBe "06h40m51.8s" From 957d5e379bbc880d7899d926aefd82bf7bb950ab Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sun, 14 Jul 2024 16:36:24 -0300 Subject: [PATCH 041/104] [api]: Support PJSR include from scripts directory on Windows --- .../script/PixInsightImageSolver.kt | 21 +++++++++++++++++++ .../main/resources/pixinsight/ImageSolver.js | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt index 70ae33a5a..174ca044b 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/script/PixInsightImageSolver.kt @@ -1,5 +1,6 @@ package nebulosa.pixinsight.script +import com.sun.jna.Platform import nebulosa.common.concurrency.cancel.CancellationToken import nebulosa.io.resource import nebulosa.io.transferAndClose @@ -9,6 +10,7 @@ import java.nio.file.Files import java.nio.file.Path import java.time.Duration import kotlin.io.path.deleteIfExists +import kotlin.io.path.inputStream import kotlin.io.path.outputStream import kotlin.math.max import kotlin.math.min @@ -59,8 +61,18 @@ data class PixInsightImageSolver( private val scriptPath = Files.createTempFile("pi-", ".js") private val statusPath = Files.createTempFile("pi-", ".txt") + private val includePaths = ArrayList(INCLUDE_PATHS.size) init { + val scriptsDir = if (Platform.isWindows()) WINDOWS_SCRIPTS_DIR else LINUX_SCRIPTS_DIR + + for (includePath in INCLUDE_PATHS) { + val inputPath = Path.of(scriptsDir, "AdP", includePath) + val outputPath = Path.of("${scriptPath.parent}", includePath) + inputPath.inputStream().transferAndClose(outputPath.outputStream()) + includePaths.add(outputPath) + } + resource("pixinsight/ImageSolver.js")!!.transferAndClose(scriptPath.outputStream()) } @@ -83,5 +95,14 @@ data class PixInsightImageSolver( override fun close() { scriptPath.deleteIfExists() statusPath.deleteIfExists() + includePaths.forEach { it.deleteIfExists() } + } + + companion object { + + private const val WINDOWS_SCRIPTS_DIR = "C:\\Program Files\\PixInsight\\src\\scripts" + private const val LINUX_SCRIPTS_DIR = "/opt/PixInsight/src/scripts" + + @JvmStatic private val INCLUDE_PATHS = listOf("Projections.js", "WCSmetadata.jsh", "AstronomicalCatalogs.jsh") } } diff --git a/nebulosa-pixinsight/src/main/resources/pixinsight/ImageSolver.js b/nebulosa-pixinsight/src/main/resources/pixinsight/ImageSolver.js index 9aafaa76b..6ab08f84b 100644 --- a/nebulosa-pixinsight/src/main/resources/pixinsight/ImageSolver.js +++ b/nebulosa-pixinsight/src/main/resources/pixinsight/ImageSolver.js @@ -43,8 +43,8 @@ #define SETTINGS_MODULE "SOLVER" #define SETTINGS_MODULE_SCRIPT "SOLVER" -#include "/opt/PixInsight/src/scripts/AdP/WCSmetadata.jsh" -#include "/opt/PixInsight/src/scripts/AdP/AstronomicalCatalogs.jsh" +#include "WCSmetadata.jsh" +#include "AstronomicalCatalogs.jsh" function CatalogMode() { } CatalogMode.prototype.LocalText = 0 From a831d4329621f475db089ee9f0c568acd4002e0c Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sun, 14 Jul 2024 17:40:43 -0300 Subject: [PATCH 042/104] [api]: Disable Kotest autoscan --- build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index bc5b13abd..62d8f21ab 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -85,6 +85,8 @@ subprojects { } systemProperty("junit.jupiter.extensions.autodetection.enabled", "true") + systemProperty("kotest.framework.classpath.scanning.config.disable", "true") + systemProperty("kotest.framework.classpath.scanning.autoscan.disable", "true") systemProperty("github", System.getProperty("github", "false")) } From dbff300e35a05be979312487980e7a36c506f682 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sun, 14 Jul 2024 18:03:34 -0300 Subject: [PATCH 043/104] [api]: Fix test initialization error --- api/src/test/kotlin/APITest.kt | 2 +- .../src/test/kotlin/LibAstrometryNetTest.kt | 2 +- nebulosa-watney/src/test/kotlin/QuadDatabaseTest.kt | 2 +- nebulosa-watney/src/test/kotlin/WatnetPlateSolverTest.kt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/src/test/kotlin/APITest.kt b/api/src/test/kotlin/APITest.kt index b170d126c..fd839c066 100644 --- a/api/src/test/kotlin/APITest.kt +++ b/api/src/test/kotlin/APITest.kt @@ -166,7 +166,7 @@ class APITest : StringSpec() { private const val FOCUSER_NAME = "ZWO Focuser (1)" @JvmStatic private val EXPOSURE_TIME = Duration.ofSeconds(5) - @JvmStatic private val CAPTURES_PATH = Path.of("../data/captures").toRealPath() + @JvmStatic private val CAPTURES_PATH = Path.of(System.getProperty("user.home"), "/Git/nebulosa/data/captures") @JvmStatic private val STAR_DETECTION_OPTIONS = StarDetectionRequest(executablePath = Path.of("astap")) diff --git a/nebulosa-astrometrynet-jna/src/test/kotlin/LibAstrometryNetTest.kt b/nebulosa-astrometrynet-jna/src/test/kotlin/LibAstrometryNetTest.kt index d9466c71b..a9a94ef26 100644 --- a/nebulosa-astrometrynet-jna/src/test/kotlin/LibAstrometryNetTest.kt +++ b/nebulosa-astrometrynet-jna/src/test/kotlin/LibAstrometryNetTest.kt @@ -22,7 +22,7 @@ class LibAstrometryNetTest : StringSpec(), Solver.RecordMatchCallback { val lib = LibAstrometryNet.INSTANCE // http://data.astrometry.net/ - val indexDir = Path.of("~/Downloads/Index Files").toRealPath() + val indexDir = Path.of(System.getProperty("user.home"), "Downloads", "Index Files") "structure sizes" { val tan = Tan.ByValue() diff --git a/nebulosa-watney/src/test/kotlin/QuadDatabaseTest.kt b/nebulosa-watney/src/test/kotlin/QuadDatabaseTest.kt index b9762074f..849b774f1 100644 --- a/nebulosa-watney/src/test/kotlin/QuadDatabaseTest.kt +++ b/nebulosa-watney/src/test/kotlin/QuadDatabaseTest.kt @@ -18,7 +18,7 @@ import java.nio.file.Path class QuadDatabaseTest : StringSpec() { init { - val quadDir = Path.of("~/Downloads/watneyqdb").toRealPath() + val quadDir = Path.of(System.getProperty("user.home"), "Downloads", "watneyqdb") "cell index file" { val source = Path.of("$quadDir", "gaia2-00-07-20.qdbindex") diff --git a/nebulosa-watney/src/test/kotlin/WatnetPlateSolverTest.kt b/nebulosa-watney/src/test/kotlin/WatnetPlateSolverTest.kt index 7ea19313a..91f5e0b5f 100644 --- a/nebulosa-watney/src/test/kotlin/WatnetPlateSolverTest.kt +++ b/nebulosa-watney/src/test/kotlin/WatnetPlateSolverTest.kt @@ -17,7 +17,7 @@ import java.nio.file.Path class WatnetPlateSolverTest : AbstractFitsAndXisfTest() { init { - val quadDir = Path.of("~/Downloads/watneyqdb").toRealPath() + val quadDir = Path.of(System.getProperty("user.home"), "Downloads", "watneyqdb") val quadDatabase = CompactQuadDatabase(quadDir) val solver = WatneyPlateSolver(quadDatabase) From d7dc8d395df28981efbc991e1b620fd2103a35ee Mon Sep 17 00:00:00 2001 From: tiagohm Date: Mon, 15 Jul 2024 11:42:32 -0300 Subject: [PATCH 044/104] [desktop]: Disable hardware acceleration and GPU on API mode --- desktop/app/main.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/desktop/app/main.ts b/desktop/app/main.ts index 2df6e432c..38222a771 100644 --- a/desktop/app/main.ts +++ b/desktop/app/main.ts @@ -11,10 +11,19 @@ import { WindowManager } from './window.manager' Object.assign(global, { WebSocket }) -app.commandLine.appendSwitch('disable-http-cache') - const argParser = new ArgumentParser() const parsedArgs = argParser.parse(process.argv.slice(1)) + +app.commandLine.appendSwitch('disable-http-cache') + +if (parsedArgs.apiMode) { + // https://github.com/electron/electron/issues/32760#issuecomment-2227575986 + app.commandLine.appendSwitch('ignore-gpu-blacklist') + app.commandLine.appendSwitch('disable-gpu') + app.commandLine.appendSwitch('disable-gpu-compositing') + app.disableHardwareAcceleration() +} + const configPath = resolve(app.getPath('userData'), 'config.json') const storage = new LocalStorage(configPath) const appIcon = join(__dirname, parsedArgs.serve ? `../src/assets/icons/nebulosa.png` : `assets/icons/nebulosa.png`) From 3ac6278c39942b13fe184802546b9ee7017657c1 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Mon, 15 Jul 2024 20:47:59 -0300 Subject: [PATCH 045/104] [api]: Fix PixInsight Stacker --- api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt | 6 +++--- .../kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt b/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt index f56ababd2..f56f9a1fa 100644 --- a/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt +++ b/api/src/main/kotlin/nebulosa/api/stacker/StackerService.kt @@ -28,7 +28,7 @@ class StackerService { val name = "${System.currentTimeMillis()}" // Combined LRGB - return if (luminance.size + red.size + green.size + blue.size > 1) { + return if (red.size + green.size + blue.size >= 1) { val stacker = request.get() cancellationToken.listen { stacker.stop() } @@ -47,7 +47,7 @@ class StackerService { } } // LRGB - else if (rgb.size > 1 || luminance.size + rgb.size > 1) { + else if (rgb.isNotEmpty()) { val stacker = request.get() val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE, cancellationToken) @@ -64,7 +64,7 @@ class StackerService { } } // MONO - else if (mono.size > 1 || luminance.size + mono.size > 1) { + else if (mono.isNotEmpty() || luminance.isNotEmpty()) { val stacker = request.get() val stackedLuminancePath = luminance.stack(request, stacker, name, StackerGroupType.LUMINANCE, cancellationToken) diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt index 91a85b51a..53863b774 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/stacker/PixInsightStacker.kt @@ -3,7 +3,6 @@ package nebulosa.pixinsight.stacker import nebulosa.pixinsight.script.* import nebulosa.stacker.Stacker import java.nio.file.Path -import kotlin.io.path.moveTo data class PixInsightStacker( private val runner: PixInsightScriptRunner, @@ -16,14 +15,14 @@ data class PixInsightStacker( darkPath: Path?, flatPath: Path?, biasPath: Path?, ) = if (darkPath != null || flatPath != null || biasPath != null) { PixInsightCalibrate(slot, workingDirectory, targetPath, darkPath, flatPath, if (darkPath == null) biasPath else null) - .use { it.runSync(runner).outputImage?.moveTo(outputPath, true) != null } + .use { calibrate -> calibrate.runSync(runner).outputImage?.let { saveAs(it, outputPath) } ?: false } } else { false } override fun align(referencePath: Path, targetPath: Path, outputPath: Path): Boolean { return PixInsightAlign(slot, workingDirectory, referencePath, targetPath) - .use { it.runSync(runner).outputImage?.moveTo(outputPath, true) != null } + .use { align -> align.runSync(runner).outputImage?.let { saveAs(it, outputPath) } ?: false } } override fun integrate(stackCount: Int, stackedPath: Path, targetPath: Path, outputPath: Path): Boolean { From f6d941ef4aad000515383a034cc89bcde3ee08cd Mon Sep 17 00:00:00 2001 From: tiagohm Date: Mon, 15 Jul 2024 20:48:42 -0300 Subject: [PATCH 046/104] [desktop]: Set min slot value to 0 --- desktop/src/app/settings/settings.component.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/desktop/src/app/settings/settings.component.html b/desktop/src/app/settings/settings.component.html index a739d2731..b776bec5d 100644 --- a/desktop/src/app/settings/settings.component.html +++ b/desktop/src/app/settings/settings.component.html @@ -140,7 +140,7 @@

Date: Tue, 16 Jul 2024 09:40:25 -0300 Subject: [PATCH 047/104] [desktop]: Add button to view Stacker target image --- desktop/src/app/stacker/stacker.component.html | 11 ++++++++++- desktop/src/app/stacker/stacker.component.ts | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/desktop/src/app/stacker/stacker.component.html b/desktop/src/app/stacker/stacker.component.html index 086859656..6f5cc6800 100644 --- a/desktop/src/app/stacker/stacker.component.html +++ b/desktop/src/app/stacker/stacker.component.html @@ -73,12 +73,21 @@ {{ item.path }}
-
+
+ e === target) From ac4d68bfebb9f8282c2011affe6225f1f1c62b2a Mon Sep 17 00:00:00 2001 From: tiagohm Date: Tue, 16 Jul 2024 11:51:17 -0300 Subject: [PATCH 048/104] [desktop]: Improve Settings layout --- desktop/settings.png | Bin 12074 -> 57273 bytes .../app/filterwheel/filterwheel.component.ts | 12 +-- .../src/app/settings/settings.component.html | 21 ++--- .../src/app/settings/settings.component.ts | 72 ++++++++---------- .../shared/components/map/map.component.ts | 18 +++-- .../dialogs/location/location.dialog.html | 15 +++- .../dialogs/location/location.dialog.ts | 29 +++++-- .../shared/services/browser-window.service.ts | 2 +- 8 files changed, 96 insertions(+), 73 deletions(-) diff --git a/desktop/settings.png b/desktop/settings.png index 1bcc6fdd2d1a60afeb67ad562cbaa20785d51000..84474f972f156393bbed5abccffe9c44f7d762bf 100644 GIT binary patch literal 57273 zcmbsQ1yq&c*EWbBR6?YbE)kHBE~PI|M;mx}>{B z8fKsOH{Un&&YJ&xYyRU}C~-W`^W68ouYJWPR82(zAD0Rjfk5CtekA)8fxvhOAI&&e z@SW5ZA`kfInzQs{4IKF6jbj!9UsJlsX}dhLw{USYb}~m;+S$J}=X5r8GB>w#eqryj zeYHUXUc`)kk&KhMv5S?x-5m|9m*xl;bEiAJ5AImMvc1E{!zXZumsdnUScH%Nu1LZj z0&xfNSXN5IJ$Ylw&7EZEqJ8)9SGlbx4t*@q9jq%1k0J%~u4MR2iVSE};^vZf)tT6{ zDytVi4>M4|DMb`(Clw}eQ;KWg%JrzgK$2SnUFFB;(Mfe!w;mCGn;F^PiP|VDEoDg) z=XYKTANcZ^7@t1SLCRX0{2>m#b=b9ZqGt2Q2weK-asOXFUA3u3NLP{s2;x%@{ct#5 z_aF}yPka5HxpSfUF5+#j3Wh%A=0j*SUD}^tP4?PHR!yD+mt|4A6^QB}ywvZn&slmLOfIqN zk1u#E3F;O6h(GB@EZ0Sx3Ok0V!VRMzEN9!%RNdi4 zenvK(FMDRv^y3w~J|7M~_6tNBZeGePVZxBK7%{ zd0fHk^eg4t^0RtjWYX~0_1VG&qVsjv_t_eLdDa!HijnUt9Bs5IjG4}ETz6z)=X+hS z#_`Ew_K_3AaecRYStxg6cannMh2WVA^G&VCNzw1_kdoBQUO%BdPK-8{=S{yvq+U4S zFbe)MnyeLZv3hw$g#Wm$C!OE;inNRd!-sv04pj+x+vgJ54Hv%m{&q$z(9G3D#uZOr zyUP5E`FD}T%kl566TTsl%fBp13MTxfjz0Y#K zO=L(6Y1uWcpq|B9tH`DX3A3hn9-m*FEBIKsuWcG%P2ib1R35MKFJ4MD_xeStO|?0j z6>s#`QB1hb_v@`kI~hw7YM30orn#aOZm4=YY+9l!9~zH{Qf`sioH z9FqOh^wvjeoq;O_A<1~&;{+Do4SGBt-1BPkh&t&yddYzBQ6F2$RMi?4#$&xpvvRXC zv)^iT^}Y+&eLH$t=!m6K6bAM?*#4a#9Gd#YnY3uWzjO@`pB1M(-pIVW?UJcw+@d}b zlOyQcVy3y<>bx)fiLSM|xT24*zGoj?B zuQtv`r;A!4`NRF(7CVRBs8=7d{*5^M5+-+kcFX4y8?UFO5o;|;?i7B_wv1qJ_I*9` zFSU*Hi}=+b0@Ft`D!(6#H==ZkzO5YM5YUFSEyr>Ft+S_)5gBGU{=+=%>lb)qckK82 zz&oy~YBfm<@qFL#%dYJPhuPsKxn7J1V(o`?_6*W~qAeH0?{se_9jycmwGOY!Zr23! z{Bb4R%aft?xt1iM^P~FF3(sYqY%!4pjHWRf?Fa8hwB(|m4W4!_E;`RH`1(%Oy-N{w ziySde$a&&ySeGjoam#e#zDlfwjR|JUVyUIFj14bAI%WyFO0QpDd$n)#U7DU)xA z7@2ra7)-`{t#sbFjbfSCd&}RnN4F*HSlq1jW|8PfesL?}UOLmfAg!BKgKmDh}Ig2%(c~f%fQoNyt zGh6bXYh3w%`|012)WvZUIVmKPL@qCU2uZ0t=paP%B2jZt?xyr}Y!_c&-=Zs{oBy1? zK2#@h5z#N69r7Q@p*niW zxt`zQ;wqdpXAjL_z4b=A@>?^aV29q}ad4exKB@BHi@tP>9Mv?7o@8O|ubOMaU%OWN zGj|UT7XLH_eEIT)h=xW#dxmW zgAqgL)6I(gN$1}FQcKkWP4)n6LS}mU*K+U3`tzQ#n3$S|hKA0@8~Pfzg^~88Mbb$c znE8Zdd~;cSy0^FYVygPSevNC}3xU0h)9nu*K3skH=n)P*J$>!@zlmfqj~IV{f0U<} zbV$;}Dqa7qs+HNrML8!YKIi40#qtR|(}j*`Sp@}RBBF;zMt35p?l+qh|5;wvLcO%G zu!u=ad}3|QCZBnej*ia6#H7+?^%mU!%7G^XBcrhAUshGga{*pn-ZQu|Q(@7!>l}fV zyB`m)SSINCYt^jmYQg#_B|V6ckD!W9P7d$3XzA{bSXeOYNfqyEetScw!B<=%@^;&- z!=KgF&?Y0+z5O9r>%MQsGTuHuu=tqik3TS*Sy=Gd40FJDtR~7|>dd4P&0%SbKd*kC za8(VdSkdwG1It*IGmB~ad-KlNd*~-_2_`JHn-cN%_I6*(%Rw)Yd}cKKygyr+TDROGYKN>?rLjmRav*Z2WdC!8E)BJAd4|VouDs-Lv3nUW!Hn8-JJ`3)G zD)u7b&Pdni%%5g+!+Q2ie0(wR-J3UWHpOx3SyyXIhfrCRjui^4&hkqYMhdWF6A}`N zxNZH4qL&eJUc#HGurFF=xK3}!BWMf9iazXF99jD04URwu9Vlp=cqRm1;Fahl+0jpc$o_`xniXAS_ zJQ5$g?3}syC+PWa<1v&$dnDcRw%?`b>({RZtOf#S{4P@x_$~MLdnHW;s1k%684jnt zxL;0`FT#?shBd?YRX;E*Q;4{*N=Qh+4wP(oJ;G66ot&ETI9`l@tgOuG8m^Yv-_b%S zsgxq}O33HLC1H5eK?s)1*l)@DCC0Sh<+<&2Z30{+CMiiV^0qinQa2uzK*;g_GQZo_ zb2KI-B~dFU3K;*4VX8e|O1g%PO-wR7R|5Z7y^m<7e8iQ; z_V!@qqzAmtOG+ZH8}8j0WPwCOj4Uj{SFs6roEAFRw@w8q@WhV(1pG!J-@!LEtb|dV z2qZGgZmK$2$nlClEZR*nGWnJud||gO8ew5!Z4R=f-n7UzlUV=5xUaq@7=pvM0GbrBO2LtRAR(mydjKRMVKD-Cv>|IuHd z!=IjR{;yAlP(5FhlZ@;6BPS=Pk8z*Jw`>LlzIJf3g=M6VtQSvg%Kg~s?CHTWIy>6+ z{x@cMmzkN*V{ak9@O1ALoJ7h4oe=8ArS7C+Z4RYRJg*nK;s*gqEssbA6TQsy%gNHS zt?n{02`AOiin`uqV0d$MD- zVH|q4=_?u}m?VcxPnyln4E-o&3UUjQx zs^=50DGmX_5*!NegCQ;0TIU&`L%{#Gt*M%yKY!8-34MaC>q(PTZGTT&1>mk%VOMA3 z1MMWsV}A)YD_outS`-sK{b%V#GU>@=)B(ut+u}Qa|1PAsO=G0n&(ynYPt(HD#-{W3 zPfMfY)GfOM?+T^%&GW$8^Kh$syWvtrNeQpvZ0`oZO2gVo`kl!*F8wD42DiWJRTTDA zum)DX*65Ur8rVBLWDyZbEGrX$CM*M|>F2Lsce%LUza!_~oA%nqaF}>m(O>7~_SaK9 zEW?N|;YnRRG_mM}gvZdM^78U1B7UrSzmpE3epGek8;6#UxR}^CZH^a-@+Kw>-ARJ& zBO~!qQAE&&J9>JU@7}#8DJh9Xc>CAI`6;Eq3!>A1n~c1?(btKY5tyduUY?#NJQT_6 zTy{R@pGUN8E^esX4S0RFjupnhEy{=+2H?Z!=;|_^uJwS^zPs>2^%gmKI~)!;uL8EC zQLBSF&L@AZ;6Yl@3s7WG7xM1i)kfO~&Ksk=Cx_drW@cZUr)u1`>tVU8UGA;x-I}Y` zI&x#_ozHvz1i)0l|LpASDd!#iM}fJ*dt#}b>h8K@PB@~io+6^%lkc?**alzN02IEd_&WPDS!p)- z`dl3M`o*NC5p>4*&sz>FXy_4wOUx&EUwEu?HB6HF zQ1PkBN4tj3L}#ez9w}TjIc#oefsSH`vUbkOV8!i<=VlQUtav&+@*keWgm}x!g704K z!ERksMJnnuaAEkUqbsjuQ|oxQ0EPP0ZQEfxoY_gcJX;Q11=5117__wAfbKTwfmcvG213NLbh_!K&^-KwEH}MZCzc0gpWw6 zMR&Ey&LFvgd((00nC(*EXPJjmiq88>-O%mc%(es%W-1W=+nRd!)68UduFcHMtPh1` zN0i&o^!(eL*gZU4E^fbVdbl;kWJiaKW%^0fjjPVhf~x=x#IPd&&u29v;u3T=qjuOfJA-^g%A_$%_}P#4IY;aM|2-bPMN} z%6!i~Z68q2|A?3e>az@30Dbtj=L)^`5ULG$EfAis(IqK5KBLE_eo0tI-wU)BzHfX| zysutht;HGd0t{XSPC$QuzpR{GvHR|v$#RYNmm6~GPke@S2Fn<<+Mkr#LZkcH(eVdX zigdcZ&BPd>gzsrEs|jou&=6*&PmOzvU902Y^ZCyP1_rDPo;yk^2>A_Ht?uINaqcDN z=f=J71Jq*yApwg)C1{6cUTP$7YqqNMJNk4%UX|I;+y>=RRKyL3wDrf2IBV*}?C987 z*>_}|h?UV|#+x^p{L(?F{oS0X=%9b3Q(<2*!ApTBL_@&!yz(KmjFgE&=oNXLoOZsj zRExoMzDCV~*N;w5N8FD>FY^YR{fp{P*buwByFgsY7Zw+HhqMfLcUlNdc_@xHD`vv* zHi=0|+knA)Y*j5Ij!xE#y8iBDeq`6;0~IA7P9bG$%Rwz@$5D(q0<{Tz5?#j#zl&p* z^^qd(!GD)$`>MBnkBoso`e+ttH&r^$QwTZSaddQSOFbehwE3TGVQjr{#NT4%+p?D3 zOmpYcAq9h1r^2-XB$vh|8IW2s}taFNX!LH53xAu!h$joF<;S8Ba~lhDf!#Wd8Q z)C*6?aV7ESfw}*bBl@2R{(l1V|JA1jPdr+aGFWp_VNPSFo2Yl$R7yK4mE7ZO%wL_T zDB7oQMJnt1ONW%?RxgeEjcvN3rGbk}+5UIn4$jLdZgUPoM3&7C&XtuHR01y= ziyAIEVPD@H6fF;`N-~Lyr+|_ozI995#YF%O*4*4hsCQg}l|PZkyz?L)Wh?Bab`B0W zN7GTaC@4C}4ZWM-KdesG2qJ)-0-Jn2n4=0zfck$h2Ho!&P-#$MrAAFx06}MGXOa50 z^no{6wQit$elIA?yk|KpL;2)tJYNp86yqrX=`BjDI*4YV4DYhA%+Jraw7nyLtf<)X zLSSxwKA@sP5a3C^Xk>nKQ-6;d)$AND9kTw+!|P3K6{dD7d!b&rZPVZ&F~ZN!@8sWR z*N+HlVc#?Nyf{@A6=rt!caf48p8)v2fxs*w)5CEjX17<3;=?xbC@eFmb&ozjJ-iBH z;0N55`^x9w7r%3FT9h7#9dr8;*SK!Z0bD4hNuo|MBVI)_4RS< zK(Pe|2F6-XB|Ug4oiixxM+fHw7MJ_g*tGY)GT_7Wwc{cSXoE+`$H>m=K%)DZPjvl3 z;D%G(4+H5K4ZuF-Hlt6PbdOk0{gb%YgXNx-{MZBVjvVLn2UL7SQV3L4Rr&b%5G#{a z{LiwLq;dv}ofe;f0?;WBnU_V1FP|}dlsb$mZ=^= z^fEzx8FDuaJQhhUetmkak~7~%ZrD0F_<>R3{SN4LCL^KM`Zf+`j zdy9c?YzI#Q5QyKrlVrnHG|hYOI@k=(T&dv~WtbQ^usj!VBN4SbKyLB4jpzKV@9 z8NsDzQ~!AF57ZJ`)FWX3EWy7)w{K9$r4F;w2w0ZuI5-YmgN6E{z8A-q(5JvXfRe?LM`<%Lo0rEXHApK#%MHv3;0b{2g7<+qu=O(J-Kd-GSI&|+A%))yBc6n#B%43 zKWr=1sygZ=ARstZE5GxI5wI-{YsW2(jSt~2T57iI^|m%AHeHpNi3x%OKsxjn8A>jf zQwzLMLpj}`x7PevhG=PSMjst@lDE0JtZ433Qd$aUh^y4H_lFtZE>wZ(ciogO8eykE za13_FEYmP{{!Q4&Tm4?HnDI>l`zVzq%{wL}1V`fHX#SSoYY@II6B9{*55C|Nmatx^kn1Z6{s$mV;1d zbqJBP#=DZGXJGod*68cL0ZfzkaL#*v_?^^F35VX!%;~1=|4)0D&D`agoVptF`{=Uy zWJhf+7%RUx4)?$aL?YkO>gWy%&=3T>u&@PCSEYW;=JN3J5~ZU*)q1LhQh9q-4Q=R7 zkroNsO@30i?a?Ysa{)qB4fzqAk}FrQzWW8ct*eqI(GA?@Ixa2)s4lckI@^r7ECvn) z+E-y#PK-)U{*`#&CL}Vl9gZ>71QF;puxEdwRc?Ok-x0M}AJ@^<%J+dE*Ja@nL?f~(JTM3{#7{o@Thue-UqEpG$uoU1?G zGCf!uq7nBjYo4edw|q`j=XuZ!hAQ|~u|kn3l-N$=)dGXM>PL0hdF;r%=HNz@ZaLC> z?8{}L(fJO{m__QJ1sFyn&n3XN0U)d&wF1?iEb=Oh zOTRj{(p%>+Ex&r$cf7>>hV#-dG(-G&%M)PaSE@KQ5?ORYY4{Fw0+2UL03EHA-dTrl z=3Qi1cob@LVo$Z$4717*T@38(H&|Z`FE1^DsC(c40^ldGSMoBswN4&ZTifbR}|mciC7xBUr67xom|_5AEC28o#H(btM;6CmgUuPTlQ~`~j zsSpWTI}naAbfq6)8ib-yAalfR$IGt!1O9`$qFMDK9wvic4%1GTz*l#$={WJ1Tf~0 z&_DX%;$$4!jnG3C!8rx_XW5;2zqPH6^t6f`bO`DYbTW-LSXcMvZw~ z@s|p~+U;a7+UfPXDD7DP@0kRoE;43jccIo`=Wfx`Mu7DLbifquG4So%n^aV2{fD7l z>G0WEAJ!`KS&jTO3 zvyvYa01^P`fI>~(<$7iw>CRqzuWCn6Q9bsSeOgyf54-^AA0jn1b<(Me^Xzyz4S?Ut z*|}c;A6Uq;3+oHzI1&y}IdH0DbJBbhK{NVZp1X;-toZ*o# z5GO})cfg`39IOB(BSeJ&izXgu#&d0UO%KsDpK!oSbxUc6R1Uii=yqn-AklPy)bmb#=`uP$lWLt1vAcgDg+( z_EaKZG$biHl@9cv$Cd$^Az(m>IotRzhee7iEKsqcA0KQy(i`!{O(yw<(n17~k!l~F$22nY#$9nB3a5%qB!A|032fw$lD_=D-@zFGJ>QI)X=6?XoJ};Cr4-E)Ertr&VMSx?RHoV&);_j%YWa$5~v= z=6E*RhW({Jnau-B6F(+C3qjspZ1%E3o1s!^pn8Pp4>bqU%075@3TObT;s+#P?#Rl@ zMx~@EgZ&9m27Bc?ASZ8NYIq@ zId#=VB-MTHdK`z2Q@5`_$SMea7Q(nMla!Ia(bsU@xC}Y^GH`&%?F;DFpLIF|x_F(C zu&7UDZKNo2$_`C`^1nQt(hkQWln$u*=yeQl3bJvy$WRs7PLW6&3RPw|m55LMK;zj@ zJFa>I{1=qEPUIOevH6(p`~od<>d4)%c$i-sRW&24{)M+idAd5IP}NvFMMYTg*7dmG z5pQi2mEU1JaZ`BH|404%+na)4OMaK`fdguOi}(_|YgpNQ{-5AtIfuGADnIoxBJ8QC zj~)5U#nF}7iW$}C&FT+qz3_wQJ1?B1HDq56^Iw0c&X&`2(HxiJTvc)SZnEEk!xW42 z&s>(X_u*id5Y3)9g}N}R=D*(QXSb^5(bRq=Q>Bp+wterzACol*K|%XH&H+a)jrVJX zmPp?OWh4@P+93o3$HENI@L`kBM~FBY&G;N4t}yUBe+Ahtq4-}SaLu4!@Y_#|0q|-L z$&q9^cU2C z#|s}StEwF5TCYQkWa_P|@6m7*&)*~a1N@;lDSqHii&HO*kCjaZNeRNaG@RG@oILFk~vH{I{n7?>5`rXZZ_5tW6TM~eZp zqXW)Y3y?Cqsm>V%^+_6(7(&o~`d5KYDX=x}Jx^EH2NtE2NF*;+1cbK(pv%z63*rin z1c2leNs6)D5G&2oZZke(9*S>cwmq-0A*>C~=y=q|~wSzxp|{=LAkVOlr}4f1GEgEZ=k z-{r-N#2=8;A^_Dgp$Tc#3F=n{ffy8=b`LP`isLnI4!pH|d^&U4vtHED1Iz|)ifNkd zu1~k@V?3;@;15{9X+lR@pu^_2w+S1Qg`Lr>r7E_2EmCX`2XfDz#Z-u|K`UuHWN1Ewp6^5AH(DfY|pGJ2qMKvG4Qd6T;N!ed$0!6*i(1L}ovfCd5) zb<=d6m$1tU5ugNo*J17VJve2mo}MDG@{Ej(nH`AA=2t_b^bR0lA#y>a1FV58b2>Y6 z1hE(bl1M-Rpp~TR3Ck1sS2h3(A2OR(BOY+8<-t>f=#E3T3@4z;A7VgYQ0Q?3C<(M^ z1g4`lC`UdLN>wxA4gDN6?$y$H|` zQCgh@NQNxfJ!(9Oy_RV{SdChSK5gK`xSy=%^b2$!djfALs{5yl|Iy$%p_u>$#&bGG zm**;LW8JHsxi+ABSU>zKxa+iESo@wVR8teb-QaKLW)XJ`=6>UFJg_C}?ASo7u- z*}Bs;BCfk|pPntFdOhJ}FQRASK1X;j0JR$=&hm*(SwHyp_G|fdU1irdI=x{`af>)q4X8 zJS=(IE31<%aj2LOe@_e1xoMRlz%gvgVCow0<&kHZQ8vIgFGP0ilMv57BK%N!5Zr4p z^D3En>J*G6hn|1z_%zkpO2={N`6V^f=5bdzqcBrg?r2>r3oYmV-eNVW%72MD z_GF^w#sB+BRb=N^hp>$2hx()f%0OTqEss-=MyT}`%B{^FWHoa>lv9T@HR6+1tKNAp z%&pYhSFr1}QU~lpMNbD0m<9mt>nf4`O#nEDe42z$XW2Pefcve)sDp*7@D%sXFtJI4g&3b!C*};suS$T z>-hLzU+fm%nW+`bUOSr{F4R|q68(>ksd>`;1a9-QZg9&UsHNYz>c5K&(?FY}Q;GjW zP5ds@Pl7NCqD@Q^@BBiY(x97+@;d+-eUKN9m%r=+Yq|r(yDB*OFu>At0BT_qEkj^> z0m7AI$W>AMo1yE08LX3D+jTB0eXpTiL#P!1SqPkbXu0UA6li9>!0lItzf$|0{G|us z3X?6nXtxFuj1mYuL9t07vQ<(#ffeN$Hb|h|BW;NVw9L%R=t#n)oc~qXcOWu@?L3X6O@*Etx;S7Dwi0XJ5CONDT^j{#|*UZG~P^^mxO= zrYHqFJ3HuQ1qld}BzxoU+ z2qGeq%j`vuQe$=w)r5m64uCc~0EY@L-vi-KpFjkx(Cqqp7c?~3 z$ug_KAQ%kl&sArH{H-0{5}lHRs|?4Mj+>hs!Z!uDYay_E;YQJ&5$$}uTGt$}u-_K@ zQs=(Q;Pr3gGi0)VR|m0`2OlXbn}Zz-qYL~Fe;%UW61>ljo;da5{HGpky0h`BRY5H= zzDgNoxb1)0BiC{*IrYl#N=T&k^{EBnQ8rWC*V2=7+Nqi6*}Tn}=^Vm}-yzOIf~2B7 z-~btQdD?IZn}eQJxZXgm?Xji^cA3+bbnM%13-%EwG}|8+#`KbHGq z{FnxkNlYvmfT6^3Ufy+U^7=#YTaK3{FJaWscCxbHW5%2wHX2Q~(83wy7BoOAm`HR` z*`BE2R+Tuuixv=IY?}VS)2*;m28{@>NZco@0=g^&gw12`E_&1s3{6W2*kG?9-8}-S zpYJIcVhz&$Xrr_joyMTUYoG#)Z^;eN<4>R_4ZJq*gQ85?kJoUU_E@G}PEiQU_yhX| zZblclxoFFm>>Z{*j29+=#^(bY8(6HP5RLav6E@h!yYQ|e6)>M842CXu-QTANTSSgX zAKQ3i?)P&%AWa=OakKdh9PS?LZ~ z!@$*wJ@zfY7RmS23bE!fX~p?vQM!K!T5}JCQ_0JT2SEh1ogp_Fk473U7LyI0PI|Rf`q-g(mfUGbUI|>m)+sv0-jr*9a2iilzY3@14}#^x=z|#yX=&*&@2d*(@&hn8p@GbT z5VuE$9OU_%fB>Ch6U@tt!v?G20!jopAr>%nTA*JO2X+m)7h`SZE?RYS7}OqxO?-w* zfl)mB70BymAVi9`Vj4=3h8k}IZvlFAdb)}@41Ixfn%Ho8zRem29Sn~}HFW{3cvG0; zNIXO_w+vv)N8L@Vg;;5t~J+l+2T4DE{J22`yi+1Yv z7Jeeo5!&I5UqeT&*Wnfu%nSkH9LQ26he0z$C73Dp^~cQcb4heRMoTgy9v+W9vmfti zyP#AcfH6u4+9V%|gfc>>JD{fIU;#0bzg9JjH~2}yJgFsgW2I!F;*PSIHI>hhHjz-~ zJ00&Wib3H+ou;CvEx@`5hwTZ}1zH3`0Cvym2oIC911))nC&)hLKIy@zKbm_tl8hc1 zP)ZcI?hniM0fGq91fU}orGP>Rv`Y$mCX0slr5`WI~utgS23hG7PxY4Zyf- zjn?0tR{H1#luc*qeZ)>TO2Hh2AzLLF%RvAW%Y?C$jp@1?zUk^*dGHS{;btE;IZHuj z`T?{&2zn8OATVoHQc@xWle}YNV;ke&-+|A*6LvtN<(B?Ovlc`Mxz5sLm2*$jWSy5F zM3SF@1e`%Wvaq~NeDmh(oE#R&!OSczA>w@l;u0JeWEH!t@Q}OUCunPZWmeA!=p@2X zC{TSEM8w20;I{j};R%n3K+n$tVD2?uB?NDsFe){*2RPW)^LS{&5U2`4=8AzE^q9@t z=qaoO40i#A>Q9%t3Q-|UAi#kVR`^IJSO}UJ!XWM2?td_VHg*As{RC#D1gB|btds>& zG381P-43%dW5~~A3ZrtrM-)_*S~SKj^tdHZ+pr99Y-|9kLPA3w33kaSC_p>85xhR| zyFBz8IH`F*v@*2>90*-f5Hn&Wb<2ZwhW2luij3f7pp9fa3LdnF3u#eAexXfk$bTiK zAgV;zCt)|yNtB`QF%u{!bV9VTVN1qs@GC>^9n4|?e!_TP8SWD{NW_;oyHp&=T7j{~}fgv(5L(zFY6xR(< z*}&|s;#SvBI=0hlC70YBA*95Y*APbkMGk-A&_8+n|1izpN$OAPGy2_umNbtY-Tq>8 z>SNgvH-bOkn$u-_ss$RPgjLn&p4*K+yNWKsGFEl--#0?VK8_=TJ2!&!~l0 zq3)7P1;Q^U{6AdkfBBmQo%boE9UNrHY6a7nm8oa5`QwDrNU4LK+GaS^KYvGCs;-sF zfV`e`m4g6Z4nsBbrdG*1QWx4Z|{o6sjt{{eEcA?Fb&3Xeeck_r6{4D6yQ+*~hpurOOi- z6*)UT^ER<3$fRgo0U4JiHn+yLK!(RKYpUir!k%T&V=~ks*Mjrua!;5QMUawhEcWec z7w!2s(SjH6QPjE8Is8UvKGd24p_Si6A9Z~vTJkYJFP)%G7NKqX%aY2>%v`QC!MgAK zIv{|$WUFTA)09#cZY7Pv?JbmE@nFH|HxXM34RNf$3!}7^>xF4y_RcHC>#y8%SU#r; z2gQBBe??_-qmDGC3BQL{q3%=2!M~o-{Zbwav-B@HpSx5TFKckz&!e9rW87^R>P6@Z zQ21_>PiQT!mz%kSg;6t4y4VQ`h%&cntR2SN^vWPfX$TlC^j9w*hCS1n{bcGEW!JxR zUzc}1tVl59uhXV(mE?p={?&jd(G8DNdi-a9r?Da}DG2`FS?e^#-4c-(vY z>3LF=o+wf2T>7UCb_PN2H2T8`RwNFY1iAKqIPDsJu!P>p^@FwHd)k#G3Vm2v3s2Y8 zq%f{}^4U_Qo~*N+?IDS$)&1sN_uNQ=<)^=HetxXDae*;P>$>5}9%iUdBFKMY+VEMi z=9)Y)0iB_3L{cWRxshQh-Lq2pKg+M@*+^TJmxGc_TCFRhwmMp$9k3!PkuD2X$L{NO zAwMHoCZgYwvfoB|<;9I`h-~Dt67an(K9_cI^-W0r_t zDtz^WH5-zan2A4k@zTV3@ZJ}_`y|SYQ`yEt0!}YoH(tF-H}DA&!L?L1bvtAp*@&2P zPx_YGP|*yXWJ|%N)n3m3}VCG4iDv*Ln95=`6jIpu}O zRo!#u(erhq4y6|3;&h#TwS8xGr;QMR|K7+vY`?rhKNAyB zfB5o~^=VYY4omE*i1FHBkhkJ{=dp$$01SdQm2yVvl3@DV z`$-0LEmtLD@)$ZR%8lKpHW2CM<9d}9v-U{5l%Ox#d5k_iqe_*l8D3^$w7qoIY8emd!Yod@)9<}^g+g#$B1g#^9*FBlfcZFTC zMdX?atyV}dpP45M9ldLo(Qh+W@LN-@q=+2Oz4!0W(kQKFA5D*pF{_XZ=AVYkc(-=) z+jisk@dHpSy{QTr2Mo$n_EI@kqiH8s?tdXTVcBjm=~8eW{W)Ax6_pllFf`bx9dBlX zTQ8FK<~-vQ)T1!>t&e5hG1;`;5q};yYlj9my>;58A`1>uN3wbI%2pD{4H+wmMaCq( z<@_>4n&a;Dl|VqQYK`35IA8TJP26n86Z^5jcg0st^VW$o;~=X@ZeNK%ZcUQdWPt5q zFVF9B`@Z`2^K#*{E*f9>rHkC^%aocL+eCn|;5WOyhW*>;7~PUYdWTZlZ|s^Zx@4S3 zFHe)N=kKR2eG@e->Zo|%ZO8cF@(LDGHBLN<#Ea?ztKm($^FoH#B|U;8k{cd&1z-N} z$}X?_Y?i0VLscJ{J6OnVJW02MHLbTr55AUvCPV1_v*mc7VW{gjszPpp(D@AcFl2gSrziXTQq)+ijBtdRaxnF$UW%Rr~B}->TA! zL|VCiQh|0=8u{6QoDb&>QgLi>rN$JX{Oqq zyC$4Qt?=jBRbD%x@Xb7K9_9KQk(v=aV`1gLl26q*r`n%Y&b%b(&?@;^s<*4|vpaH% z@h5M;F@yBwEIIk#x13U|0W42s1_l0l3YO`>=YLGaocM%|()a0#O8 zCc`QIy=*cX>9CpkXqzw17`f($XPrQJ?R3lKf6M~BW>h`HZke5W;d!-uqDC~SZq;nQ z=Tc-Ldwig8K0wF5eU^1)GI<-Z&F9j=QS0zIQY^@%R9Xcqu_;iqg8qpL^OFG&fqeX0 zZ+d?GwyA(xvX^}xMHfocKufzRVWIrKpCb`?HT%p=e%tP%0;;pZZBI0 z&J6^RZbQ$^9$;(V$2T3o+z{4zj%)W`$C2oR`QigZnXK3xj^IXfg2oWy;Qm#mm7Ww? z<}tNf<+6hja87rq6^% zDWPj{R{BJkfsCb~QLm!H@=`$dm{kAH-rp~FQx8kRg|DrgDIV0b1&~tz942wvs1k6x zaphtpanR+#t$l9C{zP4(H%nNo6YouCjxRS-+}vpvtN!`%ZZ=%iJKUi#*UVSpi5l((7 z-^IJEW;5}{%%3UN1qeNFu5jZWoSj;d>7#ocF^&}M@eBgAa_ZF!=P^I;QVZHn-WKJ+>?FGCi+ng7$R7ow*|qiNNR^K_i(+8;%SvmH0a$*t4d z{g1+zmMn(tM?+RO>Xhx%XR{)_>N_&kxL4BC5t~w?h|FJCINH9*vj1?VZOyxZLq*Ig z{q4c=%~vY>x7#-(c7M_|@bd*_6iqrQKO&*?rc6Ikf39jaGvUA}g^OIRd`vULG)woT z6HoAp;hT>EUcV_>4~9ZsuJ`}l+7_pGksTsSlvm9*I4P^dAf6ldr);Rtn2B_~r_Y+= zpRu}9BzCnu<+c53rS(d&?Tk)D-ZiCUfwwXJ<~aRb&p0J&8scN?xgyt4PafEhKlFJe zUPbKmZ{5A_ZMO8C^ftx*wF>j=wbak_)Ng7VRNkR7bB;sMeyOovQ24kI*ZOmtWmRi^ z$!0Ri^7jXYyv)xbJ0~%G8vznTf98xaMN+pv=Zp-f^*a(|SYE4_#gd?@rQLTIl-6*hS+uGlDGYyyhKa$*0r8%W>-I|+*kR-*Tj~|n~VMM zL}INqdS{E7S)S#lpi^o4T3+Wg!>4jwPMcLRNdRE>*EW zMB|~AjSc0~`FN?N`Bq(ce0`6NL4&+Py8) zQRPgQf+`fgX( z>iYtnJi(T^BJa1+^#=RFit90+I-3~Fwf1wLhg&aPB#Y#G0glJiHg8$#4ZS9{neUOrC_cIWmy^zDXiL`5nG$i+ zc}GNyFScshqyaB|6I(~c@Q>n`jK2CEykA)DUc9>}}?|gydcPQg7o$q(WmA)idzidpdeP_$Rf`LP% znC*nfhe5>m?Pz}(I3-G}tDRj^6OKm`zqx}@mf@;KY}S3erW{eZuWGbx{7!vpR$n!x zzeum;UjRp575^1O293An#AKOu=T`)VHV-jlMUoTiUK$zlNV0~nT@S9~Af<={ zSUkswZ4*ptkwK$3Jf=02bOXfmm$7+k`|xgL8IzBBi?NU|>YJ;$iOdu#RD9lA z9oSgUrtb4PIR5ituc(0T%tyva=%jMUva}J*fP~x z6%ndeXr>%zvsKMKO#Eh!YxprBQP64EJ=5p@rc}l<`8HO&jY7=|&l}5`7KYf_nTZJf zZ%Kjm?}Hw0k~<2kM!LnY27F=U9oku*l`W)FI6%q@5>EVDzJ+9bB>4;T-;W9Lkfs1N z(%;#-F#}n%A^g0~@-ao@;i1+fIsun=hQjNMubsR^c&#lTcoV*)n8+J{a~CypaQ4bT z9M$*eNz(VwR{^eev=NRL_YUk#(+-h780PcpxEZXybqcL3)FYhPe^v0SC-$?APyJI@ zC$>grv9595M)mQ$qOE(D+8cLoLuJ-a_R|>dp%k}+D$eIjO0q;_dY1qr$=~sTc1Bd{ zvVyY950PpD#G9FJ{T6h}GI}?jo8G0k$E8dMOGw|uwV&BS!FKtByYkwH8Mu6bBmRpsM*HzVO)_CqFuQU8IQ zSEHS++-ZmUI|0i$Q_dzfg=bzoDR{{)SK`8tN1#?#BwhW?YF5LKW3ZqhkY!fZk z?ha98A6{qV3RF}$&A$@d*-ksbTbG#h=lNBj-bGRV5ZU}D-q={qi6`R4Q7PHy^78la zD-$LZHv^5Gdc_;AJydNN4qG7Nou`-(ycwPt==F>8E^mT{cHbfmrE1y!E;eqWaTAKP zGWhmj#rcVINzdQ-$QvirR9oDg1-DRBBGak`rh%GK2hv_|mcQVHVY}V_QIDl5MS*)7 zrtl>V%RTodQl|IEEs>W7G0zW-@{`xc7TTPSe&<|9z##D3s{JMP88rpAj~Ug~i9b%T z-V2{NFhqYdFN523)B4JsXj8n?p|*G|*l^BSNEoWYu0Z#ShFt%zj>c#8XS6{{LqkKq zA#aUt|HWee+nr?fb0=0DmskAW-mWaiJ9oR}=9_ZA1%K~uO>C#Xcr*WA9BVMdm6Euh z8|QWII98mTn%Y2){^3&)S*2^okBg+TU`%3ZtOm zE?}{D7uxqbmnx*nX|rKunhN;Ajo(ICBEC#nd;DYKxyLcNPSxK12X^DXEV-($saEGo z&lCC`F)AxZoXxMApY15P4UA5!6TaAqd zjcwbuoiw&>+je8yPA1Mg^Ly6%zsS3pwI=hOd+#}CfA+ovzNaYX=XmZ9Pn_+0p>}yN z^=gsIxr)jWdYZ8(kMvuQckWF$lsw90!sAu>9vhj;8)J)(7647E`6wpYAk^x%m3L^R z0(8+%y4|k{qbKMVBzM>rz#Vg_t3Dyqy$&?X#N_1bK86~2oy!G>u7}Nc%3Nob6&*K( z>8onlbe?p=&)ZS-SSrJ1VyCg$*%OfXHISMQVE}_BNAsT&AXD4+4JGDbVv@GJy4vVy zBIT#clrTfbqhmqE?E3T0Y|isNqqg{jyi#Xnjtt|waNF;B80gbSq>Q=W8=CRo$@A46 z^#E5F<4}X|@8@_7c!0!<&I^&aPJzpgt8pM9eL%!$uSZ39PIQ8W zg)#qcwXdaGtNn<#mBnBJa^Dnwc7s*ZvAd>w<@+mUq{W^L(qw~Vv670anlf8Ouz5z9 zmJ(`c@e_iJ_h(5aHmf6>(ZmS+e&+?h0F;d9DHBnRJLRc4dN^NfEa6{v-w2}SFg_o* zIdp`l!7Hlozvn!2`dQMr<{bUA1*2q#IZ=uvC(uI;mCEq5C{l&;XtqieTWqf+hr4>e zL?$LFZ%>Wl96;pGU3F$pKXqx==FwBRN}H)%V-VfVJBKDGKS&ZoE8A?SUuNNz+l!xraJgb}+>M(P{j^$oK$X#Y0w3G}1j;#7kTcIJm^lpQ;8 zOZugS5R*s$JGNFx%6j^KSi=twv9AC4nN+sWIgy&oki`|Vd&lXYBl4Vo8f<>YMWn*V zu{#-bY>oa9O|W8&D(9c?94%z<+n1E^6;ik@$L}!briW(rt$I zUvA+5dG1!g!*NhBrv#$`D!hU(+i~ix42NTyf7<>a3GOr5cI}yh!1n>So(Ft?YbtA( z#kKm|!{Lv;0OUe{i-#He;N&LFu{k#yq zI0eBgpuTS116v5cCWHH-mAEb|QO}@H&0i{twrz{l8F8;Cd5DOdA#_+RtZly$Q8I=d zP3j&_yKNtZ*7}5Wyorm0H1jNu*4BlExvAB9lcL0G^|Nz(CokHF7T1yFzw@gLk~Jly za`>~ZbyJc6c8~g>d~9rd6_yp$G-D@kwL4Sfxxk-c1P+i9qO{GO=Qw)0@+9-pY#Bi| ztwDtT75Y6uOd%fxA+j!oWMkN2`CSICfV?`$-^~bjdmE7Akbe!=oY?eEAhoy6s zkPa&~1I>_&lH?hvEKD;&p>2jK5@n^+<~^((p^MU{)vj%KX?{V$hm`>l4nWEzE{@}2}6JWgh(8QH_*ry*21(P}DdZJB>gzj3YR?#1)iRtnjd4q|g7 z`Sz>>`=AAXp#=6dGV5wZ(y(>)iRIX1Dq$Op(aNd=h1zx*AixOgT?0ruwMv*i|q90a)&!vkjg2>8@}JHN?xV~g+z?9ta|aJ>i(+yH>WRn zXOz(%Kb&^TX<=zjYdKV&fNWtq+X3}2swtgtCAA1iid#p=`O5n`GkhptE_eZ_uO5}6 zfGVcI8!0Bls`Cn!{6_d=`;#sGm+)u){v-ypkyKU#?^gnht*r!&BnAQ$(wXyA-J^S} zUZ}pU-nOU+RBXN6>S)Jx(b)5Xha`oXKad8%%^%`=H5@RZ1$T z7vMV4Ws5HI=+gY_9WZB_dx>4OOGEx$qbA3asN18GY2KFLM`~doy9|x6V>1edC~?7h zEgQ7ete73F;6MvoZC;1dEED9O=o2lzcht7GLh}?kCye{(^+ts;4(43^Qbnf1R`}?d zv~u1UTvd%Jt0qE(Q7E>V*AQ*`dHa)NiPJTqXI*Pc=}cVB*>3fqSqW7(JLqjYlgSkp zj5oU{f{8F5>J~_{-bH4bhq6K{saN3AXxwG|?SM6E_vqOHGdm8O`|mI5kGE{d5c0LI z9|5Tdq=7$Je^bl~m9P4L%}g=@UlgtLk>D61lo9xUX`w-DV{c*^!$RP=FCdH`2VjK; zZ1u4fXz)akh%IZO2umnDH+AIj6P<%$`QXbdZ3nIc4q+jF;rkhhG-Uw|=E$T%{{T7B z+x56{_&mMtP9>;Y>O}VqMe8uV2Z0TDdmV9gbV(rcm`UbBu_%+>7H5r$JUbe=RN4O5j$IxjOOp=G5{j|3O5jfR;c^-)uYJ6@`#pc9^i+L7?3vttR}4P;j@dWX z&wF0XOQ9sZ^eE!~k&Br;5^YtZ!A_}Upi4(niS~?AL>iu016Nh#E~sid(?Yb-5-;0j zr^xwEJau0oBkb;cv5c3~?f2=ayd!NP;=-$59?hX8F=butO}o>cS=(=2-I>8SKH0mn z_$a{KU|gN=pg3E;+i$Ljv^zSCqVnkP)2u}!r>4Yaof0?2iB8oRBNuG==OSl#1@%=VYK`&ak zH+}9wpvr5796G*WGON5Yw@N-0gh+b&(~G9Sl6C|jcN!`tb`;D1xD{NHm+4@6aV}z# z(O24BjV}|W|BgKWHY35O=;^F8Thi7Rp5>01L@8_dRG|tYK)XK!42FZU@4BV*~p*|wh-tLqcL9nuzSuMxtn8t znBs))Ea_8QINFs!i00jc2;BRm+^^{WhyioU<0dEhg9=8S>1Fy2^^QyKn)YMdudjax z(F{0Z4h|>-ig!hLp`8_>B#;?(yQk!J1_%{%Fa6KHecioX&|7tLXH;GPHE-`WJHyX> z>o#EB2FX;1|(aquYuU3-aiP9N>lSj{*<0K{&Tnr?q|`XX2wvk%Wn zmJ@|t*Byu8+g@Bd$ZZa$-hS`m`;kOg52E{e-j=M~&&Mg(T3n#zszA78QKngyl7TzX_L(3DK>m@x#Yq2}{^ii0w2%aa$nz`Z}~R zEceLE4~t(GB&chxFn6~H98)h!ap|N?a)%kIU?5wS@U+US|(grUyMR&u=v-!5VTOfKOi0a z_wP(DS4Yz^7!JHRg3+Pm7ZfDMXmK!mjnG9#MKu_&$C0vZXV+Mn3nS6y{T&8DFJdNQ z2YA{(iNogv=-#4Et z^&s+2X#{~cof@F3Rq*{xXY;x99VK)eL=v^XWmuK3{uxK$+#KS)sRrMzRMUg#yP)0P z)dIfK`vQ_W%Qkf*Y+6Cftk?Kr*=E!A-A$v%+k=Cz>&Xi^JVKxOvXI(4aAEhwO4b2T zsxw%HPQNKE)x^MM?7gRP+q{D?mCc<=BrkP)?JRNKWXUMmhL{3fF8W za0Nv$uq{hq2~a;OvnVznVU~k)3shb0uo8WK{+LHo3SO!D4h0iH7@`02S=sZv1|bVc zy=|#687zqt;`yZu?Q8a*=ll6$;Hy^uIkIjanjaRgO8b?kb?ZyddaEOb{3Kf>$8h(i zq|_A@7vy-ppVa=+n0xe3dG;_;hT&veZ)Y?Gv~sdUOj%vMage^gW`8mR!x`S2o0{)- z8E?it#dhAWuZk|o?#zQ*w|&EuF>@zC89$Q?X1SuAbg>zJkb)m~3L3W?q_;lRqY@QS z5-G|_)m(_9Tr%Bw)POAatSb!OG;S*n5QchCRv2qMlePBW-ln7bym^nsb&_-4AX-_J zJAgnYJfCnD->_{p@wK&P^Vcpmo$RbQ+#FLgPq`#jvC8F9&#XsHFNMvkS`?eBc18JT zQ(qqm9o1_H>F;_uBo1>h1pe06$F!{$ z7EQEb3WM$<2m)>gVf^i9C7BxD=hWtfj^S0OJi$Hg#;Z~VRummI2a=gOs-5na^}UUk zpahvTx7B=@!Ap`h9-|p}qN0tiuVca2qwZ&AU4fjE5>r@-Sds*Du@&Any90{Y(h^HE zS6~t8@8^EBfAiQ|5tZ!P89oXE?`-XNT+f^DG9aevUE6c57(`MbsW+eN^w__ec%N*v zIv!!@9acTe9=C<$vwa*!prv!0QRsEPd1}udjJkcnsG5U3H^|dJM0#Hz5QqPO18vGC{)O2Ln1{6@3A;DtExi99qBH!dR?Lgk?tLTLa@ zzF^g^km1O85aMF@&&auB-nA8sZ)D##@rHurMSZD%k3@&1%ofHF#Br`d)lpz1vsQUU6D3{6}k7U*y05*CiKYM%PRD@P;@*Ta%!)CH2 zoHU6CktvKOC%E1>8~>|m09g6(9H8@9lt$%Ep|z&}pp*ao&GI_lDfo+iejJ zXroDq)axG*EX4MJXR!N%_A*;upCf#L2l-!( zLaDcLA9-}%@K4a3dH<5P8O;80PvT*hkZ^z8EZ4MYX^+_wRoDHFTtK@u7Gwi;Iy%aK zeEDxpuGIAAsOfrsUwPnqj2CI!RnCRQ;JoDTodrF$`^DU?;iB?IbBi)cH_=m7->3E3 z+u_OHAyCYg$3=B(`_-~m{DPR;q7j{r6zUI8f83uSM`cSAOo%Wmr%Xp+HZ`iGAegEM zQKPS$nXuDw$@pCA=8Wixe4Ny(SP#9 zyoK_>-rtv(l?^rgcV68VWnv_5wi%$A4*hqYspQuinUNbwPuf?u%wbL{SanFj8#LHl z`~e$@r7x^+j|l9#^|G_JEhwqTkV>M=Gsji6!8nZSs&YHo-{Xd@pio@O&op95Q}1@A zzv+5F1Os8cX4jYf+4S9v#zP|cB3EMJbqkD&ci)iekJ*#mnH~3?wP&yAUu+v%=Sj5Y zF|vPa5^H7QkM(U0-U@{Y{iHNyA`U~zT>T#lKrbFoJc{(^Jriy9B{DE%ei$wqul=-E zK;-^ZS#q50!IWU_p#H5Ix{X|8JlWg>;D&`X+;peB4xT@7R|~(=IJmcHfxrRdYUVmZ45L9E*Uoj-+igONfZvQkj0_Ug8I6x-jB& z2Wl6yZIdn$TJt~~v8VSBK{1u)GB@S5b2~HRXoE(Gbp2tKe1;I0|cwaCqm94`_O9wOH+X} zfNEHLc`itxngUuD2NGlZN!8NKyPJ@>6MaS;;ItM@as)H4s};gy@%2Ta7rd2Ea&fxU z5Q^AF;!U2T2_+yT|BXsOM~SIt-=G55*$KjDlNkBXQZa|M?S@_vgN`1xgu2B>ymC#p z&IwPt0{@s{$gW~U{T<2?@H>2o)*drkfvEw#NMR1HwwCpN!NUiqZLE)cFDxggSaXdb z9v)tG_YJC$N310%{d{izmw6g^6ZM{mIvl*CSXQ#^z$$ebZ4Qn%#7jbFgvA@#W*@|N z^l9-Y1V<#-B?KBzCH#biVO+K7t+Zbvm*Y*!>`jkJ+-Qg|?H;KL%%Ixjb2>YF2 z1n%^Nah^%Im8o2x34F6bxFx9jd(5vs@&iW5=n_wAR3?JsH^8K!6T%OA=xd`KVZ*tLve zbf0KKe4Oa;SI2uRc(RQY^&ri*dSO_pnr@Ww=!SfU(WnUW-y{d@;)oLy|6Y-7J`JWW z(T_)>L-21MCBk5b=%FKZNT&}=vFO9r53Y%oBN1hoLSFvV&P@a_{?PS)bHOv9lFdS% zt?_ou=$X0`-FgF_ys)#WRKqm*81Sc{g8=a0iP&La^5B_s6{6{|AjbV6T9CO-s_sY@ z(K5oc<2-CZwel5uTE*Nn1sj4*m(S`~^lK|BDIpUvAPg;nNUU>5zMksxbvSs$v9mh} z)bG`cJ8<-VXL18v5|6*1O}m6w*ib!n{#sFll~Dw#08tEMGkbYS2@i4HXuZCapz+mQ z(AZf|-T1cnfPz8!UeF&kQ4Z);{BOS{LafcKE3yWN+df%ClKmBBxsu?T_#nEw37m!U zp6%ne=FA|}E!5C3Fo#Xs@_zD5O=8!Z^gu~ST`^j=Iz1S02Ia%!UO_1yq-7*@6GY@9v?c{`S{JexMurq$ zbYseb=9sGnoTOP6$wQ%l4A#9G^*iKi=2Fxt0Tx<9q5QVLV!q=eNuOf z@%p07Yk4n=1k~Dq`84 zh|M>2gV}fPhxK|iz%L?lCje{_X1o~${+}GF>5|_HtI1#x&jW^6bdMq^bBa1@Fj+I= zNFXaM_WFwzZb74t0L6LN3s0tkV}dONuuznI{*-;t3lBkW4jFG;YwAu}U*{n){V8|) zPvzetS2v`%*y`h{BZ0?@g38Jg3yEg5iMaZEf7r)Wt=~Zk25{(sk8Kc^{BcVt!)RUR zF~oXnzZGqD@6FX~Oy|uKXclLDjAIsGetv$_6_|wrIQ5i=J>yyP3zEv0dZTt06S)x* zqgX^WEBhvf>EPX8B-B}Q9e?&^?v&98E`OX~jSH2zY2&rgto67C7Rx$1cgSuQqitq% zf{WyyFR#y^kjU4fcO)Z3wxmhKLtbCrmQ5XBpEBgYrz;4`O*&*W0o?Z#rn- zJ2LG)F{Rjd=SOpodQ*Y;>)Ji8TPvW0(|9_g`Qvnkun-UG#;-2JrqgwfVIu;2-#>YN z2hUlokltkO@TE&Bg)IH}=C#7Ovyl{U@1K{PmulSglE+*JwyE4a)7LA~=7;d%A-6~c zUH4*jKY})Hm$+sZpxe`LOEoAA0uxG1++hqTBckdIPd&C1mS*pE+F1E_{1bd=GwTu{ zUY!2Rr4Q^aHhQo@VGdc#_husM(BY3-(T+M)JZ!i zOS1i8rt`K4&l15h@b2gcR4!w^1&;-_cAkE@4JN36CTmo9@jSJVD ze!gl;J}pnXCt~NOrvB{q&QwcyU4u$GA9Gh=Y5LDR*u$dtR3posf97u(mFMOfIM48g zJz_M}4I>V1dzAteK<17I*Pvg;pgw&eF*bjRoV-}Y8p*4^7c|@<=8qd^Eu902IVWCO zPRHD$2vM~b^ZhnN8%Y_A#l0f+WAOd!Jhy8##Wz_#M*aoVj+aGFj4a#_SKKePw zm=DqjSs~0}qkeduX`Xg%L!Wupg#8Sp1Q|-oOpUCvq>Zy4L&E<_oXt z{M*$cK_qkiRGw>afC%StN9)?HfkC46l+SlbQ5IdySY%(kHT`F|8{Ei4|JC5&kdn~Z zUZX-dWC>fCn2j+J(H$r>)?jcXX3a*6!-fm99ko8$&m7)k#QrV%0|cYM<<{Qu;#6o3j9}l^}sfm=@B(ykXEw#yi4+=s(FW~DNTKfHm45I}66~R%AUr4syPp)9{ zI^Ha^ppcB*&KIRfI0=0X%>O$1CW=Atk*PD~`YD)*7IEA6O{})_6G77jRzJ%5<&ol4 z9citGYza{OzBmSEqwCfC$9o7?;3M>9=!}YF^Hb$rWlKRU!)Ok3t3p<*rpD~ZAtu-e zb|H>gG)`L71tkj&z3-E0*XyVmbO%xi%H<`p^RYw=^pA=xT+o)mU|>shu4s%>V`t3Y zKVyCe<#(@j+<~`cDt`K1r=`-C*V2e|8ct!r@$><{MBw>b?fdQ)L$6y&_o+FXyIdMd ze+K7r0(@eY)53Rtf(I-@gf4LJ{bGp-w7oiy2QQyZ2m~Bh+0fonJj@(t=4hCn$Fhp@ zk~XR$QXFyhm|DBCK_|Y*sKL^rkI{{n3tHydSF)C^*qU@=6wTlB!SWOGhUxezA0x*U z9IDsGS1q{PJ4)lVIeKt?7;w^Q9KI}+zACdrH{OWUc`YS>12?hf-P@?}v~Z=Gnw6E% zrK>t!H+(T*SwL_M1;h|5QXV=wT6AV)hXIC=FA5+K?KTU&1ZDUkkxG;5W+~gPZLvDP z->N{h1=LXL7qI)PclXI&EBsX$ou(ZC40u`8b@z$J7Yu9*(HR{a^>ap2FS__Tq1*^M*IP_e3rOFba0Hf zx0i?ha~w^Q=tfV{s||?Ut}KrI!rHtMs+zHY(N5;b$vFyH2^|2IsMib5n25pv1765& zAj3)?X&Me3|DJ(DR2i=2AcMEg?g>_qbC@g}NrgJPMF?AQ#`uyP=x2xO%aVC8$!f@@ zlvt?&s?%pInQ-R+G0D1`|Lyee=k)KWWfqR^Q(AyLjV7wtlFt#0L`T#l#DV^NYvOG+ z`L48Z+@z0UAj-B?aa1&h;A!U^OQ*!`h)gz|@#(tWs^8kbVK@EXfM)XotGH zLc#b6t(55gOto=hp&3Lmm4bv5=P8F+e)@1UJyv4o||k1;bvc=`r-~VFKm&f`{Za; z{-w0`^Qz%y1iy4XalyVkQc2uY^J>+luRHUJi>&#m8QDgLJ%88!m=6k(rDFVUZnab7 z(ofR#=*E$}ZJz%(u7V0iY`Wwd2v~wose<=Sta~qLB#FMj+(iu?N$1;B#1P?;u{4R! zm0TYSU#q7-#Y5@P%Wb1@Zn52&0P(Q2D>~1rB;u0EJ`dHmP&|)wB9h+`OR#&0SDD$N z;o{oDLwM}YP;$XtjWi+9_=+>7fE8-Wa9XC&<;fZ_W&s{*Y0=d!1Zm7=-xA*tJecw(uStd>cl(MQ8H82i^)+h^qV{ zS{w(AEOYqQfA}oll$mZ1IaIa1Yk41`m7+#D^I0HeYYtRVhqz02L18#eN%p*rD|>uy z+p&5XQsdEBah+TU4*1#0M398V)H~vTQ>3zXuoZ!!N93xpIPU`^dkWi_7 z{jbR4eSgucMLq^04&#Xp3LcPre4v!Yec~!FLHiKc*%6ceRyxrO}+P57sDoAT)9^_SJ3jfNZp zyZIB0{9XXvd2qUW^Ho;oi}Bap5Q}_zZ+OIk6Vp0xSK)ai{>R;{-~L|jS9NVEHnR8o zUoGy-+gCOY&V}X831tO=;nj$wmxYwQt}s{1i2QSJVAxI}QLBHZZAUsNI;at3WOm?- zv-5e+l+EBuUjiksJp(sm4m_giX%9d{K%vu-c$TO4pcxDSY8_;rk=Ic};4R@#A4dW= z;68)z`+eBICh~Mak8cW_4(#0X_Cjtmar_RG!(c_mkuyHWq*0C@0BF6FDm=f5is_B^ z^SHRX&Oxk4%k64Y_3#N;`}Ns6rJnH45GqdYEst?#5*L??VqB zf2w*lw*|;dD7Z-Olp^TuVkCTn=f}^vh|!_xj|4N04oA^vV#_U!9g)};r#LQ zc+{QMczD@E;M-?^w9+%?agrlpWWz5A%KlrXckNC6vw%b1dUpwGTCim{XzR$C5z?J9UT56-6m1_A2%0_;AbzWRF z#ZjDge3ll(P8Z_L9@orWos9u}$|rluBT0mDp`lWob6S}L$SR!S*bXG(Kl6iS#PCv* z_x!m)z9BC=6YFciiWohif>% z`f;`=Xrg!UCIAvDWph~@Yr_bc(2o!IN-0IN9Vf;?#bF>Lf5wIuC@ze^Y;h#Udb=a! z0Miw|NyFXyejiBXkqKn32*I3QlhWJ5p0+)O(dfvP0LuCzgSzi458)BA(1BzYmb-dlL=d#k&RlJOKG3T!G{#yOpLc( z)B-#nba5n^EpmKvgYtK5I`%5~u{X-o@`KWCrot75a3r#ZcYvNox9-T<8H-qI@` z#tUN49yA9Igyw`~Fi}P>|>tH4=?rn;2Ui>Bhv4e2{5lVHmc4r(5iJFvv*~4X8 zLS>mFxQl-f7VXPUAntBm>0frIBA(S?CNO;1y=d^CvqV_3ZJB4{%mo6QHKmZ{f^60U z1H~;FsLB~aK6`|&Ky~D)blt~_9l+r%-_fCi2yhs|jt!qKo}wa_fRp>h@LOCR1@wIx z72w(uF$b@TfDsqMUv+%%#tm=cz4V2bVw6qFjd~)XLm_6UvK|dH4Fk4bnoxNuU?W4M zVND)oSk)eL_Wl?Y*HHxpvfwH(dbtuI3g($xT7nifGYEW82YlQU=-m`44LKcva`yhN zsPzays&Ta`e)ym4c*Ok*NILj_IJ)mH4{NsXeA&nVJ1Dl&?~3|j=Ns;{6qg|AiHQp- z?g9Jx8YY69j3Y$n2l;uG8a~S#nshQt0j8_lh+;MPeoC9uul|O0cxsG%_)ZLz0+ zRoUZB4hrB?_d^mSg7F?tE>CK#HU!&wouTKu9ff8pV77f(Z)T$$IN$d;$<9oPo~0c- zIXoCxYj6Erx%yAp{!bR%0A6f>vS@gC_iqm(n=@M>?9=KL|JVeq837cDe*du%=KjQk zq)r8s{FK+PdHH@0tq__tN~XUt*2pMcr8AyT9P)wxayz|pH6gh{tG$7^%c38O51JmlZ97f65|s%$2a^7gi&c5_&41 zgnnzv9?>&}FYGa-j#v~3nTt{U=bSdMvn2tMY(AV8+0W35h!scENRISsjT zvteb8p<JXW7{H!45XvphXcso4#|&G571VC641Zpr-uwaxDOSM@qO7uE*!OT~~v zz`BU^O|@p`VB~Za%4L@+glfS5LvY}~taZc6*2VS3e&be%*wyqv%_|{w(#)S*fh3H$ zT)m$qJEcu@Y~~}`x^~bfdKjvG&VY%`(0H1xoKtK&>gjcQHky6-WYiv06M(5~gxxKU$%_iR zBP`A5dqEYV>9W8O$&<$ub2MT7>Ja~TR(x7IyN|;h0pMP2zjE{2H}g}U!J6ewC)EBb zC-%v$V7&E0(Z&*2QDH}$as{bHl055(K@MmQTOt#O+-v5)%4@}E>4&t~z6(!n}4U(-C4n3RjG!(Whrp*?-T{Jy` zGh&Yz5!t^HppQi zB_c+b8Y|0(R0{QA>dV#%{F~FC@#BhD4j`2uGf6-1HVA zF+eWi&)D%l4sr8WSz08g0$Rb%K9^SAAn#kTK;B&OZD)#rgMvbosccB#3qk))Y9P&A zY-Z%UBl$YFG81L%ey)QpRnvK#Fa?@-6SE3x4zsVUE2_4iljtXo(HfrY>{XkK8&a5? zMB2q9c55s!sO#HD*EeIg6w4hERB=he0okq}tU{`a=os}52%z0_H+*=nOLzLG+Pm|h4+pMGU@?uks3TCKcvL2m%}LU^Bn<*J`p5f#Dn0SlnPWz+L!B$vcwH(!OJC%QLH&iFH_K>vDOUCXOq^(eL9&WIVK{HkUM!-OT;2M~^qXX)tvl{d%N;>=wn4p!>`v3+qTIO>+cthJHkLX_F zX0ymdX>6dt1jC*;_?|~aSP7IVb^AU(HVIsi9Ga`s@K=(jM(Sl8@w++BMQsv$nIdOb znBQu|=eFP6A5Ah;gY)EZ6}6SQg>~uO=j&J)l?V~M1t@l8qF;A|OlIqkI3KTj&|siT zIG}j5uZEhaMhr~U!(v9=PgDaHa;4bzSkEKeB0l!MXU<kBw8Q8pzLa0o4Q7O!Cgw zMB9Fe!6LUrxt$zv>3w3H$6)El;sgLUX&y&+U`FLJPlyFJW4Ua=YqmlGtGrxsJ(#$I zXT@d8lgMJkV!twV#9{4f4Q7AsT&CY{-swm;|Gt#|m1KuPNuY@#Bd5c{y!_65;)@TX+dAU}yH@sH})S6OV2yL^t&P9+?ibmn?TQ$Xi@?%E%8M5Qh9# zhbM%Ew6#LD3`e~rVbXfzY^BH-g;~zTkvIuybvmL4fXZ=3DL&d`{Jj0r2ZQ_#4Vyl^ zT*hW(PNU>7=F)-K==v>lB=2u{ipWsJ??M%$@7#ysT;CZ#A>6K+^ILH9U_it5^^D9p zcobMuY0fMyyq9>2y=w%}V9(DMWBb6)xV4;97p%Bla^Xn~$S(Akwp zrb?$V$_e)X7iGyF@Gl22maP~8CqLguUUus6Py0{F-~re)))Ni8#A%J#z4-{53+bY zTU*JoxXfSvbvR6!b@j|qK`8D?oL3v>fOK6;?$Vjh!VWLfrZ`iwIO3g?^wIlAXH}P{ z^5?F}=g%H6P!(ORV&#(aUS+k$&NQ{C3)H2!K+${c%WSticw2t@$vDOL+jv2#mAU6u zVV!7L<4bw&mB$KKU^jf^Mn(9Y*zlPY5(yaSyhXlxL`$%;sXxuGwbeDMN9n*}t`e}N z%s`RgI|(yW0^6kzzuV&shDYX3K?DPV4wY${l{<(3Y#0c#^S~6k!b1gq40b?HB>y02 zgLb-BK5^k(@(thM4dvuQ#LD3ok$p5z%dt|CTy0D`B;BzNS##WS{6||uB5xUXL~h1= zQgBQHA4;?cNki6xB3SX2btFWXGq>85eMeSQ>yuTJmsybed?(HU{Mq|_l6x5C_5})% zaJkDqsTqEE0H0q91r|)!iyW--UW;@)pmF-0>v>#g0j)>cf%}Zxvo~Gm?4Y|@r#}og zY<)i?qh3w~von}kR`_F>&h>k@3u)`v1++35N` z6={kK^n-og^0t!5&b8Z_)}VcR*`Bs5?B-H+&Oo}U<+e3Y>q>3zuUNj32MA@G+mmNN z*$Kovj`v9glm>M*d^~i<<ejw8h$9E~px3cgK0Tcg^joj>f;cBG>lb7Qycx7~aP< z`9~E<%EnkGqd+1XgA1YOp}c7H1y>%v9ukR<63b(wT1j@p_<5(*yO^<_0vdyR3UdyO znX#5)Da;n0=*6F(lXN^Vujz9~dhYxnl-s3_!iI7`IPOdE6l0h=Ej~&F%LYxO5p@ii z@J$!~sG~f#ijo*eGv%ePoZa%?^#a+|8*>i3ve0YjPI-I9C2Rs2eLj5nfYpSilQ|ID zeBPXXns~biD>~6%^R^8+!Gs8h-2XsHkBy)^H)x*1Tfdfe9_-v~3v+O1G<$*>dv1_S zv3rl%XP4@zs8`YO^;e^t;q^@svd9W|6%}soYRoyB;Z)5S$4jsjK6?z1uQaek{D1}p z2%`t}UlVz2MabFS(iTFmU0V)}R|AT1q*=K$*j)_H(a8ds;ep}f&Zr7thY%Ijkh24A zRr^)>$|+dMGK?%?(}~))=LfZ!cbb-lS@Doj6GMbwd~e@V^J=%k>!~$8;8mWL$45?6 zCMCrp6G;^QD9ETQNKnx0mW&sX*C8@9M|OYkXlsWB@IaN>b|u!S7<1d7>~x2%Y<(zr z@4XA|DcpERKLgzYZ*EJAGlzqAFD`$a@wcz$ zs~~5G$HrvqMV}OB3;v$Cv2+)~;V+I7fR$YjuQoD>M_-9Z7|}a&9BxTDS|hJ4rZ$4| zX7S9fERZs>;0KcQ(BLSb-T9&+xo7F3d_JHK{Hl};)DE`4EH$Y3x+ znndHS`OY4)uRR9jVPS33)`JLAZxhn_&IwXEg3f4DPX03AC9Uj`QP8~$;1@-F2ZmOt`*uyms+{2QamtO z^i#eUi(AFGt#FR5PmJAZ-ykX+1b!=EiJ)yhnBXtdiHoPdo*g{C9){Dca@)>B@9*~s zuSY3p7aZf%m+n zXt`fm>B*SNSuw?5oRYi^fZZRf8S)J)vP>w|rdCud0eBsj3qC$@3mCUzpOcHrSZ54R zz977xuf5uD1UVk!l3oWN1#3N6%x-GzRgdfMNox%x9+`rcn8DVKZ53y2{aBy@NJ{5a z^BR_v@|LXdyXrjRr7Io_IqiVKtO~YKY0sr4O>r+`BhOf-i_2`9L@;5=p(=gvq4L1R)_6xNEw12+gZYP|QxnG-$8*qHN*s`I&l~5||#Tl%4l;Bww9xKEp ztB8n1sRK4!W2!cTYNMRl+@3@@o@F%;4}ibT`mls5VXLBt2{xw*zh3q32Xj9ltDSN* zf%m>&y9k_)!*3=1ak-HzbsjgGzQcBy8D{{zEl zjQL@M7gLU*p9v$WY4i{7KuR{T-fZAg@Ah}i%9v~rj+iOfM@mD4zGJu*cQnx)>T_aGD`A?-1%sMm6!Ohq8fwud6NY^7dr~f}l z)MR8TKAr$i%zAnpeHRB8TP~z>_nG*=i3O@SY6uQXoi|^M44^BoZ!J91Uu97ohG^dM z@epoa6@{Pq5fHAN;nJsc8ZRnASF z6k+pxvb-mOOP}A?tm};H!txZ+-P^{03kxn0CLKLDrkxoh3>|roMekuq_RhQi=wgTc zp>-{K<%=E&)_CTbeDe^>*%h$kdt|3HNtXNmf#trju{{&#>x|{PMB}{JP~ zlmH}EyQgLcX^^1^e(=~}X^(SfhcnP-9m%MOBW^&Eh>*lsE1$@Uxmo? zowe5V2mR@Jkh~q^9HFXtFuQT5)B_&Vx1%qid~K6j&!$c=+D@>Z z@Ar_lrpD%wk7nez-vF)lXUdG^nXB^iaOEXog4hQ6pLIJpbU?u0)cc4ypRCHA7hD*& zTF<3Q_aj=}*q_^@5?^~p*4iEvxv$47FKf%tZCA0=-jBy|j$b1&UAJ!+uUl$B0V5-i zw4V~poSU~7U4Z7=qk#9D15&>`HEXZO-ycke?6n>)*UaB;K0)cpAW8~^FZ==BLZx75 z$LRNz>es(uBJ*;!^Q8m2aA!11_vIq1b5C2~F(0YHX%un$E7pz4Uf*9B`#$!$Cn##R z6B!MUr-AaC?=&euisWC?jKq!;^nQ=Sl*S4FHEwVzWDEuL#8%w{vwGKM5t7R~ynf_( zGeG6~^_ApTaioeCODeGqeggd6#Xn>-R^*e*!Q{Y z?)Hq)Zz8O5Xnfv`wxbX*#ZnAjn3i{ue@pkHEj(C3p|QkN&1h;A?N_mcxBm@P%h{xq zPF!mJAP8S?!`eXEyKP6ywGYdg+aoKs?cc$S?nwsCvp}!h8X6V6W1iu^(e?#A(0ASW zeSrgCmw-i;-C+>(ROAXqxN;TGUxu{6w{``T#7b~Zgg@bGu*J0A42 z-pkF#%eNAKAAfWoI&1fbd%p|;NI!QmdhfKVG`cfNbv>y;@ASTY$UV>lKIxs(xZQst z0m=Pjw7TM2=&o1Sxa@25#+;Z8gELBjt7EkV-0aN`@^z_Xrt4R_!DU%d5= zZ{a(ezlFEJ#0E|mY?=^ld^&P$knr9gflWy-xD2HJr7?m54t>|RFx3&*@U%G{YhIa9 z%}O6YlE$t7Z+d=(MwsiIrRE|^s*SKAxjp^MNy$eat_hbjV1_8jkak@{2!#-eNn0nA z7Lhr^QV}sR!a_rH4n$K9J=?#7^ulM5Uh@)?a#udb_6V-~;P420c5GwEj_sszjVQ`J z+@IZ(D-TajPOy3NW_%T}?Xm3)j|`C|2`bG9)-2_=&EMnfr<~2X8_prJ5gX1unNX|4D!e$kMf$!pGUm7m#%Ur z*I)laZvEQSsDrDozKZkD%PBjVo%a3P7=^^w0q=Xq`*_{!Udx(Qt9kg5M;RL%=f%JN zVvJ2$x}=X^d;atJ#;sGwyzaVZ(pAojG*?`9DZBUVKH@#zx^*kNcJDze!RF1InVg)U z7DYVz$YXQ+@}A(ZHYF){kzQ~mm9sCSaNp0L5R(i~2uhLdeiXB29rl?o$1YuU(tW^i z3OvB3(eu4vhCyti<|5ieNWt@|XSGItC&JG>a1Mk(%aD|a;rbBEyd{`y>NpdoLbmKqKF#H5%2Th|C7s4_ls@Yux0fI?T~NyNAvx3|PF|zltn%kgPp- ziq)UgIM&38XI`_Zl>?M%l}($T&Bd2o#OPQq-M?kaFMwR!^wq!nDoW!iX0nbbBLR9dvef5=AjeNX{sU*5?4Y;>t^T-S6MnI{)t7d-%#%bFXrIbc}L) z9!7=_48Vo$bar+!S(%!Qw_@e;{Ii>QMovznFv{}(|KtCqz0}S#pLY!vTjk)$0G*v> z3^u=~%A>2NlYxOLLC&7;sg#KH1=bvSfsfb5@jTtSCjc*h*~=(*ojm>NSQxeAtzqH| z9ZlY8PzVu8mDELeQa|o9k>?6OOAwFz0{hID&x?mYF9vYBp_?=nN~%CQEu2lA0ntcw zONsVFOd3<0i19-~N3n$SC89yF9UU2Gv^vHaE7meuAH{kWm*rvalD0k`eBdFTbkhr8zxMoDG3c8k9l!e3Te$SnOX=-h#J%_4$GPWj zz{Gjgve}j4oFyWqVyXlpphtJ&|M1&nYd4bg_vbm7Ste?InWD6huN5XStX$Dg94EZ- z4{t;vr!))!*;Q=4Z|#cJeB&$Mpy;=wR69Z{9((jruD||;04SYOGvick*NpQ;^+~ip zvtY1vML*+{6~;Y5Idw>-d1TuTRa$ihA<5Aq|d5ltJuH) z0M%-ZjxevrKJxHmtUhD;agV8`Zf!(TX;v>=MVcC3{rj(`T%4K1JksEyxpF((m|HLM z;{oFgTyP~Fx8Fkj8MAu^78;cDaJ#o5nhG%UfRi?WhkAEfL24{kS_}@4nFCMiSuP## zoJA{-PkiDZ_}=$!XHjnt0|y2;^UO2(lbimSWqr$eY{!4`$hPgQKVv=ZKp~BBS`jE8 zMhixh}&+vopNU<8_z$NASkl_oDKZ(o8H3nF1j4q zRbcn%Ft7gI*PzFzyr(OlaRnd!=-+blU;H&!Uv(AVyX`joFyzWBp3ZP>fCI@OD}#QH zCr*}GL%G<_i(mR8-u$8W@}?Kuz}9VB_}W*#!e>A8Z^!){nKiuq9q-`UXFrGg9=xAa z8CEY|#rpN@x%%p>c>ABdgWvwmm-EopZQOO|oqX=|pF8d`dl&aGK3U_rhl{UaG)W#8 z0f@Q6y2hA>?xl08{7#4J>gswo=#ASIsFF98MFWSgE-u^Z`FT}ZwXJ30I13Px`vxgsK&+rK6oU@)Y&pZp88C0OT;3?;k z$$;m-;JG~f&;#7{gCDbO*)rbq?srnns%))3LLdXmx`Vc`1DB;NU$u&r%U5Ddf>avm zX)Iaz(cv+^f7=}hDR|F&-_4T6i*YU^NfOqav6{Z# zT-Geh9KILulyf(rwa57voXdB<^*zQXCb;OLi@5fhO~gsU9k<`X_U$`3W6fI5Ip=IL zV_Kx)Uv)SKvb_`i(9aoPxq&^CH5LVrKQm&sP*S1FUGU>?BhEZ;M$UOU{_f-daNJ`x zCqT}+6Xc%ze@L4MTM|VEhelA%B0_w$@~CGKT4=n6VCHl_mWL)RwDYmQ{X3TTFXzQC zzCI6EwC34Qzn0H`{fqqYt{-y$y$^8lQ!nB>-})}^f8Tonc;)Z>58nIUck?$lf0Wm} z=G81;xttfj=mxHR_H$Ubcrl;+{O9DrjcnX_9$)&>mwCl2e}m^g=Q=+BxqoN#ZFjNhqKoH>WJ2gENppSDt0>&tKLgi2CPCLvW6!w{5g6*}r!o!yf=*&gko$LpjZ zL)NvgYn?AOF*Z$F?RYSi^W^hCK)meA*7Z1RF{X~t0VoMJ%ST_P$zh+NS!s@JM5sd2 zEFp>_LgnTBz{dM0;|duG<)C}&ni~0?=@a^{&XOH=-;OlS;8z_=d3amyz^-1; zaG~=F=>cj#M1A`+WEWjU+R<~=;>RiN1o0ZxBwqxLq<a@)rSE)YHws{L82K!2AE4TBX8GFZ&;q`h1?cYANsh`2XPr z&wBy?^!NY5EuZ;6$ev|9_1aDR;hWyfvtINfgy#_y+i-0GiIhmC$&8_6X+JNx{?}R$ zpUoULsj)BF%kr>~P>Jhwh!Rm&WztqCr~s23LeM^BLZ7Xt zhvl&h(QyY`{i?$_L%i-{N)O#l*9BKTA^U}$%aDaKwyO{3X@ff{8qDvPVc z8W}IoseHJOvka!gB$+wvy#PW9+6$dH>)5k!3Li@jb7 zjg9C?Rr={LNtAbgJbEA>B-Jo36fks zjg7ISiWEdZ-JVz!awH=sGWXxc?-*!O#sKv8hiA4NK0zRaBy;o2^_{f=Y=(9<7vY>m zh^dF&;HbG=x~QNEq!@%y^m;uMWjN#gO*re&(&ryP{!cvp%F8H*Gpl(odGU+**4J+3 zTi?8$>#lp=QR9BqRwAwC-pk6B{p{M7OT!02kq7R7fHRh_K(*!J-Glc&NM;T9{^CAX zuU-v6duN&b0|#2KpK<1yho7W@Fevc4-@lQ6{?||PvA_OX0JO~I#OJ%uROIEpYCO4&`*!FrwqFRfH}o%``V_Z(?Q2X{CV9#QPvI?Ze_Lyyc@yiO z^kfD{MmY1VGbk53T6v{Iky(S^wFno-1PFffB`@K(Uh*ayjh)oY&XfGp=Sbgg>QL(q?eSr zec#7jBk4bxpA1lxMWo166~`m?D$hrM;m4SRqwu=toYLIUp_}VMlQ8>bfRX~e<6#Ip ziTW0w76Ukurc9<{&cmma^6(!11+KH3c=57%DT17I2z(^SOyZnv8NbvSdj0Mh@2R$X*AWCbk3Z$*qsMkhuQsuHqNkqLqff53pN#c41tu<*}AvH0< z&c~o{8Kad!;@TKmYr4A2RBL0@YLhdrwYN7{F|Nmz{J3!iAtb$vdN4Mn9#@FsdVYKp zx6T#U^Dc;`%a+hyDv~DA5j#wp2CqZU%>y(xC8|%7yyH`dt~Lz$f*nrBNS&piLOR=u z$iUIz6{x3T{k#wsqerZ>LgH z5Xh;GQa1X={~PlNp-HoZtZ@2rfRm|U@jPXQWPJj+XwjV7-=*lr*%q}VK@QI`inB(+iNF>uaOHpMLCl*azUvwXuMn-P!_S7 zrOgYE*k&h$nqhpWhlz-Ud+xc18(;s20DSxtALYCa8?ZJ-TaTB%im;0)6b31pMRch$nX#ZP zGSfs@Ivc->vJ7<0U@}aHE>X`Sytu|*001BWNkliumJq?-xu zW`3>J7u?hYoHp63*)lhgRp|2;;fsK}ty2(rZm)UFc3ouzNYV~+5~C;%K15119LWj zO%JW^A`syWva^TAkm8{kOor+8ds^>l8Zl33LgA6Pm=0ND#Eel=prma5tuF%hr2{Mt zdoZ>!K*%ehQ;T=^cd<)XlRo!lgxem*7{kRET+GKm@lhZTf#(Ya5rP8c2@WPBl>7oV zb4Lx;W?S_VN}>MYo4DsZ1@F4N6>Z}F9mK1<*j9ajG|j_!XBHuXo$Rd@S?V8t?o3)V znlw$p(+pH=boxF@<^zmsqJ}5(j-BJdNkLZdkeBu_RyB`X2SIEjgcJy&P*NPzkWD9t z7j%frV2Rgz8n1R?W46K^3j)rNmb+kl1dgKqbTXLra-PU46sB?dnq0tw2=o6}24iW3 zz)eF|QippBy5UbW!{!u2x9-f9pQnY=`_ch=y&h6POF?n#&vC=K06?~OBUyhxa^xU3 zsiB16ybT*TZ^MQY`aH9tOEeALU_8W-8KErN(Mr!7<-#NpV(UKq*FV4Itq!b8soPx? z-D-T5dw>%Rfi2?H5ZfZdT7OlGiA|NMk8`xPLjj2m!Rds}L9a%igSn06*(SeW4LxDds*r)$vssuK1BeYhn{=o`G|kN6V6-HQlf!;(0L{;Hgjx? zhNvel_W*U?sWP07vD90FZj2f*)=;+*ZF-76($g5FSx*G`Q|CMp1E7_M7(IY@-qYvZ z_)VB2^CX)EFh?%1(Y(%HmGAs95%?adsUMbyl$oN(>w*;g(5LK`=*r3%XBf#wr^5Ot zI8JuvvP~1B3$8%_{6|O;B9^acwKy(hh|H07FGlXzI-7m+p<=7l8YJU==>RE)s+)UtRA^21&>q}#Emx6R-X2NZ4C53`K_cBsX50CYbXs z#e3){=%3z(!{jra7dV8F$a?*#!?R8Xv-SWBs(^D*t0J3Um})(MU8+pgRFRn^kulXQ z!k4RCjmr%=TVc>9vVB% zXb8KA?a>~3RnLr~($OHDCU&#)9E4J+N`*|RBUTRg)(q{Qqr;p1qMS?x9f!QFLzYlt zYS{X*K9`3+qW3L?qNIw{T}0hR?6P|s-7g;Z)gQ`5IvQSfhbo;A9cZCo!a%#P=bVeR zHlu#k^~kY7ia+^2)l06#^YZHOLRF1E74l}YzKw~CX%it@iB_HtXyxsIJbZ0Vu2i{q z*X;ZBWT{1usn{y9h-oMHT(t6-G!?qNE}T>p9{ed{e3aVLubaAHrP0>S@E{@I9RQF5 z&(42t$7PPxnbw12Fie;VD}yo>stnj+R;rVDkfhGLQGWU;-nnZq#~^r)+HumX5yPq~ z*dl%YA_C7lW*9!*Q9A?%3Z{l zTuIwKcR^bRu5%eIUA8cDgPFrDUxj|~XYl0n=SA{t)*)~;i>TXtP)~{>aWTfG6h$#7 zDQ6L*cD(gBz>HiVOljEpQqwKU6h)E2bQpl%pqF6h!xV4-3RzDd>E+J>a>JXr7@IlT z8U>f>a3;<@l#|%K_SOs&$BCF@kr!yXb*`s3VJdX%PEu!3A`iKa7e*fmf%Zw?^=YzQ z1H>;l|CkG}o<%t7h+rpMCBaFx zIRz5>+vd&@n~r)G(IyM6jS67GPBLLDgamj()9){By=GjV!pP*5qR&FcycoY}5Sc@u zaTjdDbuL5ixDUB++hOAo76PnIajVY;z`y5q+DcsnN)jk}(&7lSUV5gX#?th_JT#fi zTDiVZcobzWjOkRq<4>AO%YeZY#l=InNX?zPj8+hA{sLJL5?_5iNzW4MNrjq=5JEAY z<~g`S7pap1ec&KTXZNgCF5(Qf49^rXIFf2bni(?Zm~40zMb(Bcb6U5Pc~x?@9)pu2 z_mD?x`0x9jW9DHdT!o!+J{_$;D6=M9PLJ2gq@6^cfFqw73#piO-pFQ-Z0Snmf$bce zCc)LjY>e0GsJb@2^wg!)Z5{$om@2g_%KKo2W^b||Un+d58lxHl4#Y!ji*~lw_d@di zrsqHd$-GmMMCORI6w|ku=xNVF?|w9|5-&i>ER#gICtnC-!-#+TE7<&>sM~MJIl+E7 zYeP8eTUkO2o2LzS&pZ6G87s5ONu-8*I8TEv}-}T z=O{4qMoJ-wT|$r7#ermy)EbnKlqjO5MB4w|@)Q)yMcVu7glf%jzgZUgZ-Z zbr;d*h51x4XOH?Y34Qp29ZScKTczFD<+HY|8Lnp}t_C_jtn!#SN4M&rmeuKOhzJBS zpwg&_Cs{hmW^qkX$e$~gY86|ZFUn-XPi&~n6GE*!M`{+<5miv9I4EiaGHo8=qPF2R2 zDwh>wD$+StNL;rO4@Hk1_IHQACpk{X&GGK1%v3HJCgwL?a3qM#;jATHcL~8QpT@iW zt9W;RcU~*6Cj;$=1PAt`@AxKJTqS$jHHe`hTo&V2pG~sq#RwU|vNf|i?rbll*XwCL z)G3C?;+?GY`}0Mvng^Ytxik%6^Gj~F#rX#Z2nKhdhXyfEzL4tT9)yKzQbkEc#Z(DJ zO1mx*;^oH^`CQ;0edO_k@(Aj;)ESnCeKR~f56y+eb6dG; zUj*D&e~5w%SsNUA3}``xoS{~=jywGv({ZFx5Yw^H2-()Ac_C!^Zv&uz^6l2l7iVIG z4yI}o*$5QbYP$HeA32q9*pcKTedo{DOig+>%^KLrepRqLC|=j z)FL`B^Og{2F;!7TWs0D&Q`9pvqhmyQK2chuI6RD*970S^lC54(^_-`X5`nSQT}nNR zawF$;qS4f|e8z}}X4H<;p^w~u>s71RwvNMcfX5=f7JM}$)a?xIkC(nU6irgJhh|M-`BATLWzc`b*A6vQXBW?G zZJtL8iAU{tJ}dYnXjcmz)}~-nloZ&t=hAlDmvKQGcp6fJ>sbtO9;qd(*O8VN%?nY! zIggvnBpOH3{Qr0`b2`w9CY@QJnLmdl`3JW zNMfo4dit=_ zo)fJ+ykhUQGGMs6H+z2K|3qK24hor(s_vC1GsV*B6F?ww1tAxA<@+|ey76d zFGRGw!BFS@>Qa-G^FmXEA-v?-h@WnTHD_@YA*LB`wWR(>kg{6)~bwqLZgJDN0#w)fW7q> zh?{PhS6#Ccfs_WcrlaB3#9GbD6SU4DdwNm(ccQx&W3z>q2aIfjul)s=SNml^GtYNu zzR!~3RVEQa<{>j`MmRiuWT{dfID>chcX5kWkZ!ype@&^WPLIsZ@b->I4$Hc_=G@mk z>-Xm^YdMLzLzL){C3^iHJRP*C2FmyF$A$=ZK1NpVVmuzEq>A+UGra|4(-}sfO@vr! z88hSgWHY}^#h##tmTNysDB2$@L)5@YjD7AK+Xl}P1G z<2!C9D9A9MzuTD7W}PLLhO|LS)<1j@;h)~hn#Yl=h$l>s$qdQLHBg&CjvQ<)?1h9L z-TB|f?>HE>3C>)GJ9qix)^>C zx{Z!I*7KJQ^BKB}%t7BWvZM-r5tSumWBc%S-Pih?FzmpUI#By}A|^)2maQi1UOZJe1w>LOTe^y@r;qWzGbqH9xHO~IyBLw#DFtYu zsk^Af3ric$L%E@3VsOM+oOgsYoZgDfl~0am{G5sNe$|t#rdC~zNn52|H8@~6dc7X- za${E3?fAlHe=SdS%*G0r7<& zW65Xk8fT8`;x9xvDUkI%CnU!Pp?qYTQHo(G9if&*M^~pg1amch$10wE;E#B*Br$|i`UPU7aaW@hgJKKN5= zS3HkIrg%C;rxxn~=SXcG*WNH_Hkx6$JT!x*O2G>oJ-vC{6}uEGU7jmzczcP9kv4z5 zIZ*v*P*R{Dd?T4WB}V&@s`v6ghhN15xUZTHPe`_?>WfW9M&D038e6~rF zB@|U#zSA}GViTr9*2qb=={6P@mmZN#uSwg5yE&HEb>Q&NS)x-Odeu)%bgim5h6 zF!&7kds`hG&2!aUv>?S2M(sGelD$WLeWA4UEkw-P0A}r-OxQ^l>CTqQi*>oD)SNNl zoNX;MkvXca+6sf4uQdlK8Ea5d5vMVerb5(MbWNq1Ar)K2kzq4OAoC&bDVEqJ7z}N)Kp+FO^pHy9L_V805PoaOP@0+C zAOZ?WTi8MPZ$H9(*@jSmrHhUFVn`M^!@( z%0cd{Kg474P9BOLqncG0q%koVmMkzj(y7LLF(^)|YEY12tJSTUr!zRT(5)dx(0o`5 zwCR9}hL>2)q8aURoqm}RkFr;yqzZZNt%1m;xy05qX{{qc=pdhTbrdCtOj_y`w-$m@2;Xs8MA+sUV%gmtL+y zEE}Q$E~88L;MWZLgI^_kXb)Mr@DvP_4&wwiQ`b$k$2TM#t^zeLT>q%Jb4D z`9y;W=iV57(nn~DoC36aAtH0FxxY=c90aLT;!hZ5`7HbF|Pb^13OiHrix?$%dg- z$d-VDFMQVetJs|!AP@mdgC!Kb5KGpQSof61HWW!M8I!g`Pq>KEKYbtnU0*@;b|BvU zaz=X$1N8$e@fRT#v=Owb+$Rf7&Y4Wfjl5L4p;CQ{l{;*PJ^yOFd+wOgDBmGU6h#{y z6d5z)4BFv&IoHtUfK^MxaAY`?0sA1Q)4dxEnzfK4?PgCoUIlp(_E)M5mE?3y!>+r-6($K-kT?<7j0DT-8f6lMHE#V6t;PW-Z=5d8m_*v2# zfiV}%`df@#iop@th<07dix+N6Ahp>N*VOzoE~1)6448b1*)o3#xV*aSoF#H8$gq|F z>-7SJ$OkVqr^D4qu!~5~~NS^$ZIUj5GQ{fuCn`Y>i(*{h- z74<~!9YVg_7-twTLv+Xzi&anVEs2~=+?)&294usDTzxkGGj0u&O>(rna#Ow1r^{j*U}_BRrx@hIaH`gE`Jv0l4nBLiTBgZn8ZGA zT_W>YRd3Q@nj1(#hO7yfW8CRAe)EZ=dCE^D$h3+J1JaJ3lTv`0ajeZH= zh#A8=*9w81v$+yXBm6a)VToQuNfl|=rPd(zp>#M8DgR%4=N@d=d6xIzcUhNxJNsPa zDt#f2uBFU1IRQs9njF0wOYp=EU zUhjIp_kG^yk!i3#6o%DknOG$4Hkr$Lu6UkGSd25MT9NpLaMDuxGWdp$w;@t&5hyIy zd9>1W37Ml-4NXV24V&gYr!K35Va}Kdn|8#g7CeoF#(Br->I_|(qC~{;Vl4 zjY3jLgI3|1g%shtaQ=q;;G1(5O`t9FAgTV)Tj(G8^DFAe-w52un>#|YFTVYXrdnpW zK~M^R;#usicV3snU40Wo)Pe{?x0&0NDVr|b>=lN!a-Fkg6OEvhC4JSSFgu#U0-&wO+dMY-;VO+n(f3`v56z8z$!#^KE@S8i?agcJv{8s)v>l5CQJYxL z>mhs85?X2Iq8{tjCWat8C7q-z(okPix+YzR8~gbx1k1kapwX0X_!i77UWa<-Fir^y zX&9S~Ei(?wYBgjfT4GPUh#)MJ5kc~Ps0TzSR-p*iH@0017*Nkl_uqbeXT=Dfjapt#esv@jR$!3f~YR1 zuaC|muAuUUJ<&?rkv`P98|y9e-6g7j`#*^uIDmNdeT>FW zuo|yWx{AeG)!Mj<%ok)XM+=RX5nb6O7IFJ<0PynS#qNfn+la9ym2NY;-NpF64)XfA zFE7J>J@8z9qHPK^=U}Tcgx*VJvxS4odOFux2C9={&WWBd9CZ$G(B1#ph!W}5||?y>TY?Rsd*nd zu_-YT9jLR1AcIw~8ZXhO(*`>099v?H^%gBtN?)>;ouMN`XLZrdx2D$-5sN0p+;s@~ z%$MNKgD4^Cs!n?iYt>nnqb02HXdf}J6HKk(vLqK+jh68)G-QDguqDDJ_WFB&koY{kIzt2%B?U)bq@#J_EIDDnn{qq%OGxKARgr zFn66}O6GI6tO@hjFES7|BC#C}T*A}kD}@OCHQm8|F%UxHd=(_Hu2Uv_)xVTgxo2ld zw6C$PQiC&=2xKIy+a8r)#m`W>hF~V0KAp{+nGSvOHDbb#! zim03=mYR{-Wuq%Z;u)-r$V{!rN5Q!&P*IFGEa?Tj zw;U@&GoyLJhB;n?CSoZHbd|pDvEYVy356>VaSXrkyQr;#;-|hdEYIs7<{jxOqbi(R z=}S5)ZT*A|24_7|h%f?Z@>b1fY$qflVIdy0<9bqQN?&4q&e&OcG7S?A0xB%j-Yn2~ zG+UGxI|S<+aI-W4=3*2Rk41Fnk)sXl;CvOBW+}Ox>Z_LIZ?I*;eu+F^)_+d)uTkH8 zhOacPBzsp<5I=Vmx4ied3JG8JPjJhRYcJn0fiNfL5JCkrbOePj$bCg$^_Z7Kx;5=Z z2*Gl+gu#afh6pC=sfp>UPPnn<4wrD`$DFCw+YhG6cINBaS|c~rQ(Y===;)X(y>{MM z)caL7WNk&=#AvdWGu1llW`kqp8a>rzHCk?Gljn3FD?FLY*|rl3S5TN7t#n;qOGvE3 z9ey7DL+`*v21nTvfsHjS&oLrQx6DUFmi0VC*(X&oN(7?yP!B+a;1|iDid|F{QfUeq zg7NXItGvT{=5uuC0eREcMgN+tl0z)(<;Yf8Hzq>Z6X9aL~HNud7QbS z7=-B&zq3@yYmrXb9nu?TcpT0<5|M;}13|^QUfv8;53MxYHY16mnx|JHg=C<545L0n zJz%riB#{aIbHE3F6S2_6sBoPTij8ucoC+Znxvv|n&oJToWM=A&Jrojo@kko-)7{-Z4ELKnhJ|W(Gh9LvaO*jLf}maQz0)Enwpfg z4s3;9yHGK@6DtnQMcg|tDe9;A)y^$9+225m8}5-i!&e8q6z#a{i&GK25Lf*Z$|)&a z5w!HGg5_w4^+Cpd;=-`Fm!hpb&BsG>o0F)B$SWp(5;DM=Od5+Y>Xx|z;|#+nbba$( zR1@!QThlsgHd_VXp`N3XL1wFTftY-z3bUuiRaj$~N*N@qWXjZKl&-$|U=n zFxD_}liK@N(33qzW((^b(uFzYxpaZyA3lfw#otEkTSETCyO_F=X$hg2xCwpLVatq( zd>G@C1a%STJ(1FQ4BAN=zcD2R*1L9_ExR2$!uVDoB9;+d)uAuXSMr^jDT=^>Ohp)f z%PHCiKoq_7lKUP@{?JU|;p{^+ZOZ6OLu4fSpdI^}eO7G;_cM-Dm1^Dq(A@$dKiQB~!R@R-#1` z6>-*VG7{S;ArL|kq0bu=TarVz{FshNLQqhh@Bzt$$_4f2W){}%y^G$lBWR&97$PE0 zS7!tNPHNV&HBMD$YE8qOOye2ZT~^`Z)HEz1Ma53)ez}@i~3fA@>ypMO#x#i9>csLFuEgM5}Mq zute2?D&qr{=A0?mm)wT1p+l_dVAt0@tg}cj>B;nhC9oq9h!^!-nLzPUdn(c1$D`E72|FkA8{h zm;VHL+Y-q`hnNs=sw`+}T;m1rr%L6B_f>bqPqlVmupgQtn=H;-xspDNWzy?YR%BtiXTXa>Yb!bau5}Fkh3}rtw zOPt4Rjdqd)>0ShqiJNdVdxl%%TUd=(7@2J%rzt4t$_^v5&AQnj5)pSN`$Hy}^zpy< z*A(x51L5rI>m3LXNGegV z8n5ik1>-Sor@fhU3A4%_l`!WL*3Bjz9kS=l1quJ$S3%xgYLt*}!GA&H`wlsjg; zLGOJToO+JY(txp@TvQoGIt4c?uWg1ahEKaUWV-0;eSw9da0T9bthDrf7l$QtISXcv zT$Bi*NL7k;4l6wI3#I~A;-%0{u2o}v{rXV!F}6C7_}nag&y?%*qF!s9bh11}S9JpY zrp7P|*{HE~=IK3pah19CZL-xximGCc9(N{tLxyLz>FXX2N8k0xT|q~t+#25!l%Jyx ziB-YJpOU-hVb5KbMaK1wK#muoEP`L*aEFy zI(c;AJj6W)r;f61G!>j3`3bGXsx)a@_c(Bsc=VTxkN{Gf~KFGLrK|ES%mXc!V-Daszw8C*4NajcIyiQbW{iH9OwM#JpaTe1I7R0iUQeiilg_ac7a?U-zeuQOloZO|&L19Wanx+F|p#%i?8ax%}R9Z|R-_&W02 zoTyIHQ3)NH;;cDO=diCjbY#kEyn?Jd=&^`f@rH)xqD7dw9m;+?%dC|Sp2b4Z*WvpZ z>Op-yqTS|dYl71kp;zdoz}4d(!573*x=`zzVTP-P7dJ*-=&A#t_L?*H9DUVc>hsXt z@PYqjox?iIW;trRf0eKlqNwRB6&`yY@23$~Jz1W{I#(+=PjU6Kxv7JV?UY;NJt082 zFxla~r7wayb0fGaow}&tW9D-rq3P*9T4`3}6$)Q4G2_sLaCObn8njM`PF2Jocm(mc zUJ37dE8E#-Sk4n@EuzkZD?%Xas1#9Ob4MhM%D_`RU7aO!IZx-$G7tmCCMeEGrP;J2 zw)~jP79l`;OHXuJP(xA?L|bJ&-C^)lKFD2pzZ3Kd>)RUOZYAiZ+#sF8SkoToO3>H` zcrH|^X=Z-URA(=H4B~RgzKFB!8I&_x9ylMJ0{i)_NAVO%RnJ8AYMw~@IVdIzi zowVe(pudY~-2}nlw^1@RQ-*rLmJ8D^7dvi+A+>$wUlVTBK1z&~1`&{!2I=llCy1c5 z(jiKRj2P%h0qKsBUyvaU(gP%<#-wA!01?Rzi6IR3?Du>AhUb2Hzc`=s;=DN5b)9n^ z@!^Ufx_MxnAFIZyaFy;tej;Kpq4Bp+p1n6Vr8n%bslInZQWSHurrk+62|}iMUDT=7 zYtsCyVZ>jE3-N#srj;;}>YM-E0n(8N193b%qrxe-eZ8Hddalloi5>*l$zXW%>M-cS z=MndhN_0<2{l*mr?B^UOTnQzFvV<--n^Uj7rwN~dwWA9)EZu^3KN7+Rk4@--n&Gnn z{82n%28+!NSo)j66CXQKWn~=Xx{#EwE{vgjkEFefZA!OUke%-iB02eS?(>qpuX2FU1q&Bp1)!lqbTNZy|erW|cda^u*`%Y;LHPJH6w6UeMH??KY zoJ_K-ax;1?0v&{GsK-RYE-UQS6Vh=_uCiu~jHMzl7%RObEFl@V8@VAk6cv52_=>1xXF6n7V*_a)Wb6l~mT zRmaPy-F6!vH;lFR*XzuXElVn4{M5!!z$u-K(ZUgrVNK_{^WhQCyC%dIq8e$sr|XPm z*Hs;YP}3K!TK_rO?2PpF4rW2(SN-WP7D%RPvUeo=^vN+naQWEUd+&I|s$kts!8 z)lcc0LYCGMG9V|^$&`C(xjGKnkMhY0_nSF6c6R)F(wYeEx=i1xgxZJfO<%2Qq=p}H z;fH0A>q}v~41aS7xWtu4+@14-rGXl|GchRfkmK-{%*<%Cw{!zf#I-fjpZ{Vl?7QEM z6Y0$iBeFL<2EFl!n_iOo*|Uw$VQ5Klh&|}Lsm(|&8gRrK{<~#osk*9)+{8O1;vg&C z1PTdWkpi8SmH0!~wYF87gq8!61-X`D!LLESA89l*ObP?>Lnu( zk)T*TS)eic*f@9f;6PoGRS6BPNV3p-PV|^ArA^`9Kkd!*&ZKD{aBJ6_IYXAcWEQ6T z7~4xog||b+pl80RE#{rNhEv*XrAF+8+lCM0?bR}w^W+IEJE4Q_dr3~pM%HLLB!YT8^fC(iMFU(yOCANki(3qK@tpj22L%y6%va^t} zn#tOhq!ua^5Ybm`C_@XS%u6YG1E4*{&`xLNl0-;>P{WzjmnRG3Zj`?t+fit`F~m!X zm@_Kpoyqo4xghot{))|N5pA_!vsl>4%F%xpl<`@f7UkNljB3_p7LEn*Bbn!<`e}}1 z-R4$nl0d#aKy*g3S3!{y0bK5fdyTX|?~TA+xZ(&|RcJ7PTr05nSIT7cK}`b|u9qHp z?B6fEfJSqzOnnSq7n15&UnOnt8E}o_`H(CxoXkVq!~*M^4qoHdk#KOBwOVV&sAlIa zpI)yW<$Ajh8F@cQ3s}Qf(*)E_zCD3>CBh zwAOvQ_oi^G90|G!wZ$s=WN{UuRNO!AoXeB7vD?{hpqYg?9@$HQE*S93%}}K}%A;Kx zyEc}|6NET~!2M+~+?)G8?8@AhwR`{BMcTFV{8ME7T~Tx?c|UGd02E3)v;UI?{y;@S zh-?jG6b9nBJ=A@-$-~gAPaOPFyU{~e&RJ(t=9oFOtj#%Jik!_v&{f=&zTd-`YHpI* z@-A$Q=$?-r5Wh;AP!yl?PpuAa32055;W}6`)<^S0ac>G`{%lGNRu7W|*1I zJ<<4gP=l&uP13XJe&KuetiQf#GuDYVC49V>ib_~9_KgtU3KzxRV6HmH;ZmyWbogl@ zdwXdO9@TqIcT*g?P9KY2U`#^Hwne2G$EClmXZ771SOZ^y{{As#%gF|vPCZ&$Ufx9b zgudwd?8j~&PwjA*s;p89gMN7@?h%y!{&_!p$BP`#x1DZcr45j)IBW(z74*KEW~9`t zJmD;AXUACF1GLU=hdTbW^NNZ`o$Jr*Oa9ME0CshrP^Ps`fW>r?7rzkbSMD|rJW*|C zy6l^z@dQ-wc)(!}IZAx>@D(ZD0~d;UmF`o}p3gETL&K|#51ccB7|H6#42YOH-TVaK zLQ@69Co!h^jY}>iSDsyrq*Kl=Z(G?NA+%XXrBjra<9c((=@n;u7MXDVEYs9{VvEQ4 zCCvWO>5pDgA3Q444N||KnJAW8oe1OqEWer89G|7q9entPV^&=qGvYNg=+(r6kW=K- z9u_H7Fai&!+c|g&f4nQnq|PT`lS(>YV=PgJ2o-bJrpU_IICgp{>)%k8Z9{MplAP~4 zmphLZYC0ABqLcA_u~22n$Lm%mQ|;{}Loz1+%$6J8HNallS2^I8QJ20USzO2B(BV#X zMakCt#}m3D=Yxq!##I&oc1q^>iM$a~z7+ufs?LtGG4=OemTkG)35e3-vBN|4 zTTWLhmDC7t?yF0OmWdvrFM_FS$?T74&l=OlbaY-KKIWiAd`NR?N2qSpVdqs<=V z)fPzBR)LL*BfD=kPNFUyo};IC@n1O1G!s=l9!(FMNBG)M*q*-E}CQt_DzCpA~m$M^`4(F-24NqA`g29Aboug@f9j7^FDg1`K6eZ`2;iTpC-o^=mT$5|&<5~l zSe(?I4u!0jyl2|`D%Gsh^WYO%%o&>2F7~qKZ?@H-2>XFJ=LsxUwFR|=>?}!O4l%BP ztZf-8Z2F#)0j94HjZUnaM}aMamGlZTnbCXMJw%~~(&QHei9hCHV2uT=VMC8(BR@Z+ zkXb7WMW7n?h2wj%aq$b`dKcHZw@aCgLbhg8l*Taa2m7BwQ&)p72mxaO^2#oMziD7! z0|d2#7c)ex63EvBQqWm6kYcR^>%+dAIy6$s=~H)evAZZ+H_qGY*~Y-5Yu9%+ad%c9 zas9yWx)YKjdVd6}Zrk>r*&RyGNR72nJ zgIM$jAtM|$s@4QSeHH~C&rYh;AKk-tEVlL>vR(9TC9hDgb>8+_ z7EqQ63csA4j93TJ;AeAm5vR@WADe!aKI?z<47aFutlm!93zqe~>Ii_YYfwpZf;un1 zBgZ3`gi-$(0C%{sBnE!2v(YKnmjrZQDL7CcxJ#TDlw(sXY_H6HJwI&~AUkoJ(})w# z>%u&2@sd9kBu-1DCEq^X)U#MHG8;52u3~;uRP~a)+Znc)h9IRSO-&lY8! zDPU1Xs;4~H&P@yOJbzWgS%tn~3EM%LQKG+$%z736s=hksgNplD5Pzxl=j^=pLa337 zMO|wKr>IVQi7&bEn8NRu#n1y8zYLq3@s=|^%BPENV*|vE-g3o?z3H6(gD=n(k>K6y zLum5S>*9h-F5{mhT&S-%-oW`Wxrx#Htlz-TPlM;s@0Iiolj6ghP8v4w+rClLan{=d zOU$%y-+e%B&0!sQK}!LaQM;Dw<;ZJM2D@oCS zy|yNS*34ri5YmG&Uktnd#vV6s*Sz|BJN~EfIRwW$XwK*r!w?UPmIZLfw3q=Oc15d) z1}x~Wfr;SkBtQ$-Y}vE^A6B3khrhA}yB1#7vFK9jvmH6-1TvUGaZA^yIqK^K+1wOq zFt>2AR{sL{nzQ#HOz26xv}Mt)8zLwWNx=^j_!9$?voBwnH>;=5rUTu{o^ z#PjE+g327;5&HTjry?%o6qkM}2!DNvsOKMk$bMsX;)ppgu!*G=&2oGzN94aLkjyjg z%DHQZP=&Im41DnhkS1z&(dlxN?{Lz)maTs;NIun4t%Us^^)i6*t4g`r`>Q=4_nj-6 zg6_%6q8ziWVmsUgbjuxyJ^ou3eN(SPsO4pP6U^qjVl+A@y@cV{H+^bTKzlCmUbF%w z<4d>v&Z2&S_n#>gxfd##*T`V#%HT4#T<(@U_g%4JGJbzoQpxIiH5T)jx_SW-Of;|i zt07=ZlF%$8XFidU1G;}|soSp*BXcN2@A5N)k;u>f?BYf(%w(gGucdSt~Cwm!hh%uz8HpD*`V-6i*p&32HVcf#T|gW&l!!QcTrTsob#~e zm7;?xEZ_K=yg+tYjAB9Z&%(xiLD|xRiQ`jga6IzDm%BdVtfqs&8n^7MR5;OyfWYJ& z69i#7eL(7#BQ)VJeS9*W^}OzCGQ*%L_<-&T1emm!f7)$DA+qOb;_aiG9(#be$8dXL zH;RFecdsZe8y6w`w2@+yg-1B2+Z07R_0oZ^PH6#-p=H*Uw5u&{9D<)l@xu(0*v-;b-8 z;hC(^6ngmYqT?fZwX5*sdDX-pekXH!tm&j`XXfN;h%m)6x3#k|Wp^}2n3~!;TG%Pfi|`1Ea0?&L6J%py z(PGI-dCj{DOYA1bL;U?oXH+I|ZV^~o-_|D}K>v3hMwdLW=#5@iaT?kr z%$&`Pa3(RII??qXk*YFeZUpdMX1~lcC75>Y__V?w@jafrG}K(_0zlE zb*J1DltPUkr96fx&&li7){lR;I|a@u`y3J#j(t5C;*ZGEST(gf+1^1o?@eYjIEKDl z*;Xa>iWE#7st>SP@Y#92?Ya9V_1KQX$&Re+8`Fykia)vhh1ki?B~01OhKk5J{$%Re z_O-{nNW=d7N@e7oD1DDOgEMIlaXadU_p;1f(`MbQKKZRiuG2CCOr8qvA5voIaAWwB zR^`<%E4hdC2)a3*A@48P?23Q!?T8MWf8O!ei1N^%r4&c5 z+1mN)bI*dGKYh^#+yz`=Sswd{M!{Ce0H2+e*9#Sl-jUi5w5W31_-Sb;GenTo*(@Fc zSvQ7xJ!d(|L^ln6_k$Yw=XgIA97II*$}!dL;zjDL8&4%(V$@%Hw8CJ#sc?Y9i|=f- zQvZqZ^z`9b`4%rBqEf`$o38df$G(K3L77*sc4c&ZcqG~QP~dM0;*B#2PWK7!_X+J~ zMTNUGZu@0k73FT!#Tv-4}gw@2kW)gGGJ*8cP% zAb47Ce?m#3h}WUtT)U$9FWUlGLGwI7EDdq(n2kI;Ht6JyiueS}vd=B|etFUe(PAo(+-nkPT&q}*6 zvd^{^ZmtN~EKw0G9C)|8KAvS2JNv`C(JdHTb=&*+*_F}Ju@veMON%~7#ULdlLhy~m!(A@gggZIA+ULi_yn7L6) z*I2v3Hh2~rRC=S^rzqZ_IDqB%nV+44RGef!j@~2jDcx+|30#N!21j_SQrqpT z8#ib2+m!3y3dU6}O31j{DXC0{h9d3ranAQ;y|;a2G_-6aN3)J|(wc5A3%rIFd28od zoL+A0684J5&MRA}y{kZFGvIHhzefv?8PY&|o~h8P*@<{X#Ysgi@4b z6?hqm;wQKUb|XLMI}?NlQfa*1+?=Y@IIX?>?s!~p(4R22CcWV z&4vAY-NDvB_5>$hj%`L9QETE%w!PQ!B~&ds{)ykK>lynikA|qdc4kd#q2Rdn@~V|Z zQ2fF4Q0fh$GeQN;NR?h!&Z$sN4mBr=XhhfD+NN`Lu`WktF`NL-XFnsvDYR7j^uFI< zJ6sF=x}I~%W;1|~hainQYdO43)Ae?JlKQEi<96Idfvm+K+{}B`^z^=q_B{Vh+M-;T zVQ25l(36%kb&2ZFAOX$GgiY%q1 zC+h0NZf9;$&bdn6^$>cSmm^N_KuwkfOVlkB)!%VO8suTdH%g?eio}WQfG(kh(?L)p^6(I$Mg0?m}yLJh! zkWlP*n-LXtb(seb9+dWLsi{fZ+HzD>R3MSa$%TcMY}KsR_I3tINg6>x!4MkBt~WSW zkY|Sr!p=*#VS$xP+j`@(Bm~)c!`?3qX4uD3M_j9ZkEEpBma?-fM!vHT4Gl%b#LUdi zJ$7*s$j;90KuMyUm-`(i>#?l`C?q5#%B!k0j<%KC+S=&Y*lxo9pPZgzTTIl7KYsie z4i^WWv8|Z<6kjVw5N?%Yi|>=$Jmu_=Jx=e3Ph++{-x)+97}6HW>2l{?4)-D!S`) z^cw|bKq+MZIg?XaI=%VpNK-ooAj+h63o81bc|YFY*-3X?=%SSLPHds}2x5>8`DTdr zJ)-{P&!;jsH#gwfG50E;KPaI8(eKQsixYK{#?3)fjUR~^nV9mi<^q9WwpkhxZ|8LoL( zVm4yP`}D|RWAb4@KtO&)^5o=8YVQNXlarHs92{nIKcmw#GF}`G;!%lkIsJV`%%O|a zD|jkB>n^-H_-$v$N#ASt1y-f=aCGP}10rzM5NG8Puf#ALzjqNel2|b58Kff!X;(Mf)mX^5&b>o&ZT!iD) z;_mi)D??ApN?#3xbW5Hm!YOiD{kdmbv#Z{pucrXL{i;8gPEar=3*{YuhgIEvzJm;w z;~x+(y)lIjSvWYD360~kB!vE(gL^bvAFn~Wxe-uMv?mHXVz&Ng6ialzr^C^XC7i{^ z)>f+9_PmLinNjgj`SDtn+isr*;Nr>Iew}%DvN#r;k}y3xz2NuhX`_gU2>;;VjNIHH zDL*{nHAh$1g>YGFIxem-SdyqSrP2*MO-<7CL)7`T2hgGIF`NZX=RIk%A3uIHJlL4J zc=4jH!*yBMRC)%6kAZukXmVvaIi(5~xGwkkHP1d+J8va|Tx`5@n4&P%7v zmI{hKh(}{%>&bEfbGB?kT*Ljf} zFRN>63XqCgT4cp$onH~>U#qG_^{QM%W4&Kru&Su2VCt)2=1yR1u+iz!Zd7zMx5KnF+;=l9fvP8O=_|i;-Z&mJ z941*)QxkwS;hj5kHM06 z$bz{SD9xb9BukqsCfBZA6WeNK2qNbXfXlRe?A~9W=$;9c?1K8~+L~*}^bnLGBLhQP zZSXLIV~!1D96V@tSqQ&Uqmo$o;kF&vu>S7800Q zN=)>+tKcFPLL7k0Z)PBnwlXFpu)Mlt5?FR$J?BoblFg93{ufa`MxaGCgU}`2@qAi z*-Qbwm))yw4}@iCXo!(SE~~>1&|1wQR0>8$^b`Wtv`kFRh5Q~{v+@Eq!?U?lf&M~I zlRV4Sqs=$_#oePuM|I6{4Wt__t?rC3Q8wKIOfGkr(JZkb_;)e~ zjRy5MxiVA?7mkdIl3wo5d$S(;LeooNJ^SLc>(#rVpfRJK?>Rrzu0ZttT~v%4*&rJSOBbmsJ?@Pn(jM)8$fdm!ZpO* zckJ0fH)0>{uPehgL3`wCmj-yORroc$!`ww6`!kK^f2@&iyST14lZK=Jf2&qUD`b`HdKd5$va{vV#f!gk zG&s%i9!sY;*jpii2yh>0Y7Qz(aBy)wo4OM&gT_P$cRvqLBxbKw*p7{jkqILhQQk)^ zNg~b|62ZbiY*w;+0NgU@lLo*~fa^5SM8G8Bz?2wH{_;GHl_r~H#A^a28(l#)bVRCbSz zCCO5|y|1r-0ED(=`5uvGuZ`KI&hZ)#7IyZ#yu6W6*4Ps$$9({+ER6#F>fL@F-AbqI zUIYl66j-a+b_Z_|rEsqUx!mi-L`tl^^$BGpvb@-r1MvdN%=mb36+=7;ww2coyjkaa zWNGdKOCD}7L?$Kab*Dx7cCjod?dyuKVN>_8V$pFZ&bg=}qa-_gq^$a-G}w{AUNJ+$cvR%4+n ziGhbFBA7yOD`Dc~GAAb|2pTC61SA}~pFwOiHaBl=w$L~(=ap@3wR4I}gjHGp`uq@{ zjsR;iVBoVFloF^m0-wxs?;b5be{^bU>JfFw=mRTHiSeV#B6Nx6?^r=Q{nCO5bO;6( zPR@dLI)Cg^2^w&Px+n^>K#kc2MV;#4ci#cxmp=Yrr8kQGPaZUZF3Ludxbebe6nwJC zQRIFa3%GZ(b&f>)4*pmLmZhdXI)4(V%Y3S5Rc*D)U(!w_BQ0&EM3evVKS*MA<^^Pl zCR-)mF#q7Hi?u+4L<4d7^2BthCL1vC{mOyQ`|{EpRcjlSu59k_FO1mL%>nCY!dV89a$f+d0jF~3&K<>A zt~ZkBhuzY$vX1TSWnqz#I1hl%K%>m(SFNRjU29xmvs!CV=vRC*J$| zB0%I|!NHUAS=<6luRh%ysZ0#?S8H3W+m|?ADaL59LIk0!D#1Dl$Z0HZn5GAG~A_M5^yLcSpO-_9>9qHGKSqcFwxl zclZ)7;iND^6+B#_X*)3u z5f2tXO%vdmyqw(U)YP}c?Ao^|DHTV)+pw^*GJx9zOABHWquW8vNk4vkIxE6qu;m4= z1?2Q3>{aDNC4U`nPRbG?UTfmkA3Ai*gs3$QYb@o#i?%ur%bVqpW7UsTs zdV0z$DhvxXDM|8jfm-)y1H**;0>GM zk`#y@>i6wx$81}=yF-)3JwWU>d92s803@>JNis6Nhj8FY6&djTJyuo>d{!UMC*Jh>Pm^)@`-=_`k}|Y{(%RK^KfX4YUPVFDkKw&8&V>v57ruJ+ zCM?yyq@kg)ty&epNN6V~K3FlxB@vgE)@rxyzkN9*)YQ}%)u~_O&h2?%FD51?r=-Nh z$r%djC;`qSJT_L&%IZESh?k%~LR!5*&SMf7;Q1n(5djgWzx9(1?*M$Vzz)H{2Gd)R zDJ%{aGGLe#b{pen8XKh{;VFmWB?GPm{QI(lJ(gEC{sb~0xFc{K;bCE~v$B}qUBPFf zrG5SSHKrb*T|XG3Y@rCK&i!vvi9|t>7Zn%3+N=YQjy5VBwb!YM@fj(_%!u%wX=`hz zUGnL&ax8i4AM2Xt_1epgBpvVm9Rh9uL3#wb7ZaJO1^zn%x(tFM?#;ElAtvrgDQUpg zmNBc+pv?Ase~G^uu*qq$_k+*rvcazKO#(~CM{ldR-3NUP3r~(?PNyTpB*sp74nLSv zmJJm?*VnJX!Lv#mM~hkya(&Q{4!XK?qu{pQYo>ARQORka0;KiN?1BU95w@(Lv@Y~A zD1I<%i@g~)z?VU8@(wbo-vtJenTl~2>X}iVKcGzx&@^WcU~?jwo=$_y&Oub{k9&l| z3yFXcf&Dpab_gL|`nqfwD8~>U?HHw8>vOPXK4l@+_euZ>*7paXc zG;YCz)%@_qrGVgU_>NAVh7Mk>B$~7ybY6~g^c8||RBxuKM*J0N-ED`an5`wT%E|ZW zw$!vVz!Gy1*C(gzKCYv+_EV3>ku$hZP+H$!Hr$zbT{Vo5oLySd9zcVByO;Z-+e)0{ zbVWZax2_9KK}y;R5)HiH&iceeAxoV_4?QM}Sx9pIHe}6bH=YRAxJBb{{&&g;&{^1| z0@kFUvhtVdU=N9gE8V9$TSph7b_d*$bqCWoFr~fJmvapl*ZHCopkzmqXiPM#Mg(Zr z3daSEt%HU(gnQM{!vnSNYuf&4YGwuvHfPzrmA==XZx@fTUa&+vRNQM#G%F~j0mZnm z)q@9loy-6$J+8r10a;E=679=HFbr=;+PEV`k-Dr{T{0E_r z;ClU4l-h7iPK##{OkN)UH)cO$V|J4IyuW`mX0e``%R zQcw4*tt%)u)l5ZfT7Y~^J_K=s-uhDFeG!p(keu7YuL@3QXXxqak&|z(2!a1m_{7G| zBLF!Gm8hPAMnW1Uei$uxh_+>AW1B7RmPi9h%BEZXt8wE#_Rk6A>rtGvOnhZ z`>C{yOp#UJ*ZVPjlobwt+KAVc-2l9X${iTaH)+nN$}Q%C^C2#V%%{kGcgae8ys7C! z9IrVc8JSyWi~j2ApMJ$vz112~#OzgwK#b77xZvBlUiGtKN-~5}_y?GvB$3S4Rynh- zM7JhMm@9emg3-~CCV2_s|Kg=f1k}{}bB6Mbj7>#cA!2SKD+>BIsVK4v#cO8CGR9~>bv9-0W-tH2G?Rf`T z$t57vCr_T_4|$wg2aIzc9#c0%}`^3Mv;dVyjd>`Q&my%|M)Ql!c2^Ac>n&Q zs@7gO78ag2=DPsyU>5ud7$Ev=Y-#yjys)pq7aSOfvE&%vieWzpGvK#(U=<-_1PdMx z-GfoKE9dMNfQK+V$HLNJTc-N#8P>_MAWB){aF%)D86X_K!~rc>DWHZz$W&ooksmt& zAOo7$7s4e%5)xS@r4VB!vBTNOjs(GO?o3Eoh3AJ`!xMup(=hP5^Lh&H7a1S_1TqB(EgM1mZ*15D-^x9G zdZ~8eMIqo2{8$X+Q^A`sQ6igubu2h}0#eee_27QLeEISjY!()1j%|pQ999OoVGrAY zL)$YHV*Y~nz=FcSfG%hZ@6A91q2?tplo-9EsAvL}1t%`_T@h08cJP`*H6DTq0ygww zVu_q}ClRm{uOYvlT3%Lw1QuhffDtitIM*J7GhtvU46~0~uVWscGtY>~$O;%dyk6(b zE&=%kcFb<_+*fTtxibZl7=qikF%k0S-d-l$?2E4Tueq9q7hZ$*(5S3=njiq@1BP23 zR03oljC6EwAeO)a!wN>nVVaegC`j)?Cu|K&MKD{Vpa7!=6cMx1uR>#4jPU~{2yF;C zgCEGth?p2zLqj?&sOCg*58|A@0H^`D5V*w%&^-~cv44@Hkhx#GdbJ)6f!#Q0hp?oi zU=)gGp&P{vLkyUh{A_QB2@wok5HKS8@#6=~XfD*lFu>K-)%PaZ+fFmISutSljAl2! zsku236;*IT0tM7DsK?3qd6_3qu0y0~Jyev@TM+s1;X}}Uh_z8+2sX)hOs>Lc3u|Sf z?%Y>mMn!MKem}EATV(?MW!B2EwYwYNz`(#8$bV*j-nXED6Xc{u$9lYVk~ zx$SOAbI`@Q)yVLJ1LWj!@Fg&K<~3^BnafF8rFiReXvh2vu*mP<>0)*c!1pH26+zY_SaK# zPft(yqR(fWk?)C;KI0A^-rf>WS{Mv~FX;= zOJCI2*T+N}P?ARAw70i0b0&~l+ND-aPX))Mm6Vi9C2v`NAtCn?+e3?ZSNo zV)84%G&ZJKFoGm1>NaSiX6Sq5TEzkkE+M{!V`yt_orHc*&&pEO)m<6vd=?FxxK)pX z&xM$kt3BCL0LK8Az5wF`F_5`1-p~-9r@v#wRf+Bj3WPt_T3(Rjps} zN1x(bBHxcMmF*@zNcg1p>Qt;tsBx*KyVQAEy(?L~9WqCqwelIfcs@&&xs!27%K)0i zcK@h`Of+-YJywq8O6hepGcoxEa}x|e{&QA=VKb0bSb#&2K$s-eFl8q}rSaERi*6JP znQcJq!w8lG?B1XKXSPV^io2UqElRdi+XeG~tcEC@LoQ#r!t1i42`--t`ouThG z38^FXf6S5vhN&I_OnqIa<9kwZn00jrAIG+XD?ThXR&#FEz{}a|xH`jKvEz9Xqim3{ zvl+g^G-@`ov2L;YLN9GxeA@K_QiqjU^?utU-cxrm#pVhe&y#{WqvGg+{cqBgie1k? zXe6##ED;M>dw=loJ^e7^9x{{i+))_i3N_(FknnVYIPA#WJ>-7%wA0;;OQWs>)*|om zvFZnyWBu0R0%Kx0GfXuknO-#B{_Xh3k|tmL=x-W^mLLl^>rQ@(Kok|L-^JAp{qkI6 zbbfWNrL}?c58C2v72^BZWRJB5aO*Cs+AZ>-U*oGF60JU%4#XtA&}Gn!i8ANxXcQ4# znMJ1>+$ShbRC&3OzW1T2_wmSth%rBXX@8Naf^FTYi}!Ah!Df!ZX@DQK`&B!;^_;FT zD0)m#&>Tt=ibA1gJZb4mr=m7opf^F|z|8s~Ko^j>(&F;z7GuzdBje6cw6tNjZK?7VQbye|iNy?NAP^F#`k$cGsvLC~QLJ*Pfr49k!2 zMu;aCHF+G4R>inM7Yzs8%C>v+=1oXsI7-qd8M;oS>ybv^C_4*_L*is6pq_@fPLiCn z(B0}Q_|)kjvcP2%kdbLE@*(MQ-vCJ09gnTUr0Pd|d*H8M&%kv%_EmVmjPx=d<<8vRKEMR16fm zF;!~&D=)Ms*V1wP{6OnErwL-VF{Y7OaUrIsF3mEs{)jr+e^dA?mEp8ge*Rhz*%{BW zV7H0oNo153C->3bqV)U4S7p6ivB{W@n3|scIVN@1QCI8zu5|;u1b0zyLW(fEahCE0 zvWYaX>Bs6RDsSD;UpG2i_^TIYBGh-k`Y5?F)_!I7lQw6L@cm5a%zk+8s6a@^`}yUz z7QudZx6bF>Dc=EEkCCe`qQEE+VZ1E-%QL3px)sRN+9gkS_ms8EgzC%g_KAJSh4?I$ ztbEtx{v}p4J-v$K(a&%Ga^mpij(>4Z^si5r{^uS4v&H{YX8#W(+5ev#$Fb_HJ48-~KOy_%R#+ diff --git a/desktop/src/app/filterwheel/filterwheel.component.ts b/desktop/src/app/filterwheel/filterwheel.component.ts index eae0d4977..835648182 100644 --- a/desktop/src/app/filterwheel/filterwheel.component.ts +++ b/desktop/src/app/filterwheel/filterwheel.component.ts @@ -56,8 +56,8 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Pingab return this.filters[this.position - 1] } - private readonly filterChangedPublisher = new Subject() - private readonly subscription?: Subscription + private readonly filterChangePublisher = new Subject() + private readonly filterChangeSubscription?: Subscription constructor( private readonly app: AppComponent, @@ -112,7 +112,7 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Pingab } }) - this.subscription = this.filterChangedPublisher.pipe(debounceTime(1500)).subscribe(async (filter) => { + this.filterChangeSubscription = this.filterChangePublisher.pipe(debounceTime(1500)).subscribe(async (filter) => { this.savePreference() const names = this.filters.map((e) => e.name) @@ -197,7 +197,7 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Pingab @HostListener('window:unload') ngOnDestroy() { this.pinger.unregister(this) - this.subscription?.unsubscribe() + this.filterChangeSubscription?.unsubscribe() } async ping() { @@ -300,12 +300,12 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Pingab shutterToggled(filter: FilterSlot, event: CheckboxChangeEvent) { this.filters.forEach((e) => (e.dark = !!event.checked && e === filter)) - this.filterChangedPublisher.next(structuredClone(filter)) + this.filterChangePublisher.next(structuredClone(filter)) } filterNameChanged(filter: FilterSlot) { if (filter.name) { - this.filterChangedPublisher.next(structuredClone(filter)) + this.filterChangePublisher.next(structuredClone(filter)) } } diff --git a/desktop/src/app/settings/settings.component.html b/desktop/src/app/settings/settings.component.html index b776bec5d..a096e3ffa 100644 --- a/desktop/src/app/settings/settings.component.html +++ b/desktop/src/app/settings/settings.component.html @@ -25,7 +25,13 @@ dataKey="id" styleClass="p-inputtext-sm border-0" emptyMessage="No location found" - [autoDisplayFirst]="false" /> + [autoDisplayFirst]="false"> + +
+ {{ location.name || '?' }} +
+
+
@@ -37,14 +43,6 @@ pTooltip="New" tooltipPosition="bottom" (onClick)="addLocation()" /> -
+
+ +
() + private readonly locationChangeSubscription?: Subscription + constructor( app: AppComponent, private readonly preference: PreferenceService, private readonly electron: ElectronService, - private readonly prime: PrimeService, private readonly dropdownOptions: DropdownOptionsPipe, ) { app.title = 'Settings' this.locations = preference.locations.get() - this.location = preference.selectedLocation.get(this.locations[0]) + const selectedLocation = preference.selectedLocation.get(this.locations[0]) + this.location = this.locations.find(e => e.id === selectedLocation.id) ?? this.locations[0] for (const type of dropdownOptions.transform('PLATE_SOLVER')) { this.plateSolvers.set(type, preference.plateSolverRequest(type).get()) @@ -63,42 +65,26 @@ export class SettingsComponent { } Object.assign(this.cameraCaptureNamingFormat, preference.cameraCaptureNamingFormatPreference.get(this.cameraCaptureNamingFormat)) - } - addLocation() { - return this.showLocation(structuredClone(EMPTY_LOCATION)) + this.locationChangeSubscription = this.locationChangePublisher.pipe(debounceTime(2000)).subscribe((location) => { + return this.electron.send('LOCATION.CHANGED', location) + }) } - editLocation() { - return this.showLocation(this.location) + ngOnDestroy() { + this.locationChangeSubscription?.unsubscribe() } - private async showLocation(location: Location) { - const result = await this.prime.open(LocationDialog, { header: 'Location', data: location }) - - if (result) { - const index = this.locations.findIndex((e) => e.id === result.id) - - if (result.id === 0) { - result.id = Date.now() - } - - if (index >= 0) { - Object.assign(this.locations[index], result) - this.location = this.locations[index] - } else { - this.locations.push(result) - this.location = result - } - - this.preference.locations.set(this.locations) - this.preference.selectedLocation.set(this.location) - - await this.electron.send('LOCATION.CHANGED', this.location) - } + addLocation() { + const location = structuredClone(EMPTY_LOCATION) + location.id = +new Date() + this.locations.push(location) + this.location = location + this.save() + this.locationChangePublisher.next(this.location) } - async deleteLocation() { + deleteLocation() { if (this.locations.length > 1) { const index = this.locations.findIndex((e) => e.id === this.location.id) @@ -106,17 +92,16 @@ export class SettingsComponent { this.locations.splice(index, 1) this.location = this.locations[0]! - this.preference.locations.set(this.locations) - this.preference.selectedLocation.set(this.location) - - await this.electron.send('LOCATION.CHANGED', this.location) + this.save() + this.locationChangePublisher.next(this.location) } } } locationChanged() { - this.preference.selectedLocation.set(this.location) - return this.electron.send('LOCATION.CHANGED', this.location) + console.log(this.locations) + this.save() + this.locationChangePublisher.next(this.location) } resetCameraCaptureNamingFormat(type: FrameType) { @@ -125,6 +110,11 @@ export class SettingsComponent { } save() { + if (this.location.name) { + this.preference.locations.set(this.locations) + this.preference.selectedLocation.set(this.location) + } + for (const type of this.dropdownOptions.transform('PLATE_SOLVER')) { this.preference.plateSolverRequest(type).set(this.plateSolvers.get(type)) } diff --git a/desktop/src/shared/components/map/map.component.ts b/desktop/src/shared/components/map/map.component.ts index c518dd4c7..99d80671a 100644 --- a/desktop/src/shared/components/map/map.component.ts +++ b/desktop/src/shared/components/map/map.component.ts @@ -22,7 +22,7 @@ export class MapComponent implements AfterViewInit, OnChanges { @Output() readonly longitudeChange = new EventEmitter() - private map!: L.Map + private map?: L.Map private marker?: L.Marker private readonly markerIcon = L.icon({ @@ -59,17 +59,21 @@ export class MapComponent implements AfterViewInit, OnChanges { } ngOnChanges() { - const coordinate: L.LatLngLiteral = { lat: this.latitude, lng: this.longitude } - this.map.setView(coordinate) - this.updateMarker(coordinate) + if (this.map) { + const coordinate: L.LatLngLiteral = { lat: this.latitude, lng: this.longitude } + this.map.setView(coordinate) + this.updateMarker(coordinate) + } } refresh() { - this.map.invalidateSize() + this.map?.invalidateSize() } private updateMarker(coordinate: L.LatLngExpression) { - this.marker?.remove() - this.marker = new L.Marker(coordinate, { icon: this.markerIcon }).addTo(this.map) + if (this.map) { + this.marker?.remove() + this.marker = new L.Marker(coordinate, { icon: this.markerIcon }).addTo(this.map) + } } } diff --git a/desktop/src/shared/dialogs/location/location.dialog.html b/desktop/src/shared/dialogs/location/location.dialog.html index 1b554e2bf..e7b01f44e 100644 --- a/desktop/src/shared/dialogs/location/location.dialog.html +++ b/desktop/src/shared/dialogs/location/location.dialog.html @@ -4,7 +4,8 @@ + [(ngModel)]="location.name" + (ngModelChange)="locationChanged()" />
@@ -17,6 +18,7 @@ [min]="-720" [max]="720" [(ngModel)]="location.offsetInMinutes" + (ngModelChange)="locationChanged()" [showButtons]="true" [allowEmpty]="false" scrollableNumber /> @@ -32,6 +34,7 @@ [min]="-1000" [max]="10000" [(ngModel)]="location.elevation" + (ngModelChange)="locationChanged()" [showButtons]="true" [allowEmpty]="false" scrollableNumber /> @@ -47,6 +50,7 @@ [max]="90" [maxFractionDigits]="5" [(ngModel)]="location.latitude" + (ngModelChange)="locationChanged()" [allowEmpty]="false" scrollableNumber /> @@ -61,6 +65,7 @@ [max]="180" [maxFractionDigits]="5" [(ngModel)]="location.longitude" + (ngModelChange)="locationChanged()" [allowEmpty]="false" scrollableNumber /> @@ -70,10 +75,14 @@ + (latitudeChange)="locationChanged()" + [(longitude)]="location.longitude" + (longitudeChange)="locationChanged()" />
-
- - - {{ savedPath }} -
+ spinnableNumber />
+ spinnableNumber />
+ spinnableNumber />
+ spinnableNumber />
@@ -139,7 +133,7 @@
{ + electronService.on('FLAT_WIZARD.ELAPSED', (event) => { ngZone.run(() => { - if (event.state === 'EXPOSURING' && event.capture && event.capture.camera.id === this.camera.id) { + if (event.state === 'EXPOSURING' && event.capture && event.capture.camera.id === this.camera?.id) { this.running = true this.cameraExposure.handleCameraCaptureEvent(event.capture, true) } else if (event.state === 'CAPTURED') { this.running = false - this.savedPath = event.savedPath - this.prime.message(`Flat frame captured`) + this.primeService.message(`Flat frame captured`) } else if (event.state === 'FAILED') { this.running = false - this.savedPath = undefined - this.prime.message(`Failed to find an optimal exposure time from given parameters`, 'error') + this.primeService.message(`Failed to find an optimal exposure time from given parameters`, 'error') } }) }) - electron.on('CAMERA.UPDATED', async (event) => { - if (event.device.id === this.camera.id) { - await ngZone.run(() => { - Object.assign(this.camera, event.device) - return this.cameraChanged() + electronService.on('CAMERA.UPDATED', (event) => { + if (event.device.id === this.camera?.id) { + ngZone.run(() => { + if (this.camera) { + Object.assign(this.camera, event.device) + void this.cameraChanged() + } }) } }) - electron.on('CAMERA.ATTACHED', (event) => { + electronService.on('CAMERA.ATTACHED', (event) => { ngZone.run(() => { this.cameras.push(event.device) this.cameras.sort(deviceComparator) }) }) - electron.on('CAMERA.DETACHED', (event) => { + electronService.on('CAMERA.DETACHED', (event) => { ngZone.run(() => { const index = this.cameras.findIndex((e) => e.id === event.device.id) if (index >= 0) { if (this.cameras[index] === this.camera) { - Object.assign(this.camera, this.cameras[0] ?? EMPTY_CAMERA) + Object.assign(this.camera, this.cameras[0] ?? DEFAULT_CAMERA) } this.cameras.splice(index, 1) @@ -108,41 +102,41 @@ export class FlatWizardComponent implements AfterViewInit, OnDestroy, Pingable { }) }) - electron.on('WHEEL.UPDATED', async (event) => { - if (event.device.id === this.wheel.id) { - await ngZone.run(() => { - Object.assign(this.wheel, event.device) - return this.wheelChanged() + electronService.on('WHEEL.UPDATED', (event) => { + if (event.device.id === this.wheel?.id) { + ngZone.run(() => { + if (this.wheel) { + Object.assign(this.wheel, event.device) + void this.wheelChanged() + } }) } }) - electron.on('WHEEL.ATTACHED', (event) => { + electronService.on('WHEEL.ATTACHED', (event) => { ngZone.run(() => { this.wheels.push(event.device) this.wheels.sort(deviceComparator) }) }) - electron.on('WHEEL.DETACHED', (event) => { + electronService.on('WHEEL.DETACHED', (event) => { ngZone.run(() => { const index = this.wheels.findIndex((e) => e.id === event.device.id) if (index >= 0) { if (this.wheels[index] === this.wheel) { - Object.assign(this.wheel, this.wheels[0] ?? EMPTY_WHEEL) + Object.assign(this.wheel, this.wheels[0] ?? DEFAULT_WHEEL) } this.wheels.splice(index, 1) } }) }) - - this.request.capture.frameType = 'FLAT' } async ngAfterViewInit() { - this.pinger.register(this, 30000) + this.ticker.register(this, 30000) this.cameras = (await this.api.cameras()).sort(deviceComparator) this.wheels = (await this.api.wheels()).sort(deviceComparator) @@ -150,27 +144,26 @@ export class FlatWizardComponent implements AfterViewInit, OnDestroy, Pingable { @HostListener('window:unload') ngOnDestroy() { - this.pinger.unregister(this) + this.ticker.unregister(this) void this.stop() } - async ping() { - if (this.camera.id) await this.api.cameraListen(this.camera) - if (this.wheel.id) await this.api.wheelListen(this.wheel) + async tick() { + if (this.camera?.id) await this.api.cameraListen(this.camera) + if (this.wheel?.id) await this.api.wheelListen(this.wheel) } - async showCameraDialog() { - if (this.camera.id && (await CameraComponent.showAsDialog(this.browserWindow, 'FLAT_WIZARD', this.camera, this.request.capture))) { - this.preference.cameraStartCaptureForFlatWizard(this.camera).set(this.request.capture) + protected async showCameraDialog() { + if (this.camera?.id && (await CameraComponent.showAsDialog(this.browserWindowService, 'FLAT_WIZARD', this.camera, this.request.capture))) { + this.savePreference() } } - async cameraChanged() { - if (this.camera.id) { - await this.ping() + protected async cameraChanged() { + if (this.camera?.id) { + await this.tick() - const cameraPreference = this.preference.cameraPreference(this.camera).get() - this.request.capture = this.preference.cameraStartCaptureForFlatWizard(this.camera).get(cameraPreference) + this.loadPreference() this.updateEntryFromCamera(this.camera) this.request.capture.frameType = 'FLAT' } @@ -179,15 +172,16 @@ export class FlatWizardComponent implements AfterViewInit, OnDestroy, Pingable { private updateEntryFromCamera(camera?: Camera) { if (camera?.connected) { updateCameraStartCaptureFromCamera(this.request.capture, camera) + this.savePreference() } } - async wheelChanged() { - if (this.wheel.id) { - await this.ping() + protected async wheelChanged() { + if (this.wheel?.id) { + await this.tick() - const preference = this.preference.wheelPreference(this.wheel).get() - const filters = makeFilterSlots(this.wheel, this.filters, preference.shutterPosition) + const shutterPosition = this.preferenceService.wheel(this.wheel).get().shutterPosition + const filters = makeFilter(this.wheel, this.filters, shutterPosition) if (filters !== this.filters) { this.filters = filters @@ -196,20 +190,31 @@ export class FlatWizardComponent implements AfterViewInit, OnDestroy, Pingable { } } - async start() { - await this.browserWindow.openCameraImage(this.camera, 'FLAT_WIZARD') - // TODO: Iniciar para cada filtro selecionado. Usar os eventos para percorrer (se houver filtro). - // Se Falhar, interrompe todo o fluxo. - await this.api.flatWizardStart(this.camera, this.request) + protected async start() { + if (this.camera) { + await this.browserWindowService.openCameraImage(this.camera, 'FLAT_WIZARD') + // TODO: Iniciar para cada filtro selecionado. Usar os eventos para percorrer (se houver filtro). + // Se Falhar, interrompe todo o fluxo. + await this.api.flatWizardStart(this.camera, this.request) + } + } + + protected async stop() { + if (this.camera) { + await this.api.flatWizardStop(this.camera) + } } - stop() { - return this.api.flatWizardStop(this.camera) + private loadPreference() { + if (this.camera?.id) { + Object.assign(this.preference, this.preferenceService.flatWizard(this.camera).get()) + this.request = this.preference.request + } } - savePreference() { - if (this.camera.id) { - this.preference.cameraStartCaptureForFlatWizard(this.camera).set(this.request.capture) + protected savePreference() { + if (this.camera?.id) { + this.preferenceService.flatWizard(this.camera).set(this.preference) } } } diff --git a/desktop/src/app/focuser/focuser.component.html b/desktop/src/app/focuser/focuser.component.html index 4ae7750ce..42e26e757 100644 --- a/desktop/src/app/focuser/focuser.component.html +++ b/desktop/src/app/focuser/focuser.component.html @@ -11,7 +11,7 @@
- {{ moving ? 'moving' : 'idle' }} + {{ focuser.moving ? 'moving' : 'idle' }}
- + spinnableNumber /> +
+ spinnableNumber />
-
- +
+ + spinnableNumber /> { + electronService.on('FOCUSER.UPDATED', (event) => { if (event.device.id === this.focuser.id) { ngZone.run(() => { Object.assign(this.focuser, event.device) @@ -39,10 +36,10 @@ export class FocuserComponent implements AfterViewInit, OnDestroy, Pingable { } }) - electron.on('FOCUSER.DETACHED', (event) => { + electronService.on('FOCUSER.DETACHED', (event) => { if (event.device.id === this.focuser.id) { ngZone.run(() => { - Object.assign(this.focuser, EMPTY_FOCUSER) + Object.assign(this.focuser, DEFAULT_FOCUSER) }) } }) @@ -81,43 +78,47 @@ export class FocuserComponent implements AfterViewInit, OnDestroy, Pingable { }) hotkeys('up', (event) => { event.preventDefault() - this.stepsRelative = Math.min(this.focuser.maxPosition, this.stepsRelative + 1) + this.preference.stepsRelative = Math.min(this.focuser.maxPosition, this.preference.stepsRelative + 1) + this.savePreference() }) hotkeys('down', (event) => { event.preventDefault() - this.stepsRelative = Math.max(0, this.stepsRelative - 1) + this.preference.stepsRelative = Math.max(0, this.preference.stepsRelative - 1) + this.savePreference() }) hotkeys('ctrl+up', (event) => { event.preventDefault() - this.stepsAbsolute = Math.max(0, this.stepsAbsolute - 1) + this.preference.stepsAbsolute = Math.max(0, this.preference.stepsAbsolute - 1) + this.savePreference() }) hotkeys('ctrl+down', (event) => { event.preventDefault() - this.stepsAbsolute = Math.min(this.focuser.maxPosition, this.stepsAbsolute + 1) + this.preference.stepsAbsolute = Math.min(this.focuser.maxPosition, this.preference.stepsAbsolute + 1) + this.savePreference() }) } ngAfterViewInit() { this.route.queryParams.subscribe(async (e) => { - const focuser = JSON.parse(decodeURIComponent(e['data'] as string)) as Focuser - await this.focuserChanged(focuser) - this.pinger.register(this, 30000) + const data = JSON.parse(decodeURIComponent(e['data'] as string)) as Focuser + await this.focuserChanged(data) + this.ticker.register(this, 30000) }) } @HostListener('window:unload') ngOnDestroy() { - this.pinger.unregister(this) + this.ticker.unregister(this) void this.abort() } - async ping() { + async tick() { if (this.focuser.id) { await this.api.focuserListen(this.focuser) } } - async focuserChanged(focuser?: Focuser) { + protected async focuserChanged(focuser?: Focuser) { if (focuser?.id) { focuser = await this.api.focuser(focuser.id) Object.assign(this.focuser, focuser) @@ -129,7 +130,7 @@ export class FocuserComponent implements AfterViewInit, OnDestroy, Pingable { this.app.subTitle = focuser?.name ?? '' } - connect() { + protected connect() { if (this.focuser.connected) { return this.api.focuserDisconnect(this.focuser) } else { @@ -137,61 +138,46 @@ export class FocuserComponent implements AfterViewInit, OnDestroy, Pingable { } } - async moveIn(stepSize: number = 1) { - if (!this.moving) { - this.moving = true - await this.api.focuserMoveIn(this.focuser, Math.trunc(this.stepsRelative * stepSize)) - this.savePreference() + protected async moveIn(stepSize: number = 1) { + if (!this.focuser.moving && stepSize) { + await this.api.focuserMoveIn(this.focuser, Math.trunc(this.preference.stepsRelative * stepSize)) } } - async moveOut(stepSize: number = 1) { - if (!this.moving) { - this.moving = true - await this.api.focuserMoveOut(this.focuser, Math.trunc(this.stepsRelative * stepSize)) - this.savePreference() + protected async moveOut(stepSize: number = 1) { + if (!this.focuser.moving && stepSize) { + await this.api.focuserMoveOut(this.focuser, Math.trunc(this.preference.stepsRelative * stepSize)) } } - async moveTo() { - if (!this.moving && this.stepsAbsolute !== this.focuser.position) { - this.moving = true - await this.api.focuserMoveTo(this.focuser, this.stepsAbsolute) - this.savePreference() + protected async moveTo() { + if (!this.focuser.moving && this.preference.stepsAbsolute !== this.focuser.position) { + await this.api.focuserMoveTo(this.focuser, this.preference.stepsAbsolute) } } - async sync() { - if (!this.moving) { - await this.api.focuserSync(this.focuser, this.stepsAbsolute) - this.savePreference() + protected async sync() { + if (!this.focuser.moving) { + await this.api.focuserSync(this.focuser, this.preference.stepsAbsolute) } } - abort() { + protected abort() { return this.api.focuserAbort(this.focuser) } - private update() { - if (this.focuser.id) { - this.moving = this.focuser.moving - } - } + private update() {} private loadPreference() { if (this.focuser.id) { - const preference = this.preference.focuserPreference(this.focuser).get() - this.stepsRelative = preference.stepsRelative ?? 100 - this.stepsAbsolute = preference.stepsAbsolute ?? this.focuser.position + Object.assign(this.preference, this.preferenceService.focuser(this.focuser).get()) + this.preference.stepsAbsolute = this.focuser.position } } - private savePreference() { + protected savePreference() { if (this.focuser.connected) { - const preference = this.preference.focuserPreference(this.focuser).get() - preference.stepsAbsolute = this.stepsAbsolute - preference.stepsRelative = this.stepsRelative - this.preference.focuserPreference(this.focuser).set(preference) + this.preferenceService.focuser(this.focuser).set(this.preference) } } } diff --git a/desktop/src/app/framing/framing.component.html b/desktop/src/app/framing/framing.component.html index eb480fb86..8186c7931 100644 --- a/desktop/src/app/framing/framing.component.html +++ b/desktop/src/app/framing/framing.component.html @@ -4,7 +4,8 @@ + [(ngModel)]="preference.rightAscension" + (ngModelChange)="savePreference()" />
@@ -13,7 +14,8 @@ + [(ngModel)]="preference.declination" + (ngModelChange)="savePreference()" />
@@ -25,9 +27,10 @@ class="w-full" [showButtons]="true" styleClass="p-inputtext-sm border-0 w-full" - [(ngModel)]="width" + [(ngModel)]="preference.width" + (ngModelChange)="savePreference()" locale="en" - scrollableNumber /> + spinnableNumber />
@@ -39,9 +42,10 @@ class="w-full" [showButtons]="true" styleClass="p-inputtext-sm border-0 w-full" - [(ngModel)]="height" + [(ngModel)]="preference.height" + (ngModelChange)="savePreference()" locale="en" - scrollableNumber /> + spinnableNumber />
@@ -54,10 +58,11 @@ class="w-full" [showButtons]="true" styleClass="p-inputtext-sm border-0 w-full" - [(ngModel)]="fov" + [(ngModel)]="preference.fov" + (ngModelChange)="savePreference()" locale="en" [minFractionDigits]="1" - scrollableNumber /> + spinnableNumber />
@@ -70,10 +75,11 @@ class="w-full" [showButtons]="true" styleClass="p-inputtext-sm border-0 w-full" - [(ngModel)]="rotation" + [(ngModel)]="preference.rotation" + (ngModelChange)="savePreference()" locale="en" [minFractionDigits]="1" - scrollableNumber /> + spinnableNumber />
@@ -81,7 +87,8 @@ @@ -107,7 +114,7 @@
{ + electronService.on('DATA.CHANGED', (event: LoadFraming) => { return ngZone.run(() => this.frameFromData(event)) }) - - this.loadPreference() } async ngAfterViewInit() { @@ -73,93 +42,69 @@ export class FramingComponent implements AfterViewInit, OnDestroy { try { this.hipsSurveys = await this.api.hipsSurveys() - this.hipsSurvey = this.hipsSurveys.find((e) => e.id === this.hipsSurvey?.id) ?? this.hipsSurveys[0] + this.loadPreference() } finally { this.loading = false } this.route.queryParams.subscribe((e) => { - const data = JSON.parse(decodeURIComponent(e['data'] as string)) as FramingData + const data = JSON.parse(decodeURIComponent(e['data'] as string)) as LoadFraming return this.frameFromData(data) }) } @HostListener('window:unload') ngOnDestroy() { - void this.closeFrameImage() - void this.electron.closeWindow(undefined, this.frameId) + void this.closeImageWindow() } - private async frameFromData(data: FramingData) { - this.rightAscension = data.rightAscension || this.rightAscension - this.declination = data.declination || this.declination - this.width = data.width || this.width - this.height = data.height || this.height - this.fov = data.fov || this.fov - if (data.rotation === 0 || data.rotation) this.rotation = data.rotation + private async frameFromData(data: LoadFraming) { + this.preference.rightAscension = data.rightAscension || this.preference.rightAscension + this.preference.declination = data.declination || this.preference.declination + this.preference.width = data.width || this.preference.width + this.preference.height = data.height || this.preference.height + this.preference.fov = data.fov || this.preference.fov + if (data.rotation === 0 || data.rotation) this.preference.rotation = data.rotation + + this.savePreference() if (data.rightAscension && data.declination) { await this.frame() } } - async frame() { - if (!this.hipsSurvey) return - - await this.closeFrameImage() + protected async frame() { + if (!this.preference.hipsSurvey) return this.loading = true try { - const path = await this.api.frame(this.rightAscension, this.declination, this.width, this.height, this.fov, this.rotation, this.hipsSurvey) - const title = `Framing ใƒป ${this.rightAscension} ใƒป ${this.declination}` - - this.framePath = path - this.frameId = await this.browserWindow.openImage({ path, source: 'FRAMING', id: 'framing', title }) + const { rightAscension, declination, width, height, fov, rotation, hipsSurvey } = this.preference + const path = await this.api.frame(rightAscension, declination, width, height, fov, rotation, hipsSurvey) + const title = `Framing ใƒป ${rightAscension} ใƒป ${declination}` - this.savePreference() + this.frameId = await this.browserWindowService.openImage({ path, source: 'FRAMING', id: 'framing', title }) } catch (e) { console.error(e) - this.prime.message('Failed to retrieve the image', 'error') + this.primeService.message('Failed to retrieve the image', 'error') } finally { this.loading = false } } private loadPreference() { - const preference = this.storage.get(FRAMING_KEY, {}) - - this.rightAscension = preference.rightAscension ?? '00h00m00s' - this.declination = preference.declination ?? `+00ยฐ00'00"` - this.width = preference.width ?? 1280 - this.height = preference.height ?? 720 - this.fov = preference.fov ?? 1 - this.rotation = preference.rotation ?? 0 - - if (preference.hipsSurvey) { - this.hipsSurveys = [preference.hipsSurvey] - this.hipsSurvey = this.hipsSurveys[0] - } + Object.assign(this.preference, this.preferenceService.framing.get()) + this.preference.hipsSurvey = this.hipsSurveys.find((e) => e.id === this.preference.hipsSurvey?.id) ?? this.hipsSurveys[0] } - private savePreference() { - const preference: FramingPreference = { - rightAscension: this.rightAscension, - declination: this.declination, - width: this.width, - height: this.height, - fov: this.fov, - rotation: this.rotation, - hipsSurvey: this.hipsSurvey, - } - - this.storage.set(FRAMING_KEY, preference) + protected savePreference() { + this.preferenceService.framing.set(this.preference) } - private async closeFrameImage() { - if (this.framePath) { - await this.api.closeImage(this.framePath) + private async closeImageWindow() { + if (this.frameId) { + await this.electronService.closeWindow(undefined, this.frameId) } } } diff --git a/desktop/src/app/guider/guider.component.html b/desktop/src/app/guider/guider.component.html index c602ba772..38e80746d 100644 --- a/desktop/src/app/guider/guider.component.html +++ b/desktop/src/app/guider/guider.component.html @@ -9,41 +9,47 @@ + [(ngModel)]="preference.host" + (ngModelChange)="savePreference()" />
+ spinnableNumber />
+ [text]="true" + pTooltip="Disconnect" + tooltipPosition="bottom" /> + [text]="true" + pTooltip="Connect" + tooltipPosition="bottom" />
- {{ guideState | enum | lowercase }} + {{ guider.state | enum | lowercase }} - {{ message }} + {{ guider.message }}
-
+
+ value="{{ chartInfo.rmsRA.toFixed(2) + ' (' + (chartInfo.rmsRA * chartInfo.pixelScale).toFixed(2) + '" )' }}" />
@@ -78,7 +84,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - value="{{ rmsDEC.toFixed(2) + ' (' + (rmsDEC * pixelScale).toFixed(2) + '" )' }}" /> + value="{{ chartInfo.rmsDEC.toFixed(2) + ' (' + (chartInfo.rmsDEC * chartInfo.pixelScale).toFixed(2) + '" )' }}" />
@@ -88,7 +94,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - value="{{ rmsTotal.toFixed(2) + ' (' + (rmsTotal * pixelScale).toFixed(2) + '" )' }}" /> + value="{{ chartInfo.rmsTotal.toFixed(2) + ' (' + (chartInfo.rmsTotal * chartInfo.pixelScale).toFixed(2) + '" )' }}" />
@@ -98,7 +104,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="guideStep?.starMass ?? 0" /> + [value]="guider.step?.starMass ?? 0" />
@@ -108,7 +114,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="guideStep?.hfd ?? 0" /> + [value]="guider.step?.hfd ?? 0" />
@@ -118,7 +124,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="guideStep?.snr ?? 0" /> + [value]="guider.step?.snr ?? 0" />
@@ -126,7 +132,7 @@
-
- +
+ + spinnableNumber />
-
- +
+ + spinnableNumber />
-
- +
+ + spinnableNumber />
@@ -231,7 +237,7 @@ + spinnableNumber />
@@ -284,15 +291,16 @@
+ spinnableNumber />
@@ -300,7 +308,7 @@
+ spinnableNumber />
@@ -393,16 +402,17 @@
+ spinnableNumber />
diff --git a/desktop/src/app/guider/guider.component.ts b/desktop/src/app/guider/guider.component.ts index e58c9f05c..f0f13b9bc 100644 --- a/desktop/src/app/guider/guider.component.ts +++ b/desktop/src/app/guider/guider.component.ts @@ -1,64 +1,45 @@ -import { AfterViewInit, Component, HostListener, NgZone, OnDestroy, ViewChild } from '@angular/core' -import { Title } from '@angular/platform-browser' -import { ChartData, ChartOptions } from 'chart.js' +import { AfterViewInit, Component, HostListener, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core' +import { Chart, ChartData, ChartOptions } from 'chart.js' +import zoomPlugin from 'chartjs-plugin-zoom' import { UIChart } from 'primeng/chart' import { ApiService } from '../../shared/services/api.service' import { ElectronService } from '../../shared/services/electron.service' -import { Pingable, Pinger } from '../../shared/services/pinger.service' -import { GuideDirection, GuideOutput, GuideState, GuideStep, Guider, GuiderHistoryStep, GuiderPlotMode, GuiderYAxisUnit } from '../../shared/types/guider.types' +import { PreferenceService } from '../../shared/services/preference.service' +import { Tickable, Ticker } from '../../shared/services/ticker.service' +import { DEFAULT_GUIDER_CHART_INFO, DEFAULT_GUIDER_PHD2, DEFAULT_GUIDER_PREFERENCE, DEFAULT_GUIDER_PULSE, GuideDirection, GuideOutput, Guider, GuiderHistoryStep } from '../../shared/types/guider.types' +import { AppComponent } from '../app.component' @Component({ selector: 'neb-guider', templateUrl: './guider.component.html', }) -export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { - guideOutputs: GuideOutput[] = [] - guideOutput?: GuideOutput - guideOutputConnected = false - pulseGuiding = false - - guideNorthDuration = 1000 - guideSouthDuration = 1000 - guideWestDuration = 1000 - guideEastDuration = 1000 - - connected = false - host = 'localhost' - port = 4400 - guideState: GuideState = 'STOPPED' - guideStep?: GuideStep - message = '' - - settleAmount = 1.5 - settleTime = 10 - settleTimeout = 30 - readonly phdGuideHistory: GuiderHistoryStep[] = [] - private phdDurationScale = 1.0 - - pixelScale = 1.0 - rmsRA = 0.0 - rmsDEC = 0.0 - rmsTotal = 0.0 - - plotMode: GuiderPlotMode = 'RA/DEC' - yAxisUnit: GuiderYAxisUnit = 'ARCSEC' +export class GuiderComponent implements OnInit, AfterViewInit, OnDestroy, Tickable { + protected guideOutputs: GuideOutput[] = [] + protected guideOutput?: GuideOutput + + protected readonly preference = structuredClone(DEFAULT_GUIDER_PREFERENCE) + protected readonly guider = structuredClone(DEFAULT_GUIDER_PHD2) + protected readonly pulse = structuredClone(DEFAULT_GUIDER_PULSE) + protected readonly chartInfo = structuredClone(DEFAULT_GUIDER_CHART_INFO) + + private readonly guideHistory: GuiderHistoryStep[] = [] @ViewChild('chart') private readonly chart!: UIChart get stopped() { - return this.guideState === 'STOPPED' + return this.guider.state === 'STOPPED' } get looping() { - return this.guideState === 'LOOPING' + return this.guider.state === 'LOOPING' } get guiding() { - return this.guideState === 'GUIDING' + return this.guider.state === 'GUIDING' } - readonly chartData: ChartData = { + protected readonly chartData: ChartData = { labels: Array.from({ length: 100 }, (_, i) => `${i}`), datasets: [ // RA. @@ -96,7 +77,7 @@ export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { ], } - readonly chartOptions: ChartOptions = { + protected readonly chartOptions: ChartOptions = { responsive: true, plugins: { legend: { @@ -116,10 +97,10 @@ export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const barType = context.dataset.type === 'bar' const raType = context.datasetIndex === 0 || context.datasetIndex === 2 - const scale = barType ? this.phdDurationScale : 1.0 + const scale = barType ? this.chartInfo.durationScale : 1.0 const y = context.parsed.y * scale const prefix = raType ? 'RA: ' : 'DEC: ' - const lineSuffix = this.yAxisUnit === 'ARCSEC' ? '"' : 'px' + const lineSuffix = this.preference.yAxisUnit === 'ARCSEC' ? '"' : 'px' const formattedY = prefix + (barType ? y.toFixed(0) + ' ms' : y.toFixed(2) + lineSuffix) return formattedY }, @@ -214,15 +195,16 @@ export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { } constructor( - title: Title, + app: AppComponent, private readonly api: ApiService, - private readonly pinger: Pinger, - electron: ElectronService, + private readonly ticker: Ticker, + private readonly preferenceService: PreferenceService, + electronService: ElectronService, ngZone: NgZone, ) { - title.setTitle('Guider') + app.title = 'Guider' - electron.on('GUIDE_OUTPUT.UPDATED', (event) => { + electronService.on('GUIDE_OUTPUT.UPDATED', (event) => { if (event.device.id === this.guideOutput?.id) { ngZone.run(() => { if (this.guideOutput) { @@ -233,69 +215,67 @@ export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { } }) - electron.on('GUIDE_OUTPUT.ATTACHED', (event) => { + electronService.on('GUIDE_OUTPUT.ATTACHED', (event) => { ngZone.run(() => { this.guideOutputs.push(event.device) }) }) - electron.on('GUIDE_OUTPUT.DETACHED', (event) => { + electronService.on('GUIDE_OUTPUT.DETACHED', (event) => { ngZone.run(() => { const index = this.guideOutputs.findIndex((e) => e.id === event.device.id) if (index >= 0) this.guideOutputs.splice(index, 1) }) }) - electron.on('GUIDER.CONNECTED', () => { + electronService.on('GUIDER.CONNECTED', () => { ngZone.run(() => { - this.connected = true + this.guider.connected = true }) }) - electron.on('GUIDER.DISCONNECTED', () => { + electronService.on('GUIDER.DISCONNECTED', () => { ngZone.run(() => { - this.connected = false + this.guider.connected = false }) }) - electron.on('GUIDER.UPDATED', (event) => { + electronService.on('GUIDER.UPDATED', (event) => { ngZone.run(() => { this.processGuiderStatus(event.data) }) }) - electron.on('GUIDER.STEPPED', (event) => { + electronService.on('GUIDER.STEPPED', (event) => { ngZone.run(() => { - if (this.phdGuideHistory.length >= 100) { - this.phdGuideHistory.splice(0, this.phdGuideHistory.length - 99) + if (this.guideHistory.length >= 100) { + this.guideHistory.splice(0, this.guideHistory.length - 99) } - this.phdGuideHistory.push(event.data) + this.guideHistory.push(event.data) this.updateGuideHistoryChart() if (event.data.guideStep) { - this.guideStep = event.data.guideStep + this.guider.step = event.data.guideStep } else { // Dithering. } }) }) - electron.on('GUIDER.MESSAGE_RECEIVED', (event) => { + electronService.on('GUIDER.MESSAGE_RECEIVED', (event) => { ngZone.run(() => { - this.message = event.data + this.guider.message = event.data }) }) } - async ngAfterViewInit() { - this.pinger.register(this, 30000) - - const settle = await this.api.getGuidingSettle() + ngOnInit() { + Chart.register(zoomPlugin) + } - this.settleAmount = settle.amount - this.settleTime = settle.time - this.settleTimeout = settle.timeout + async ngAfterViewInit() { + this.ticker.register(this, 30000) this.guideOutputs = await this.api.guideOutputs() @@ -303,46 +283,50 @@ export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { this.processGuiderStatus(status) const history = await this.api.guidingHistory() - this.phdGuideHistory.push(...history) + this.guideHistory.push(...history) this.updateGuideHistoryChart() + + this.loadPreference() } @HostListener('window:unload') ngOnDestroy() { - this.pinger.unregister(this) + this.ticker.unregister(this) } - async ping() { + async tick() { if (this.guideOutput?.id) await this.api.guideOutputListen(this.guideOutput) } private processGuiderStatus(event: Guider) { - this.connected = event.connected - this.guideState = event.state - this.pixelScale = event.pixelScale + this.guider.connected = event.connected + this.guider.state = event.state + this.chartInfo.pixelScale = event.pixelScale } - plotModeChanged() { + protected plotModeChanged() { this.updateGuideHistoryChart() + this.savePreference() } - yAxisUnitChanged() { + protected yAxisUnitChanged() { this.updateGuideHistoryChart() + this.savePreference() } private updateGuideHistoryChart() { - if (this.phdGuideHistory.length > 0) { - const history = this.phdGuideHistory[this.phdGuideHistory.length - 1] - this.rmsTotal = history.rmsTotal - this.rmsDEC = history.rmsDEC - this.rmsRA = history.rmsRA + if (this.guideHistory.length > 0) { + const history = this.guideHistory[this.guideHistory.length - 1] + this.chartInfo.rmsTotal = history.rmsTotal + this.chartInfo.rmsDEC = history.rmsDEC + this.chartInfo.rmsRA = history.rmsRA } else { return } - const startId = this.phdGuideHistory[0].id - const guideSteps = this.phdGuideHistory.filter((e) => e.guideStep !== undefined) - const scale = this.yAxisUnit === 'ARCSEC' ? this.pixelScale : 1.0 + const startId = this.guideHistory[0].id + const guideSteps = this.guideHistory.filter((e) => e.guideStep !== undefined) + const scale = this.preference.yAxisUnit === 'ARCSEC' ? this.chartInfo.pixelScale : 1.0 let maxDuration = 0 @@ -351,9 +335,9 @@ export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { maxDuration = Math.max(maxDuration, Math.abs(step.guideStep!.decDuration)) } - this.phdDurationScale = maxDuration / 16.0 + this.chartInfo.durationScale = maxDuration / 16.0 - if (this.plotMode === 'RA/DEC') { + if (this.preference.plotMode === 'RA/DEC') { this.chartData.datasets[0].data = guideSteps.map((e) => [e.id - startId, -e.guideStep!.raDistance * scale]) this.chartData.datasets[1].data = guideSteps.map((e) => [e.id - startId, e.guideStep!.decDistance * scale]) } else { @@ -362,18 +346,18 @@ export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { } const durationScale = (direction?: GuideDirection) => { - return !direction || direction === 'NORTH' || direction === 'WEST' ? this.phdDurationScale : -this.phdDurationScale + return !direction || direction === 'NORTH' || direction === 'WEST' ? this.chartInfo.durationScale : -this.chartInfo.durationScale } - this.chartData.datasets[2].data = this.phdGuideHistory.map((e) => (e.guideStep?.raDuration ?? 0) / durationScale(e.guideStep?.raDirection)) - this.chartData.datasets[3].data = this.phdGuideHistory.map((e) => (e.guideStep?.decDuration ?? 0) / durationScale(e.guideStep?.decDirection)) + this.chartData.datasets[2].data = this.guideHistory.map((e) => (e.guideStep?.raDuration ?? 0) / durationScale(e.guideStep?.raDirection)) + this.chartData.datasets[3].data = this.guideHistory.map((e) => (e.guideStep?.decDuration ?? 0) / durationScale(e.guideStep?.decDirection)) this.chart.refresh() } - async guideOutputChanged() { + protected async guideOutputChanged() { if (this.guideOutput?.id) { - await this.ping() + await this.tick() const guideOutput = await this.api.guideOutput(this.guideOutput.id) Object.assign(this.guideOutput, guideOutput) @@ -382,28 +366,28 @@ export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { } } - async guidePulseStart(...directions: GuideDirection[]) { + protected async guidePulseStart(...directions: GuideDirection[]) { if (this.guideOutput) { for (const direction of directions) { switch (direction) { case 'NORTH': - await this.api.guideOutputPulse(this.guideOutput, direction, this.guideNorthDuration * 1000) + await this.api.guideOutputPulse(this.guideOutput, direction, this.preference.pulseDuration.north * 1000) break case 'SOUTH': - await this.api.guideOutputPulse(this.guideOutput, direction, this.guideSouthDuration * 1000) + await this.api.guideOutputPulse(this.guideOutput, direction, this.preference.pulseDuration.south * 1000) break case 'WEST': - await this.api.guideOutputPulse(this.guideOutput, direction, this.guideWestDuration * 1000) + await this.api.guideOutputPulse(this.guideOutput, direction, this.preference.pulseDuration.west * 1000) break case 'EAST': - await this.api.guideOutputPulse(this.guideOutput, direction, this.guideEastDuration * 1000) + await this.api.guideOutputPulse(this.guideOutput, direction, this.preference.pulseDuration.east * 1000) break } } } } - async guidePulseStop() { + protected async guidePulseStop() { if (this.guideOutput) { await this.api.guideOutputPulse(this.guideOutput, 'NORTH', 0) await this.api.guideOutputPulse(this.guideOutput, 'SOUTH', 0) @@ -412,40 +396,41 @@ export class GuiderComponent implements AfterViewInit, OnDestroy, Pingable { } } - guidingConnect() { - if (this.connected) { + protected guidingConnect() { + if (this.guider.connected) { return this.api.guidingDisconnect() } else { - return this.api.guidingConnect(this.host, this.port) + return this.api.guidingConnect(this.preference.host, this.preference.port) } } - async guidingStart(event: MouseEvent) { + protected async guidingStart(event: MouseEvent) { await this.api.guidingLoop(true) + await this.api.guidingSettle(this.preference.settle) await this.api.guidingStart(event.shiftKey) } - async settleChanged() { - await this.api.setGuidingSettle({ - amount: this.settleAmount, - time: this.settleTime, - timeout: this.settleTimeout, - }) - } - - guidingClearHistory() { - this.phdGuideHistory.length = 0 + protected guidingClearHistory() { + this.guideHistory.length = 0 return this.api.guidingClearHistory() } - guidingStop() { + protected guidingStop() { return this.api.guidingStop() } + private loadPreference() { + Object.assign(this.preference, this.preferenceService.guider.get()) + } + + protected savePreference() { + this.preferenceService.guider.set(this.preference) + } + private update() { - if (this.guideOutput) { - this.guideOutputConnected = this.guideOutput.connected - this.pulseGuiding = this.guideOutput.pulseGuiding + if (this.guideOutput?.id) { + this.pulse.connected = this.guideOutput.connected + this.pulse.pulsing = this.guideOutput.pulseGuiding } } } diff --git a/desktop/src/app/home/home.component.html b/desktop/src/app/home/home.component.html index bbd3239fd..7f00a41a1 100644 --- a/desktop/src/app/home/home.component.html +++ b/desktop/src/app/home/home.component.html @@ -13,7 +13,7 @@
- {{ item?.name }} + {{ connection?.name }}
{{ item.name }} - {{ item.host }}:{{ item.port }} + {{ item.type }} | {{ item.host }}:{{ item.port }}
{{ (item.connectedAt | date: 'yyyy-MM-dd HH:mm:ss') ?? 'never' }} @@ -239,7 +239,7 @@
@@ -292,18 +292,16 @@ header="Connection" [modal]="true" [draggable]="false" - [(visible)]="showConnectionDialog" + [(visible)]="connectionDialog.showDialog" [style]="{ width: '90vw' }"> -
+
+ [(ngModel)]="connectionDialog.connection.name" />
@@ -312,7 +310,7 @@ + [(ngModel)]="connectionDialog.connection.host" />
@@ -322,25 +320,24 @@ [showButtons]="true" styleClass="border-0 p-inputtext-sm w-full" placeholder="7624" - [(ngModel)]="newConnection[0].port" + [(ngModel)]="connectionDialog.connection.port" [min]="80" [max]="65535" [format]="false" - scrollableNumber /> + spinnableNumber />
+ (deviceDisconnect)="deviceDisconnected($event)" + [toolbarBuilder]="deviceMenuToolbarBuilder" /> button { diff --git a/desktop/src/app/home/home.component.ts b/desktop/src/app/home/home.component.ts index c8d706bec..a1b4ce8de 100644 --- a/desktop/src/app/home/home.component.ts +++ b/desktop/src/app/home/home.component.ts @@ -1,4 +1,4 @@ -import { AfterContentInit, Component, NgZone, ViewChild } from '@angular/core' +import { AfterContentInit, Component, NgZone, ViewChild, ViewEncapsulation } from '@angular/core' import { dirname } from 'path' import { DeviceChooserComponent } from '../../shared/components/device-chooser/device-chooser.component' import { DeviceConnectionCommandEvent, DeviceListMenuComponent } from '../../shared/components/device-list-menu/device-list-menu.component' @@ -8,21 +8,20 @@ import { BrowserWindowService } from '../../shared/services/browser-window.servi import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' import { PrimeService } from '../../shared/services/prime.service' -import { Camera } from '../../shared/types/camera.types' +import { Camera, isCamera, isGuideHead } from '../../shared/types/camera.types' import { Device } from '../../shared/types/device.types' import { Focuser } from '../../shared/types/focuser.types' -import { CONNECTION_TYPES, ConnectionDetails, EMPTY_CONNECTION_DETAILS, HomeWindowType } from '../../shared/types/home.types' +import { ConnectionDetails, DEFAULT_CONNECTION_DETAILS, DEFAULT_HOME_CONNECTION_DIALOG, DEFAULT_HOME_PREFERENCE, HomeWindowType } from '../../shared/types/home.types' import { Mount } from '../../shared/types/mount.types' import { Rotator } from '../../shared/types/rotator.types' -import { FilterWheel } from '../../shared/types/wheel.types' -import { Undefinable } from '../../shared/utils/types' +import { Wheel } from '../../shared/types/wheel.types' import { AppComponent } from '../app.component' interface MappedDevice { CAMERA: Camera MOUNT: Mount FOCUSER: Focuser - WHEEL: FilterWheel + WHEEL: Wheel ROTATOR: Rotator } @@ -34,30 +33,42 @@ function scrollPageOf(element: Element) { selector: 'neb-home', templateUrl: './home.component.html', styleUrls: ['./home.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class HomeComponent implements AfterContentInit { + protected readonly preference = structuredClone(DEFAULT_HOME_PREFERENCE) + protected connection?: ConnectionDetails + protected readonly connectionDialog = structuredClone(DEFAULT_HOME_CONNECTION_DIALOG) + + protected cameras: Camera[] = [] + protected mounts: Mount[] = [] + protected focusers: Focuser[] = [] + protected wheels: Wheel[] = [] + protected rotators: Rotator[] = [] + protected domes: Camera[] = [] + protected switches: Camera[] = [] + + protected currentPage = 0 + + protected readonly deviceModel: MenuItem[] = [] + + protected readonly imageModel: SlideMenuItem[] = [ + { + icon: 'mdi mdi-image-plus', + label: 'Open new image', + slideMenu: [], + command: () => { + return this.openImage(true) + }, + }, + ] + @ViewChild('deviceMenu') private readonly deviceMenu!: DeviceListMenuComponent @ViewChild('imageMenu') private readonly imageMenu!: DeviceListMenuComponent - readonly connectionTypes = Array.from(CONNECTION_TYPES) - showConnectionDialog = false - connections: ConnectionDetails[] = [] - connection?: ConnectionDetails - newConnection?: [ConnectionDetails, Undefinable] - - cameras: Camera[] = [] - mounts: Mount[] = [] - focusers: Focuser[] = [] - wheels: FilterWheel[] = [] - rotators: Rotator[] = [] - domes: Camera[] = [] - switches: Camera[] = [] - - currentPage = 0 - get connected() { return !!this.connection && this.connection.connected } @@ -122,46 +133,13 @@ export class HomeComponent implements AfterContentInit { return this.connection?.type === 'ALPACA' && this.hasDevices } - readonly deviceModel: MenuItem[] = [] - - readonly imageModel: SlideMenuItem[] = [ - { - icon: 'mdi mdi-image-plus', - label: 'Open new image', - slideMenu: [], - command: () => { - return this.openImage(true) - }, - }, - ] - - private startListening(type: K, onAdd: (device: MappedDevice[K]) => number, onRemove: (device: MappedDevice[K]) => number, onUpdate: (device: MappedDevice[K]) => void) { - this.electron.on(`${type}.ATTACHED`, (event) => { - this.ngZone.run(() => { - onAdd(event.device as never) - }) - }) - - this.electron.on(`${type}.DETACHED`, (event) => { - this.ngZone.run(() => { - onRemove(event.device as never) - }) - }) - - this.electron.on(`${type}.UPDATED`, (event) => { - this.ngZone.run(() => { - onUpdate(event.device as never) - }) - }) - } - constructor( app: AppComponent, - private readonly electron: ElectronService, - private readonly browserWindow: BrowserWindowService, + private readonly electronService: ElectronService, + private readonly browserWindowService: BrowserWindowService, private readonly api: ApiService, - private readonly prime: PrimeService, - private readonly preference: PreferenceService, + private readonly primeService: PrimeService, + private readonly preferenceService: PreferenceService, private readonly ngZone: NgZone, ) { app.title = 'Nebulosa' @@ -251,23 +229,18 @@ export class HomeComponent implements AfterContentInit { }, ) - electron.on('CONNECTION.CLOSED', async (event) => { + electronService.on('CONNECTION.CLOSED', async (event) => { if (this.connection?.id === event.id) { await ngZone.run(() => { return this.updateConnection() }) } }) - - this.connections = preference.connections.get().sort((a, b) => (b.connectedAt ?? 0) - (a.connectedAt ?? 0)) - this.connections.forEach((e) => { - e.id = undefined - e.connected = false - }) - this.connection = this.connections[0] } async ngAfterContentInit() { + this.loadPreference() + await this.updateConnection() if (this.connected) { @@ -279,54 +252,71 @@ export class HomeComponent implements AfterContentInit { } } - addConnection() { - this.newConnection = [structuredClone(EMPTY_CONNECTION_DETAILS), undefined] - this.showConnectionDialog = true + private startListening(type: K, onAdd: (device: MappedDevice[K]) => number, onRemove: (device: MappedDevice[K]) => number, onUpdate: (device: MappedDevice[K]) => void) { + this.electronService.on(`${type}.ATTACHED`, (event) => { + this.ngZone.run(() => { + onAdd(event.device as never) + }) + }) + + this.electronService.on(`${type}.DETACHED`, (event) => { + this.ngZone.run(() => { + onRemove(event.device as never) + }) + }) + + this.electronService.on(`${type}.UPDATED`, (event) => { + this.ngZone.run(() => { + onUpdate(event.device as never) + }) + }) + } + + protected addConnection() { + this.connectionDialog.edited = false + this.connectionDialog.connection = structuredClone(DEFAULT_CONNECTION_DETAILS) + this.connectionDialog.showDialog = true } - editConnection(connection: ConnectionDetails, event: MouseEvent) { - this.newConnection = [structuredClone(connection), connection] - this.showConnectionDialog = true + protected editConnection(connection: ConnectionDetails, event: MouseEvent) { + this.connectionDialog.edited = true + this.connectionDialog.connection = connection + this.connectionDialog.showDialog = true event.stopImmediatePropagation() } - deleteConnection(connection: ConnectionDetails, event: MouseEvent) { - const index = this.connections.findIndex((e) => e === connection) + protected deleteConnection(connection: ConnectionDetails, event: MouseEvent) { + const index = this.preference.connections.findIndex((e) => e === connection) if (index >= 0 && !connection.connected) { - this.connections.splice(index, 1) + this.preference.connections.splice(index, 1) + + if (!this.preference.connections.length) { + this.preference.connections.push(structuredClone(DEFAULT_CONNECTION_DETAILS)) + } if (connection === this.connection) { - this.connection = this.connections[0] + this.connection = this.preference.connections[0] } - this.preference.connections.set(this.connections) + this.savePreference() } event.stopImmediatePropagation() } - saveConnection() { - if (this.newConnection) { - // Edit. - if (this.newConnection[1]) { - Object.assign(this.newConnection[1], this.newConnection[0]) - } - // New. - else { - const newConnection = structuredClone(this.newConnection[0]) - this.connections = [...this.connections, newConnection] - this.connection = newConnection - } + protected saveConnection() { + if (!this.connectionDialog.edited) { + this.connection = this.connectionDialog.connection + this.preference.connections.push(this.connection) } - this.preference.connections.set(this.connections) + this.savePreference() - this.newConnection = undefined - this.showConnectionDialog = false + this.connectionDialog.showDialog = false } - async connect() { + protected async connect() { try { if (this.connection && !this.connection.connected) { this.connection.id = await this.api.connect(this.connection.host, this.connection.port, this.connection.type) @@ -334,13 +324,13 @@ export class HomeComponent implements AfterContentInit { } catch (e) { console.error(e) - this.prime.message('Connection failed', 'error') + this.primeService.message('Connection failed', 'error') } finally { await this.updateConnection() } } - async disconnect() { + protected async disconnect() { try { if (this.connection?.id && this.connection.connected) { await this.api.disconnect(this.connection.id) @@ -364,6 +354,23 @@ export class HomeComponent implements AfterContentInit { return DeviceChooserComponent.handleDisconnectDevice(this.api, event.device, event.item) } + protected readonly deviceMenuToolbarBuilder = (device: Device): MenuItem[] => { + if (isCamera(device) && !isGuideHead(device)) { + return [ + { + icon: 'mdi mdi-wrench', + label: 'Calibration', + command: (e) => { + e.originalEvent?.stopImmediatePropagation() + return this.browserWindowService.openCalibration() + }, + }, + ] + } else { + return [] + } + } + private async openDevice(type: K) { this.deviceModel.length = 0 @@ -377,8 +384,7 @@ export class HomeComponent implements AfterContentInit { if (devices.length === 0) return - this.deviceMenu.header = type - const device = await this.deviceMenu.show(devices) + const device = await this.deviceMenu.show(devices, undefined, type) if (device && device !== 'NONE') { await this.openDeviceWindow(type, device as never) @@ -388,43 +394,43 @@ export class HomeComponent implements AfterContentInit { private async openDeviceWindow(type: K, device: MappedDevice[K]) { switch (type) { case 'MOUNT': - await this.browserWindow.openMount(device as Mount, { bringToFront: true }) + await this.browserWindowService.openMount(device as Mount, { bringToFront: true }) break case 'CAMERA': - await this.browserWindow.openCamera(device as Camera, { bringToFront: true }) + await this.browserWindowService.openCamera(device as Camera, { bringToFront: true }) break case 'FOCUSER': - await this.browserWindow.openFocuser(device as Focuser, { bringToFront: true }) + await this.browserWindowService.openFocuser(device as Focuser, { bringToFront: true }) break case 'WHEEL': - await this.browserWindow.openWheel(device as FilterWheel, { bringToFront: true }) + await this.browserWindowService.openWheel(device as Wheel, { bringToFront: true }) break case 'ROTATOR': - await this.browserWindow.openRotator(device as Rotator, { bringToFront: true }) + await this.browserWindowService.openRotator(device as Rotator, { bringToFront: true }) break } } private async openImage(force: boolean = false) { if (force || this.cameras.length === 0) { - const preference = this.preference.homePreference.get() - const path = await this.electron.openImage({ defaultPath: preference.imagePath }) + const path = await this.electronService.openImage({ defaultPath: this.preference.imagePath }) if (path) { - preference.imagePath = dirname(path) - this.preference.homePreference.set(preference) - await this.browserWindow.openImage({ path, source: 'PATH' }) + this.preference.imagePath = dirname(path) + this.savePreference() + + await this.browserWindowService.openImage({ path, source: 'PATH' }) } } else { const camera = await this.imageMenu.show(this.cameras) if (camera && camera !== 'NONE') { - await this.browserWindow.openCameraImage(camera) + await this.browserWindowService.openCameraImage(camera) } } } - async open(type: HomeWindowType) { + protected async open(type: HomeWindowType) { switch (type) { case 'MOUNT': case 'CAMERA': @@ -434,43 +440,43 @@ export class HomeComponent implements AfterContentInit { await this.openDevice(type) break case 'GUIDER': - await this.browserWindow.openGuider({ bringToFront: true }) + await this.browserWindowService.openGuider({ bringToFront: true }) break case 'SKY_ATLAS': - await this.browserWindow.openSkyAtlas(undefined, { bringToFront: true }) + await this.browserWindowService.openSkyAtlas(undefined, { bringToFront: true }) break case 'FRAMING': - await this.browserWindow.openFraming(undefined, { bringToFront: true }) + await this.browserWindowService.openFraming(undefined, { bringToFront: true }) break case 'ALIGNMENT': - await this.browserWindow.openAlignment({ bringToFront: true }) + await this.browserWindowService.openAlignment({ bringToFront: true }) break case 'SEQUENCER': - await this.browserWindow.openSequencer({ bringToFront: true }) + await this.browserWindowService.openSequencer({ bringToFront: true }) break case 'AUTO_FOCUS': - await this.browserWindow.openAutoFocus({ bringToFront: true }) + await this.browserWindowService.openAutoFocus({ bringToFront: true }) break case 'FLAT_WIZARD': - await this.browserWindow.openFlatWizard({ bringToFront: true }) + await this.browserWindowService.openFlatWizard({ bringToFront: true }) break case 'STACKER': - await this.browserWindow.openStacker({ bringToFront: true }) + await this.browserWindowService.openStacker({ bringToFront: true }) break case 'INDI': - await this.browserWindow.openINDI(undefined, { bringToFront: true }) + await this.browserWindowService.openINDI(undefined, { bringToFront: true }) break case 'IMAGE': await this.openImage() break case 'SETTINGS': - await this.browserWindow.openSettings() + await this.browserWindowService.openSettings() break case 'CALCULATOR': - await this.browserWindow.openCalculator() + await this.browserWindowService.openCalculator() break case 'ABOUT': - await this.browserWindow.openAbout() + await this.browserWindowService.openAbout() break } } @@ -482,7 +488,7 @@ export class HomeComponent implements AfterContentInit { if (status && !this.connection.connected) { this.connection.connectedAt = Date.now() - this.preference.connections.set(this.connections) + this.savePreference() this.connection.connected = true } else if (!status) { this.connection.connected = false @@ -494,7 +500,7 @@ export class HomeComponent implements AfterContentInit { const statuses = await this.api.connectionStatuses() for (const status of statuses) { - for (const connection of this.connections) { + for (const connection of this.preference.connections) { if (!connection.connected && (status.host === connection.host || status.ip === connection.host) && status.port === connection.port) { connection.id = status.id connection.type = status.type @@ -521,7 +527,7 @@ export class HomeComponent implements AfterContentInit { } } - scrolled(event: Event) { + protected scrolled(event: Event) { function isVisible(element: Element) { const bound = element.getBoundingClientRect() @@ -540,15 +546,17 @@ export class HomeComponent implements AfterContentInit { } this.currentPage = page + + event.stopImmediatePropagation() } - scrollTo(event: Event, page: number) { + protected scrollTo(event: Event, page: number) { this.currentPage = page this.scrollToPage(page) event.stopImmediatePropagation() } - scrollToPage(page: number) { + protected scrollToPage(page: number) { const scrollChidren = document.getElementsByClassName('scroll-child') for (let i = 0; i < scrollChidren.length; i++) { @@ -560,4 +568,25 @@ export class HomeComponent implements AfterContentInit { } } } + + private loadPreference() { + Object.assign(this.preference, this.preferenceService.home.get()) + + this.preference.connections + .sort((a, b) => (b.connectedAt ?? 0) - (a.connectedAt ?? 0)) + .forEach((e) => { + e.id = undefined + e.connected = false + }) + + if (!this.preference.connections.length) { + this.preference.connections.push(structuredClone(DEFAULT_CONNECTION_DETAILS)) + } + + this.connection = this.preference.connections[0] + } + + protected savePreference() { + this.preferenceService.home.set(this.preference) + } } diff --git a/desktop/src/app/image/image.component.html b/desktop/src/app/image/image.component.html index a9670890b..23710ccfd 100644 --- a/desktop/src/app/image/image.component.html +++ b/desktop/src/app/image/image.component.html @@ -226,7 +226,7 @@ [(ngModel)]="annotation.minorPlanetsMagLimit" [minFractionDigits]="1" locale="en" - scrollableNumber /> + spinnableNumber />
@@ -455,7 +455,7 @@ styleClass="p-inputtext-sm border-0 w-full" [showButtons]="true" [(ngModel)]="solver.radius" - scrollableNumber /> + spinnableNumber />
@@ -470,7 +470,7 @@ [(ngModel)]="solver.focalLength" [allowEmpty]="false" locale="en" - scrollableNumber /> + spinnableNumber />
@@ -485,7 +485,7 @@ [(ngModel)]="solver.pixelSize" [allowEmpty]="false" locale="en" - scrollableNumber /> + spinnableNumber />
@@ -626,7 +626,7 @@ styleClass="p-inputtext-sm border-0 w-full" [(ngModel)]="stretchShadow" locale="en" - scrollableNumber /> + spinnableNumber /> @@ -637,7 +637,7 @@ styleClass="p-inputtext-sm border-0 w-full" [(ngModel)]="stretchHighlight" locale="en" - scrollableNumber /> + spinnableNumber />
@@ -660,7 +660,7 @@ styleClass="p-inputtext-sm border-0 w-full" [(ngModel)]="stretchMidtone" locale="en" - scrollableNumber /> + spinnableNumber />
@@ -742,7 +742,7 @@ [(ngModel)]="scnr.amount" locale="en" [allowEmpty]="false" - scrollableNumber /> + spinnableNumber />
@@ -935,7 +935,7 @@ [(ngModel)]="starDetection.minSNR" locale="en" [allowEmpty]="false" - scrollableNumber /> + spinnableNumber />
@@ -953,7 +953,7 @@ [(ngModel)]="starDetection.maxStars" locale="en" [allowEmpty]="false" - scrollableNumber /> + spinnableNumber />
@@ -1090,7 +1090,7 @@ styleClass="p-inputtext-sm border-0" [showButtons]="true" [(ngModel)]="fov.focalLength" - scrollableNumber /> + spinnableNumber />
@@ -1100,7 +1100,7 @@ styleClass="p-inputtext-sm border-0" [showButtons]="true" [(ngModel)]="fov.aperture" - scrollableNumber /> + spinnableNumber />
@@ -1122,7 +1122,7 @@ [min]="1" [max]="9999" [(ngModel)]="fov.cameraSize.width" - scrollableNumber /> + spinnableNumber />
@@ -1134,7 +1134,7 @@ [min]="1" [max]="9999" [(ngModel)]="fov.cameraSize.height" - scrollableNumber /> + spinnableNumber />
@@ -1150,7 +1150,7 @@ [maxFractionDigits]="2" [(ngModel)]="fov.pixelSize.width" locale="en" - scrollableNumber /> + spinnableNumber />
@@ -1166,7 +1166,7 @@ [maxFractionDigits]="2" [(ngModel)]="fov.pixelSize.height" locale="en" - scrollableNumber /> + spinnableNumber />
@@ -1182,7 +1182,7 @@ [maxFractionDigits]="2" [(ngModel)]="fov.barlowReducer" locale="en" - scrollableNumber /> + spinnableNumber />
@@ -1194,7 +1194,7 @@ [min]="1" [max]="5" [(ngModel)]="fov.bin" - scrollableNumber /> + spinnableNumber />
@@ -1210,7 +1210,7 @@ [maxFractionDigits]="2" [(ngModel)]="fov.rotation" locale="en" - scrollableNumber /> + spinnableNumber />
--> diff --git a/desktop/src/app/image/image.component.ts b/desktop/src/app/image/image.component.ts index f7a960a32..0b72a763a 100644 --- a/desktop/src/app/image/image.component.ts +++ b/desktop/src/app/image/image.component.ts @@ -19,8 +19,8 @@ import { Camera } from '../../shared/types/camera.types' import { AnnotationInfoDialog, DEFAULT_FOV, + DEFAULT_IMAGE_SOLVED, DetectedStar, - EMPTY_IMAGE_SOLVED, FITSHeaderItem, FOV, IMAGE_STATISTICS_BIT_OPTIONS, @@ -44,6 +44,8 @@ import { StarDetectionDialog, } from '../../shared/types/image.types' import { Mount } from '../../shared/types/mount.types' +import { PlateSolverRequest } from '../../shared/types/platesolver.types' +import { StarDetectionRequest } from '../../shared/types/stardetector.types' import { CoordinateInterpolator, InterpolatedCoordinate } from '../../shared/utils/coordinate-interpolation' import { AppComponent } from '../app.component' @@ -167,7 +169,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { radius: 4, focalLength: 0, pixelSize: 0, - solved: structuredClone(EMPTY_IMAGE_SOLVED), + solved: structuredClone(DEFAULT_IMAGE_SOLVED), } crossHair = false @@ -824,7 +826,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.starDetection.visible = false this.detectStarsMenuItem.checkable = false - Object.assign(this.solver.solved, EMPTY_IMAGE_SOLVED) + Object.assign(this.solver.solved, DEFAULT_IMAGE_SOLVED) this.histogram?.update([]) } @@ -846,13 +848,18 @@ export class ImageComponent implements AfterViewInit, OnDestroy { const path = this.imagePath if (path) { - const options = this.preference.starDetectionRequest(this.starDetection.type).get() - options.minSNR = this.starDetection.minSNR - options.maxStars = this.starDetection.maxStars + const request: StarDetectionRequest = { + ...this.preference.settings.get().starDetector[this.starDetection.type], + type: this.starDetection.type, + minSNR: this.starDetection.minSNR, + maxStars: this.starDetection.maxStars, + } + + Object.assign(this.starDetection, this.preference.settings.get().starDetector[this.starDetection.type]) try { this.starDetection.running = true - this.starDetection.stars = await this.api.detectStars(path, options) + this.starDetection.stars = await this.api.detectStars(path, request) } finally { this.starDetection.running = false } @@ -1173,10 +1180,14 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.solver.running = true try { - const solver = this.preference.plateSolverRequest(this.solver.type).get() - solver.pixelSize = this.solver.pixelSize - solver.focalLength = this.solver.focalLength - const solved = await this.api.solverStart(solver, path, this.solver.blind, this.solver.centerRA, this.solver.centerDEC, this.solver.radius) + const request: PlateSolverRequest = { + ...this.preference.settings.get().plateSolver[this.solver.type], + type: this.solver.type, + pixelSize: this.solver.pixelSize, + focalLength: this.solver.focalLength, + } + + const solved = await this.api.solverStart(request, path, this.solver.blind, this.solver.centerRA, this.solver.centerDEC, this.solver.radius) this.savePreference() this.updateImageSolved(solved) @@ -1197,7 +1208,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } private updateImageSolved(solved?: ImageSolved) { - Object.assign(this.solver.solved, solved ?? EMPTY_IMAGE_SOLVED) + Object.assign(this.solver.solved, solved ?? DEFAULT_IMAGE_SOLVED) this.annotationMenuItem.disabled = !this.solver.solved.solved this.fovMenuItem.disabled = !this.solver.solved.solved this.pointMountHereMenuItem.disabled = !this.solver.solved.solved @@ -1249,12 +1260,11 @@ export class ImageComponent implements AfterViewInit, OnDestroy { filterKey: () => { return true }, - beforeWheel: () => { - return false // e.target !== this.image.nativeElement && e.target !== this.roi.nativeElement + beforeWheel: (e) => { + return e.target !== this.image.nativeElement && e.target !== this.roi.nativeElement }, beforeMouseDown: (e) => { - // return e.target !== this.image.nativeElement - return e.target === this.roi.nativeElement + return e.target !== this.image.nativeElement }, }) @@ -1385,8 +1395,6 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.solver.focalLength = preference.solver?.focalLength ?? 0 this.solver.pixelSize = preference.solver?.pixelSize ?? 0 this.starDetection.type = preference.starDetection?.type ?? this.starDetection.type - this.starDetection.minSNR = preference.starDetection?.minSNR ?? this.preference.starDetectionRequest(this.starDetection.type).get().minSNR ?? this.starDetection.minSNR - this.starDetection.maxStars = preference.starDetection?.maxStars ?? this.preference.starDetectionRequest(this.starDetection.type).get().maxStars ?? this.starDetection.maxStars this.fov.fovs = this.preference.imageFOVs.get() this.fov.fovs.forEach((e) => { @@ -1424,8 +1432,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { await action(cameras[0]) return true } else { - this.deviceMenu.header = 'CAMERA' - const camera = await this.deviceMenu.show(cameras) + const camera = await this.deviceMenu.show(cameras, undefined, 'CAMERA') if (camera && camera !== 'NONE' && camera.connected) { await action(camera) @@ -1447,8 +1454,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { await action(mounts[0]) return true } else { - this.deviceMenu.header = 'MOUNT' - const mount = await this.deviceMenu.show(mounts) + const mount = await this.deviceMenu.show(mounts, undefined, 'MOUNT') if (mount && mount !== 'NONE' && mount.connected) { await action(mount) diff --git a/desktop/src/app/indi/indi.component.scss b/desktop/src/app/indi/indi.component.scss index 6c27e4f87..465bcc5e8 100644 --- a/desktop/src/app/indi/indi.component.scss +++ b/desktop/src/app/indi/indi.component.scss @@ -1,16 +1,16 @@ -:host { - ::ng-deep { - .p-listbox-list-wrapper { - max-height: calc(100vh - 175px) !important; - } +neb-indi { + .properties { + height: calc(100vh - 100px); + overflow-y: auto; } -} -.properties { - height: calc(100vh - 100px); - overflow-y: auto; -} + .properties::-webkit-scrollbar { + display: none; + } -.properties::-webkit-scrollbar { - display: none; + .p-listbox-filter.p-inputtext { + border: 0px; + border-radius: 4px; + background: #1a1a1a; + } } diff --git a/desktop/src/app/indi/indi.component.ts b/desktop/src/app/indi/indi.component.ts index c33d85881..b718a8b59 100644 --- a/desktop/src/app/indi/indi.component.ts +++ b/desktop/src/app/indi/indi.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, HostListener, NgZone, OnDestroy, ViewChild } from '@angular/core' +import { AfterViewInit, Component, HostListener, NgZone, OnDestroy, ViewChild, ViewEncapsulation } from '@angular/core' import { ActivatedRoute } from '@angular/router' import { MenuItem } from 'primeng/api' import { Listbox } from 'primeng/listbox' @@ -12,31 +12,32 @@ import { AppComponent } from '../app.component' selector: 'neb-indi', templateUrl: './indi.component.html', styleUrls: ['./indi.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class INDIComponent implements AfterViewInit, OnDestroy { - devices: Device[] = [] - properties: INDIProperty[] = [] - groups: MenuItem[] = [] + protected devices: Device[] = [] + protected properties: INDIProperty[] = [] + protected groups: MenuItem[] = [] - device?: Device - group = '' - showLog = false - messages: string[] = [] + protected device?: Device + protected group = '' + protected showLog = false + protected messages: string[] = [] @ViewChild('listbox') - readonly messageListbox!: Listbox + protected readonly messageBox!: Listbox constructor( app: AppComponent, private readonly route: ActivatedRoute, private readonly api: ApiService, - electron: ElectronService, + electronService: ElectronService, ngZone: NgZone, ) { app.title = 'INDI' - electron.on('DEVICE.PROPERTY_CHANGED', (event) => { - if (this.device?.id === event.device.id) { + electronService.on('DEVICE.PROPERTY_CHANGED', (event) => { + if (event.device.id === this.device?.id) { ngZone.run(() => { if (event.property) { this.addOrUpdateProperty(event.property) @@ -46,8 +47,8 @@ export class INDIComponent implements AfterViewInit, OnDestroy { } }) - electron.on('DEVICE.PROPERTY_DELETED', (event) => { - if (this.device?.id === event.device.id) { + electronService.on('DEVICE.PROPERTY_DELETED', (event) => { + if (event.device.id === this.device?.id) { const index = this.properties.findIndex((e) => e.name === event.property?.name) if (index >= 0) { @@ -59,12 +60,12 @@ export class INDIComponent implements AfterViewInit, OnDestroy { } }) - electron.on('DEVICE.MESSAGE_RECEIVED', (event) => { - if (this.device && event.device.id === this.device.id) { + electronService.on('DEVICE.MESSAGE_RECEIVED', (event) => { + if (event.device.id === this.device?.id) { ngZone.run(() => { if (event.message) { this.messages.splice(0, 0, event.message) - this.messageListbox.cd.markForCheck() + this.messageBox.cd.markForCheck() } }) } diff --git a/desktop/src/app/indi/property/indi-property.component.scss b/desktop/src/app/indi/property/indi-property.component.scss index fc6120b85..33a3607f1 100644 --- a/desktop/src/app/indi/property/indi-property.component.scss +++ b/desktop/src/app/indi/property/indi-property.component.scss @@ -3,19 +3,19 @@ border-radius: 8px; display: block; margin-bottom: 4px; -} -.mdi.mdi-circle { - &.IDLE { - color: #039be5; - } - &.OK { - color: #43a047; - } - &.BUSY { - color: #f57c00; - } - &.ALERT { - color: #e53935; + .mdi.mdi-circle { + &.IDLE { + color: #039be5; + } + &.OK { + color: #43a047; + } + &.BUSY { + color: #f57c00; + } + &.ALERT { + color: #e53935; + } } } diff --git a/desktop/src/app/indi/property/indi-property.component.ts b/desktop/src/app/indi/property/indi-property.component.ts index 19be45587..87e58f06a 100644 --- a/desktop/src/app/indi/property/indi-property.component.ts +++ b/desktop/src/app/indi/property/indi-property.component.ts @@ -1,4 +1,4 @@ -import { AfterContentInit, Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core' +import { AfterContentInit, Component, EventEmitter, Input, Output } from '@angular/core' import { INDIProperty, INDIPropertyItem, INDISendProperty, INDISendPropertyItem } from '../../../shared/types/device.types' @Component({ @@ -6,12 +6,12 @@ import { INDIProperty, INDIPropertyItem, INDISendProperty, INDISendPropertyItem templateUrl: './indi-property.component.html', styleUrls: ['./indi-property.component.scss'], }) -export class INDIPropertyComponent implements AfterContentInit, OnDestroy { +export class INDIPropertyComponent implements AfterContentInit { @Input({ required: true }) - property!: INDIProperty + protected property!: INDIProperty @Input() - disabled = false + protected disabled = false @Output() readonly onSend = new EventEmitter() @@ -24,8 +24,6 @@ export class INDIPropertyComponent implements AfterContentInit, OnDestroy { } } - ngOnDestroy() {} - sendSwitch(item: INDIPropertyItem) { const property: INDISendProperty = { name: this.property.name, diff --git a/desktop/src/app/mount/mount.component.html b/desktop/src/app/mount/mount.component.html index e8acceb0a..c3bcd4512 100644 --- a/desktop/src/app/mount/mount.component.html +++ b/desktop/src/app/mount/mount.component.html @@ -11,7 +11,7 @@ - {{ parking ? 'parking' : parked ? 'parked' : slewing ? 'slewing' : tracking ? 'tracking' : 'idle' }} + {{ mount.parking ? 'parking' : mount.parked ? 'parked' : mount.slewing ? 'slewing' : tracking ? 'tracking' : 'idle' }}
@@ -55,7 +55,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="rightAscensionJ2000" /> + [value]="currentComputedLocation.rightAscensionJ2000" /> @@ -65,7 +65,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="declinationJ2000" /> + [value]="currentComputedLocation.declinationJ2000" /> @@ -75,7 +75,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="rightAscension" /> + [value]="mount.rightAscension" /> @@ -85,7 +85,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="declination" /> + [value]="mount.declination" /> @@ -95,7 +95,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="azimuth" /> + [value]="currentComputedLocation.azimuth" /> @@ -105,7 +105,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="altitude" /> + [value]="currentComputedLocation.altitude" /> @@ -115,7 +115,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="lst" /> + [value]="currentComputedLocation.lst" /> @@ -125,7 +125,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="constellation ?? '-'" /> + [value]="currentComputedLocation.constellation" /> @@ -135,7 +135,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - value="{{ meridianAt }} (-{{ timeLeftToMeridianFlip }})" /> + value="{{ currentComputedLocation.meridianAt }} (-{{ currentComputedLocation.timeLeftToMeridianFlip }})" /> @@ -145,7 +145,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="pierSide" /> + [value]="currentComputedLocation.pierSide" /> @@ -162,9 +162,9 @@
@@ -197,9 +197,9 @@ @@ -209,9 +209,9 @@ @@ -219,7 +219,7 @@
+ spinnableNumber />
diff --git a/desktop/src/app/mount/mount.component.ts b/desktop/src/app/mount/mount.component.ts index a744a786f..4dd76c69c 100644 --- a/desktop/src/app/mount/mount.component.ts +++ b/desktop/src/app/mount/mount.component.ts @@ -7,48 +7,28 @@ import { SEPARATOR_MENU_ITEM } from '../../shared/constants' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' -import { Pingable, Pinger } from '../../shared/services/pinger.service' import { PreferenceService } from '../../shared/services/preference.service' import { PrimeService } from '../../shared/services/prime.service' -import { Angle, ComputedLocation, Constellation, EMPTY_COMPUTED_LOCATION, SkyAtlasInput, SkyAtlasTab } from '../../shared/types/atlas.types' -import { EMPTY_MOUNT, Mount, MountPreference, MountRemoteControlDialog, MountRemoteControlType, MoveDirectionType, PierSide, SlewRate, TargetCoordinateType, TrackMode } from '../../shared/types/mount.types' +import { Tickable, Ticker } from '../../shared/services/ticker.service' +import { ComputedLocation, DEFAULT_COMPUTED_LOCATION, SkyAtlasTab } from '../../shared/types/atlas.types' +import { DEFAULT_MOUNT, DEFAULT_MOUNT_PREFERENCE, Mount, MountRemoteControlDialog, MountRemoteControlType, MoveDirectionType, SlewRate, TrackMode } from '../../shared/types/mount.types' import { AppComponent } from '../app.component' -import { FramingData } from '../framing/framing.component' @Component({ selector: 'neb-mount', templateUrl: './mount.component.html', }) -export class MountComponent implements AfterContentInit, OnDestroy, Pingable { - readonly mount = structuredClone(EMPTY_MOUNT) - - slewing = false - parking = false - parked = false - trackModes: TrackMode[] = ['SIDEREAL'] - trackMode: TrackMode = 'SIDEREAL' - slewRates: SlewRate[] = [] - slewRate?: SlewRate - tracking = false - canPark = false - canHome = false - slewingDirection?: MoveDirectionType - - rightAscensionJ2000: Angle = '00h00m00s' - declinationJ2000: Angle = `00ยฐ00'00"` - rightAscension: Angle = '00h00m00s' - declination: Angle = `00ยฐ00'00"` - azimuth: Angle = `000ยฐ00'00"` - altitude: Angle = `+00ยฐ00'00"` - lst = '00:00' - constellation?: Constellation - timeLeftToMeridianFlip = '00:00' - meridianAt = '00:00' - pierSide: PierSide = 'NEITHER' - targetCoordinateType: TargetCoordinateType = 'JNOW' - targetRightAscension: Angle = '00h00m00s' - targetDeclination: Angle = `00ยฐ00'00"` - targetComputedLocation = structuredClone(EMPTY_COMPUTED_LOCATION) +export class MountComponent implements AfterContentInit, OnDestroy, Tickable { + protected readonly mount = structuredClone(DEFAULT_MOUNT) + + protected tracking = false + protected trackMode: TrackMode = 'SIDEREAL' + protected slewRate?: SlewRate + protected slewingDirection?: MoveDirectionType + + protected readonly preference = structuredClone(DEFAULT_MOUNT_PREFERENCE) + protected currentComputedLocation = structuredClone(DEFAULT_COMPUTED_LOCATION) + protected targetComputedLocation = structuredClone(DEFAULT_COMPUTED_LOCATION) private readonly computeCoordinatePublisher = new Subject() private readonly computeTargetCoordinatePublisher = new Subject() @@ -61,8 +41,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { label: 'Frame', slideMenu: [], command: () => { - const data: FramingData = { rightAscension: this.rightAscensionJ2000, declination: this.declinationJ2000 } - return this.browserWindow.openFraming(data) + return this.browserWindowService.openFraming({ rightAscension: this.currentComputedLocation.rightAscensionJ2000, declination: this.currentComputedLocation.declinationJ2000 }) }, }, SEPARATOR_MENU_ITEM, @@ -71,12 +50,13 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { label: 'Find sky objects around the coordinates', slideMenu: [], command: () => { - const data: SkyAtlasInput = { - tab: SkyAtlasTab.SKY_OBJECT, - filter: { rightAscension: this.rightAscensionJ2000, declination: this.declinationJ2000 }, - } - - return this.browserWindow.openSkyAtlas(data, { bringToFront: true }) + return this.browserWindowService.openSkyAtlas( + { + tab: SkyAtlasTab.SKY_OBJECT, + filter: { rightAscension: this.currentComputedLocation.rightAscensionJ2000, declination: this.currentComputedLocation.declinationJ2000 }, + }, + { bringToFront: true }, + ) }, }, ] @@ -88,7 +68,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { slideMenu: [], command: () => { this.targetCoordinateCommand = this.targetCoordinateModel[0] - return this.goTo() + this.savePreference() }, }, { @@ -97,7 +77,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { slideMenu: [], command: () => { this.targetCoordinateCommand = this.targetCoordinateModel[1] - return this.slewTo() + this.savePreference() }, }, { @@ -106,7 +86,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { slideMenu: [], command: () => { this.targetCoordinateCommand = this.targetCoordinateModel[2] - return this.sync() + this.savePreference() }, }, { @@ -114,8 +94,13 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { label: 'Frame', slideMenu: [], command: () => { - const data: FramingData = { rightAscension: this.targetRightAscension, declination: this.targetDeclination } - return this.browserWindow.openFraming(data) + const { targetRightAscension, targetDeclination, targetCoordinateType } = this.preference + + if (targetCoordinateType === 'J2000') { + return this.browserWindowService.openFraming({ rightAscension: targetRightAscension, declination: targetDeclination }) + } else { + return this.browserWindowService.openFraming({ rightAscension: this.targetComputedLocation.rightAscensionJ2000, declination: this.targetComputedLocation.declinationJ2000 }) + } }, }, SEPARATOR_MENU_ITEM, @@ -128,9 +113,9 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { label: 'Current location', slideMenu: [], command: () => { - this.targetRightAscension = this.rightAscension - this.targetDeclination = this.declination - this.targetCoordinateType = 'JNOW' + this.preference.targetRightAscension = this.mount.rightAscension + this.preference.targetDeclination = this.mount.declination + this.preference.targetCoordinateType = 'JNOW' }, }, { @@ -138,9 +123,9 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { label: 'Current location (J2000)', slideMenu: [], command: () => { - this.targetRightAscension = this.rightAscensionJ2000 - this.targetDeclination = this.declinationJ2000 - this.targetCoordinateType = 'J2000' + this.preference.targetRightAscension = this.currentComputedLocation.rightAscensionJ2000 + this.preference.targetDeclination = this.currentComputedLocation.declinationJ2000 + this.preference.targetCoordinateType = 'J2000' }, }, { @@ -216,9 +201,9 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { }, ] - targetCoordinateCommand = this.targetCoordinateModel[0] + protected targetCoordinateCommand = this.targetCoordinateModel[0] - readonly remoteControl: MountRemoteControlDialog = { + protected readonly remoteControl: MountRemoteControlDialog = { showDialog: false, type: 'LX200', host: '0.0.0.0', @@ -229,17 +214,17 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { constructor( private readonly app: AppComponent, private readonly api: ApiService, - private readonly browserWindow: BrowserWindowService, - electron: ElectronService, - private readonly preference: PreferenceService, + private readonly browserWindowService: BrowserWindowService, + electronService: ElectronService, + private readonly preferenceService: PreferenceService, private readonly route: ActivatedRoute, - private readonly prime: PrimeService, - private readonly pinger: Pinger, + private readonly primeService: PrimeService, + private readonly ticker: Ticker, ngZone: NgZone, ) { app.title = 'Mount' - electron.on('MOUNT.UPDATED', async (event) => { + electronService.on('MOUNT.UPDATED', async (event) => { if (event.device.id === this.mount.id) { await ngZone.run(async () => { const wasConnected = this.mount.connected @@ -253,10 +238,10 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { } }) - electron.on('MOUNT.DETACHED', (event) => { + electronService.on('MOUNT.DETACHED', (event) => { if (event.device.id === this.mount.id) { ngZone.run(() => { - Object.assign(this.mount, EMPTY_MOUNT) + Object.assign(this.mount, DEFAULT_MOUNT) }) } }) @@ -316,13 +301,13 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { this.route.queryParams.subscribe(async (e) => { const mount = JSON.parse(decodeURIComponent(e['data'] as string)) as Mount await this.mountChanged(mount) - this.pinger.register(this, 30000) + this.ticker.register(this, 30000) }) } @HostListener('window:unload') ngOnDestroy() { - this.pinger.unregister(this) + this.ticker.unregister(this) this.computeCoordinateSubscriptions.forEach((e) => { e.unsubscribe() @@ -331,13 +316,13 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { void this.abort() } - async ping() { + async tick() { if (this.mount.id) { await this.api.mountListen(this.mount) } } - async mountChanged(mount?: Mount) { + protected async mountChanged(mount?: Mount) { if (mount?.id) { mount = await this.api.mount(mount.id) Object.assign(this.mount, mount) @@ -349,7 +334,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { this.app.subTitle = mount?.name ?? '' } - connect() { + protected connect() { if (this.mount.connected) { return this.api.mountDisconnect(this.mount) } else { @@ -357,41 +342,44 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { } } - async showRemoteControlDialog() { + protected async showRemoteControlDialog() { this.remoteControl.data = await this.api.mountRemoteControlList(this.mount) this.remoteControl.showDialog = true } - async startRemoteControl() { + protected async startRemoteControl() { try { await this.api.mountRemoteControlStart(this.mount, this.remoteControl.type, this.remoteControl.host, this.remoteControl.port) this.remoteControl.data = await this.api.mountRemoteControlList(this.mount) } catch { - this.prime.message('Failed to start remote control', 'error') + this.primeService.message('Failed to start remote control', 'error') } } - async stopRemoteControl(type: MountRemoteControlType) { + protected async stopRemoteControl(type: MountRemoteControlType) { await this.api.mountRemoteControlStop(this.mount, type) this.remoteControl.data = await this.api.mountRemoteControlList(this.mount) } - async goTo() { - await this.api.mountGoTo(this.mount, this.targetRightAscension, this.targetDeclination, this.targetCoordinateType === 'J2000') + protected async goTo() { + const { targetRightAscension, targetDeclination, targetCoordinateType } = this.preference + await this.api.mountGoTo(this.mount, targetRightAscension, targetDeclination, targetCoordinateType === 'J2000') this.savePreference() } - async slewTo() { - await this.api.mountSlew(this.mount, this.targetRightAscension, this.targetDeclination, this.targetCoordinateType === 'J2000') + protected async slewTo() { + const { targetRightAscension, targetDeclination, targetCoordinateType } = this.preference + await this.api.mountSlew(this.mount, targetRightAscension, targetDeclination, targetCoordinateType === 'J2000') this.savePreference() } - async sync() { - await this.api.mountSync(this.mount, this.targetRightAscension, this.targetDeclination, this.targetCoordinateType === 'J2000') + protected async sync() { + const { targetRightAscension, targetDeclination, targetCoordinateType } = this.preference + await this.api.mountSync(this.mount, targetRightAscension, targetDeclination, targetCoordinateType === 'J2000') this.savePreference() } - async targetCoordinateCommandClicked() { + protected async targetCoordinateCommandClicked() { if (this.targetCoordinateCommand === this.targetCoordinateModel[0]) { await this.goTo() } else if (this.targetCoordinateCommand === this.targetCoordinateModel[1]) { @@ -401,7 +389,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { } } - moveTo(direction: MoveDirectionType, pressed: boolean, event?: MouseEvent) { + protected moveTo(direction: MoveDirectionType, pressed: boolean, event?: MouseEvent) { if (!event || event.button === 0) { this.slewingDirection = pressed ? direction : undefined @@ -441,50 +429,40 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { } } - abort() { + protected abort() { return this.api.mountAbort(this.mount) } - trackingToggled() { + protected trackingToggled() { return this.api.mountTracking(this.mount, this.tracking) } - trackModeChanged() { + protected trackModeChanged() { return this.api.mountTrackMode(this.mount, this.trackMode) } - async slewRateChanged() { + protected async slewRateChanged() { if (this.slewRate) { await this.api.mountSlewRate(this.mount, this.slewRate) } } - park() { + protected park() { return this.api.mountPark(this.mount) } - unpark() { + protected unpark() { return this.api.mountUnpark(this.mount) } - home() { + protected home() { return this.api.mountHome(this.mount) } private update() { if (this.mount.id) { - this.slewing = this.mount.slewing - this.parking = this.mount.parking - this.parked = this.mount.parked - this.canPark = this.mount.canPark - this.canHome = this.mount.canHome - this.trackModes = this.mount.trackModes this.trackMode = this.mount.trackMode - this.slewRates = this.mount.slewRates this.slewRate = this.mount.slewRate - this.rightAscension = this.mount.rightAscension - this.declination = this.mount.declination - this.pierSide = this.mount.pierSide this.tracking = this.mount.tracking this.computeCoordinatePublisher.next() @@ -493,56 +471,44 @@ export class MountComponent implements AfterContentInit, OnDestroy, Pingable { private async computeCoordinates() { if (this.mount.connected) { - const computedCoordinates = await this.api.mountComputeLocation(this.mount, false, this.mount.rightAscension, this.mount.declination, true, true, true) - this.rightAscensionJ2000 = computedCoordinates.rightAscensionJ2000 - this.declinationJ2000 = computedCoordinates.declinationJ2000 - this.azimuth = computedCoordinates.azimuth - this.altitude = computedCoordinates.altitude - this.constellation = computedCoordinates.constellation - this.meridianAt = computedCoordinates.meridianAt - this.timeLeftToMeridianFlip = computedCoordinates.timeLeftToMeridianFlip - this.lst = computedCoordinates.lst + Object.assign(this.currentComputedLocation, await this.api.mountComputeLocation(this.mount, false, this.mount.rightAscension, this.mount.declination, true, true, true)) } } - async computeTargetCoordinates() { + protected async computeTargetCoordinates() { if (this.mount.connected) { - const computedLocation = await this.api.mountComputeLocation(this.mount, this.targetCoordinateType === 'J2000', this.targetRightAscension, this.targetDeclination, true, true, true) + const { targetRightAscension, targetDeclination, targetCoordinateType } = this.preference + const computedLocation = await this.api.mountComputeLocation(this.mount, targetCoordinateType === 'J2000', targetRightAscension, targetDeclination, true, true, true) this.targetComputedLocation = computedLocation } } private updateTargetCoordinate(coordinates: ComputedLocation) { - if (this.targetCoordinateType === 'J2000') { - this.targetRightAscension = coordinates.rightAscensionJ2000 - this.targetDeclination = coordinates.declinationJ2000 + if (this.preference.targetCoordinateType === 'J2000') { + this.preference.targetRightAscension = coordinates.rightAscensionJ2000 + this.preference.targetDeclination = coordinates.declinationJ2000 } else { - this.targetRightAscension = coordinates.rightAscension - this.targetDeclination = coordinates.declination + this.preference.targetRightAscension = coordinates.rightAscension + this.preference.targetDeclination = coordinates.declination } + this.savePreference() + this.computeTargetCoordinatePublisher.next() } private loadPreference() { if (this.mount.id) { - const mountPreference: Partial = this.preference.mountPreference(this.mount).get() - this.targetCoordinateType = mountPreference.targetCoordinateType ?? 'JNOW' - this.targetRightAscension = mountPreference.targetRightAscension ?? '00h00m00s' - this.targetDeclination = mountPreference.targetDeclination ?? `00ยฐ00'00"` + Object.assign(this.preference, this.preferenceService.mount(this.mount).get()) + this.targetCoordinateCommand = this.targetCoordinateModel[this.preference.targetCoordinateCommand] ?? this.targetCoordinateModel[0] this.computeTargetCoordinatePublisher.next() } } private savePreference() { if (this.mount.connected) { - const preference: MountPreference = { - targetCoordinateType: this.targetCoordinateType, - targetRightAscension: this.targetRightAscension, - targetDeclination: this.targetDeclination, - } - - this.preference.mountPreference(this.mount).set(preference) + this.preference.targetCoordinateCommand = this.targetCoordinateModel.indexOf(this.targetCoordinateCommand) + this.preferenceService.mount(this.mount).set(this.preference) } } } diff --git a/desktop/src/app/rotator/rotator.component.html b/desktop/src/app/rotator/rotator.component.html index 7e9cc5dfd..1e415be90 100644 --- a/desktop/src/app/rotator/rotator.component.html +++ b/desktop/src/app/rotator/rotator.component.html @@ -11,7 +11,7 @@
- {{ moving ? 'moving' : 'idle' }} + {{ rotator.moving ? 'moving' : 'idle' }}
@@ -45,13 +45,13 @@ styleClass="p-inputtext-sm border-0 max-w-full" [(ngModel)]="rotator.angle" locale="en" - scrollableNumber /> + spinnableNumber />
Reversed + [(ngModel)]="rotator.reversed" />
@@ -85,14 +85,15 @@ [max]="rotator.maxAngle" [showButtons]="true" styleClass="p-inputtext-sm border-0 max-w-full" - [(ngModel)]="angle" + [(ngModel)]="preference.angle" + (ngModelChange)="savePreference()" [allowEmpty]="false" locale="en" - scrollableNumber /> + spinnableNumber /> { + electronService.on('ROTATOR.UPDATED', (event) => { if (event.device.id === this.rotator.id) { ngZone.run(() => { Object.assign(this.rotator, event.device) @@ -38,10 +35,10 @@ export class RotatorComponent implements AfterViewInit, OnDestroy, Pingable { } }) - electron.on('ROTATOR.DETACHED', (event) => { + electronService.on('ROTATOR.DETACHED', (event) => { if (event.device.id === this.rotator.id) { ngZone.run(() => { - Object.assign(this.rotator, EMPTY_ROTATOR) + Object.assign(this.rotator, DEFAULT_ROTATOR) }) } }) @@ -51,23 +48,23 @@ export class RotatorComponent implements AfterViewInit, OnDestroy, Pingable { this.route.queryParams.subscribe(async (e) => { const rotator = JSON.parse(decodeURIComponent(e['data'] as string)) as Rotator await this.rotatorChanged(rotator) - this.pinger.register(this, 30000) + this.ticker.register(this, 30000) }) } @HostListener('window:unload') ngOnDestroy() { - this.pinger.unregister(this) + this.ticker.unregister(this) void this.abort() } - async ping() { + async tick() { if (this.rotator.id) { await this.api.rotatorListen(this.rotator) } } - async rotatorChanged(rotator?: Rotator) { + protected async rotatorChanged(rotator?: Rotator) { if (rotator?.id) { rotator = await this.api.rotator(rotator.id) Object.assign(this.rotator, rotator) @@ -79,7 +76,7 @@ export class RotatorComponent implements AfterViewInit, OnDestroy, Pingable { this.app.subTitle = rotator?.name ?? '' } - connect() { + protected connect() { if (this.rotator.connected) { return this.api.rotatorDisconnect(this.rotator) } else { @@ -87,52 +84,37 @@ export class RotatorComponent implements AfterViewInit, OnDestroy, Pingable { } } - reverse(enabled: boolean) { + protected reverse(enabled: boolean) { return this.api.rotatorReverse(this.rotator, enabled) } - async move() { - if (!this.moving) { - this.moving = true - await this.api.rotatorMove(this.rotator, this.angle) - this.savePreference() - } + protected move() { + return this.api.rotatorMove(this.rotator, this.preference.angle) } - async sync() { - if (!this.moving) { - await this.api.rotatorSync(this.rotator, this.angle) - this.savePreference() - } + protected sync() { + return this.api.rotatorSync(this.rotator, this.preference.angle) } - abort() { + protected abort() { return this.api.rotatorAbort(this.rotator) } - home() { + protected home() { return this.api.rotatorHome(this.rotator) } - private update() { - if (this.rotator.id) { - this.moving = this.rotator.moving - this.reversed = this.rotator.reversed - } - } + private update() {} private loadPreference() { if (this.rotator.id) { - const preference = this.preference.rotatorPreference(this.rotator).get() - this.angle = preference.angle ?? 0 + Object.assign(this.preference, this.preferenceService.rotator(this.rotator).get()) } } - private savePreference() { + protected savePreference() { if (this.rotator.connected) { - const preference = this.preference.rotatorPreference(this.rotator).get() - preference.angle = this.angle - this.preference.rotatorPreference(this.rotator).set(preference) + this.preferenceService.rotator(this.rotator).set(this.preference) } } } diff --git a/desktop/src/app/sequencer/sequencer.component.html b/desktop/src/app/sequencer/sequencer.component.html index 10c057c2e..c6ddd1e9e 100644 --- a/desktop/src/app/sequencer/sequencer.component.html +++ b/desktop/src/app/sequencer/sequencer.component.html @@ -19,7 +19,7 @@ styleClass="p-inputtext-sm border-0" [allowEmpty]="false" (ngModelChange)="savePlan()" - scrollableNumber /> + spinnableNumber />
@@ -59,7 +59,7 @@ tooltipPosition="bottom" [positionTop]="8"> + spinnableNumber /> @@ -116,7 +116,7 @@ [(ngModel)]="plan.dither.afterExposures" [step]="1" (ngModelChange)="savePlan()" - scrollableNumber /> + spinnableNumber /> @@ -163,7 +163,7 @@ [(ngModel)]="plan.autoFocus.afterElapsedTime" [step]="1" (ngModelChange)="savePlan()" - scrollableNumber /> + spinnableNumber /> @@ -183,7 +183,7 @@ [(ngModel)]="plan.autoFocus.afterExposures" [step]="1" (ngModelChange)="savePlan()" - scrollableNumber /> + spinnableNumber /> @@ -203,7 +203,7 @@ [(ngModel)]="plan.autoFocus.afterTemperatureChange" [step]="1" (ngModelChange)="savePlan()" - scrollableNumber /> + spinnableNumber /> @@ -223,7 +223,7 @@ [(ngModel)]="plan.autoFocus.afterHFDIncrease" [step]="1" (ngModelChange)="savePlan()" - scrollableNumber /> + spinnableNumber /> diff --git a/desktop/src/app/sequencer/sequencer.component.scss b/desktop/src/app/sequencer/sequencer.component.scss index bf78461c8..bbe2b5908 100644 --- a/desktop/src/app/sequencer/sequencer.component.scss +++ b/desktop/src/app/sequencer/sequencer.component.scss @@ -1,24 +1,22 @@ -:host { - ::ng-deep { - .p-card { - .p-card-body { - padding: 0px; - padding-left: 1rem !important; - padding-right: 1rem !important; - } - - .p-card-content { - padding: 0px; - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; - } +neb-sequencer { + .p-card { + .p-card-body { + padding: 0px; + padding-left: 1rem !important; + padding-right: 1rem !important; } - .p-orderlist-controls { - display: none; + .p-card-content { + padding: 0px; + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; } } + .p-orderlist-controls { + display: none; + } + .mdi.mdi-progress-indicator:before { font-size: 11px; } diff --git a/desktop/src/app/sequencer/sequencer.component.ts b/desktop/src/app/sequencer/sequencer.component.ts index f70f87ee4..8ff97e04c 100644 --- a/desktop/src/app/sequencer/sequencer.component.ts +++ b/desktop/src/app/sequencer/sequencer.component.ts @@ -1,22 +1,22 @@ import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop' -import { AfterContentInit, Component, HostListener, NgZone, OnDestroy, QueryList, ViewChildren } from '@angular/core' +import { AfterContentInit, Component, HostListener, NgZone, OnDestroy, QueryList, ViewChildren, ViewEncapsulation } from '@angular/core' import { CameraExposureComponent } from '../../shared/components/camera-exposure/camera-exposure.component' import { DialogMenuComponent } from '../../shared/components/dialog-menu/dialog-menu.component' import { SlideMenuItem } from '../../shared/components/menu-item/menu-item.component' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' -import { Pingable, Pinger } from '../../shared/services/pinger.service' import { PreferenceService } from '../../shared/services/preference.service' import { PrimeService } from '../../shared/services/prime.service' +import { Tickable, Ticker } from '../../shared/services/ticker.service' import { JsonFile } from '../../shared/types/app.types' -import { Camera, CameraCaptureEvent, CameraStartCapture, FrameType, updateCameraStartCaptureFromCamera } from '../../shared/types/camera.types' +import { Camera, CameraCaptureEvent, CameraStartCapture, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, FrameType, updateCameraStartCaptureFromCamera } from '../../shared/types/camera.types' import { Focuser } from '../../shared/types/focuser.types' import { Mount } from '../../shared/types/mount.types' import { Rotator } from '../../shared/types/rotator.types' -import { EMPTY_SEQUENCE_PLAN, SEQUENCE_ENTRY_PROPERTIES, SequenceCaptureMode, SequenceEntryProperty, SequencePlan, SequencerEvent } from '../../shared/types/sequencer.types' -import { DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, resetCameraCaptureNamingFormat } from '../../shared/types/settings.types' -import { FilterWheel } from '../../shared/types/wheel.types' +import { DEFAULT_SEQUENCE_PLAN, SEQUENCE_ENTRY_PROPERTIES, SequenceCaptureMode, SequenceEntryProperty, SequencePlan, SequencerEvent } from '../../shared/types/sequencer.types' +import { resetCameraCaptureNamingFormat } from '../../shared/types/settings.types' +import { Wheel } from '../../shared/types/wheel.types' import { deviceComparator } from '../../shared/utils/comparators' import { Undefinable } from '../../shared/utils/types' import { AppComponent } from '../app.component' @@ -29,22 +29,23 @@ export const SEQUENCER_SAVED_PATH_KEY = 'sequencer.savedPath' selector: 'neb-sequencer', templateUrl: './sequencer.component.html', styleUrls: ['./sequencer.component.scss'], + encapsulation: ViewEncapsulation.None, }) -export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable { +export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable { cameras: Camera[] = [] mounts: Mount[] = [] - wheels: FilterWheel[] = [] + wheels: Wheel[] = [] focusers: Focuser[] = [] rotators: Rotator[] = [] camera?: Camera mount?: Mount - wheel?: FilterWheel + wheel?: Wheel focuser?: Focuser rotator?: Rotator readonly captureModes: SequenceCaptureMode[] = ['FULLY', 'INTERLEAVED'] - readonly plan = structuredClone(EMPTY_SEQUENCE_PLAN) + readonly plan = structuredClone(DEFAULT_SEQUENCE_PLAN) private entryToApply?: CameraStartCapture private entryToApplyCount: [number, number] = [0, 0] @@ -129,7 +130,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable private readonly electron: ElectronService, private readonly preference: PreferenceService, private readonly prime: PrimeService, - private readonly pinger: Pinger, + private readonly ticker: Ticker, ngZone: NgZone, ) { app.title = 'Sequencer' @@ -140,7 +141,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable command: () => { this.updateSavedPath() - Object.assign(this.plan, structuredClone(EMPTY_SEQUENCE_PLAN)) + Object.assign(this.plan, structuredClone(DEFAULT_SEQUENCE_PLAN)) this.add() }, }) @@ -253,7 +254,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable } async ngAfterContentInit() { - this.pinger.register(this, 30000) + this.ticker.register(this, 30000) this.cameras = (await this.api.cameras()).sort(deviceComparator) this.mounts = (await this.api.mounts()).sort(deviceComparator) @@ -268,10 +269,10 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable @HostListener('window:unload') ngOnDestroy() { - this.pinger.unregister(this) + this.ticker.unregister(this) } - async ping() { + async tick() { if (this.camera?.id) await this.api.cameraListen(this.camera) if (this.mount?.id) await this.api.mountListen(this.mount) if (this.focuser?.id) await this.api.focuserListen(this.focuser) @@ -306,6 +307,9 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable frameFormat: camera?.frameFormats[0], autoSave: true, autoSubFolderMode: 'OFF', + filterPosition: 0, + shutterPosition: 0, + focusOffset: 0, dither: { enabled: false, amount: 0, @@ -389,18 +393,17 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable this.focuser = this.focusers.find((e) => e.id === this.plan.focuser) ?? this.focusers[0] this.rotator = this.rotators.find((e) => e.id === this.plan.rotator) ?? this.rotators[0] - const cameraCaptureNamingFormatPreference = this.preference.cameraCaptureNamingFormatPreference.get() - this.plan.namingFormat.light ??= cameraCaptureNamingFormatPreference.light ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.light - this.plan.namingFormat.dark ??= cameraCaptureNamingFormatPreference.dark ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.dark - this.plan.namingFormat.flat ??= cameraCaptureNamingFormatPreference.flat ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.flat - this.plan.namingFormat.bias ??= cameraCaptureNamingFormatPreference.bias ?? DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.bias + const settings = this.preference.settings.get() + this.plan.namingFormat.light ??= settings.namingFormat.light || DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.light + this.plan.namingFormat.dark ??= settings.namingFormat.dark || DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.dark + this.plan.namingFormat.flat ??= settings.namingFormat.flat || DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.flat + this.plan.namingFormat.bias ??= settings.namingFormat.bias || DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.bias return this.plan.entries.length } resetCameraCaptureNamingFormat(type: FrameType) { - const namingFormatPreference = this.preference.cameraCaptureNamingFormatPreference.get() - resetCameraCaptureNamingFormat(type, this.plan.namingFormat, namingFormatPreference) + resetCameraCaptureNamingFormat(type, this.plan.namingFormat, this.preference.settings.get().namingFormat) this.savePlan() } @@ -435,7 +438,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable } async cameraChanged() { - await this.ping() + await this.tick() this.updateEntriesFromCamera(this.camera) } @@ -449,19 +452,19 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable } mountChanged() { - return this.ping() + return this.tick() } focuserChanged() { - return this.ping() + return this.tick() } wheelChanged() { - return this.ping() + return this.tick() } rotatorChanged() { - return this.ping() + return this.tick() } savePlan() { diff --git a/desktop/src/app/settings/settings.component.html b/desktop/src/app/settings/settings.component.html index a096e3ffa..0d2c87435 100644 --- a/desktop/src/app/settings/settings.component.html +++ b/desktop/src/app/settings/settings.component.html @@ -18,9 +18,9 @@
@@ -82,12 +81,12 @@ class="col-12" *ngIf="plateSolverType !== 'ASTROMETRY_NET_ONLINE'"> + (pathChange)="savePreference()" />
@if (plateSolverType === 'ASTROMETRY_NET_ONLINE') {
@@ -95,8 +94,8 @@ + [(ngModel)]="plateSolver.apiUrl" + (ngModelChange)="savePreference()" />
@@ -105,8 +104,8 @@ + [(ngModel)]="plateSolver.apiKey" + (ngModelChange)="savePreference()" /> @@ -116,12 +115,12 @@ + spinnableNumber /> @@ -129,12 +128,12 @@ + spinnableNumber /> @@ -149,10 +148,10 @@ [showButtons]="true" class="w-full" styleClass="p-inputtext-sm border-0 w-full" - [ngModel]="plateSolvers.get(plateSolverType)!.slot" - (ngModelChange)="plateSolvers.get(plateSolverType)!.slot = $event; save()" + [(ngModel)]="plateSolver.slot" + (ngModelChange)="savePreference()" [allowEmpty]="false" - scrollableNumber /> + spinnableNumber /> @@ -171,68 +170,29 @@ optionsValue="value" [(ngModel)]="starDetectorType" styleClass="p-inputtext-sm border-0" - (ngModelChange)="starDetectors.get(starDetectorType)!.type = $event; save()" [autoDisplayFirst]="false" />
-
-
- - - - -
-
- - - - + (pathChange)="savePreference()" />
+ spinnableNumber />
@@ -247,10 +207,10 @@ [showButtons]="true" class="w-full" styleClass="p-inputtext-sm border-0 w-full" - [ngModel]="starDetectors.get(starDetectorType)!.slot" - (ngModelChange)="starDetectors.get(starDetectorType)!.slot = $event; save()" + [(ngModel)]="starDetector.slot" + (ngModelChange)="savePreference()" [allowEmpty]="false" - scrollableNumber /> + spinnableNumber /> @@ -268,19 +228,18 @@ optionsValue="value" [(ngModel)]="liveStackerType" styleClass="p-inputtext-sm border-0" - (ngModelChange)="liveStackers.get(liveStackerType)!.type = $event; save()" [autoDisplayFirst]="false" />
+ (pathChange)="savePreference()" />
+ spinnableNumber />
@@ -314,19 +273,18 @@ optionsValue="value" [(ngModel)]="stackerType" styleClass="p-inputtext-sm border-0" - (ngModelChange)="stackers.get(stackerType)!.type = $event; save()" [autoDisplayFirst]="false" />
+ (pathChange)="savePreference()" />
+ spinnableNumber />
@@ -357,8 +315,8 @@ + [(ngModel)]="preference.namingFormat.light" + (ngModelChange)="savePreference()" /> + [(ngModel)]="preference.namingFormat.dark" + (ngModelChange)="savePreference()" /> + [(ngModel)]="preference.namingFormat.flat" + (ngModelChange)="savePreference()" /> + [(ngModel)]="preference.namingFormat.bias" + (ngModelChange)="savePreference()" /> () + private readonly locationChangePublisher = new Subject() + private readonly locationChangeSubscription?: Subscription - starDetectorType: StarDetectorType = 'ASTAP' - readonly starDetectors = new Map() + get location() { + return this.preference.locations[this.preference.location] ?? DEFAULT_LOCATION + } - liveStackerType: LiveStackerType = 'SIRIL' - readonly liveStackers = new Map() + get plateSolver() { + return this.preference.plateSolver[this.plateSolverType] + } - stackerType: StackerType = 'PIXINSIGHT' - readonly stackers = new Map() + get starDetector() { + return this.preference.starDetector[this.starDetectorType] + } - readonly cameraCaptureNamingFormat = structuredClone(DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT) + get liveStacker() { + return this.preference.liveStacker[this.liveStackerType] + } - private readonly locationChangePublisher = new Subject() - private readonly locationChangeSubscription?: Subscription + get stacker() { + return this.preference.stacker[this.stackerType] + } constructor( app: AppComponent, - private readonly preference: PreferenceService, - private readonly electron: ElectronService, - private readonly dropdownOptions: DropdownOptionsPipe, + private readonly preferenceService: PreferenceService, + private readonly electronService: ElectronService, ) { app.title = 'Settings' - this.locations = preference.locations.get() - const selectedLocation = preference.selectedLocation.get(this.locations[0]) - this.location = this.locations.find(e => e.id === selectedLocation.id) ?? this.locations[0] - - for (const type of dropdownOptions.transform('PLATE_SOLVER')) { - this.plateSolvers.set(type, preference.plateSolverRequest(type).get()) - } - for (const type of dropdownOptions.transform('STAR_DETECTOR')) { - this.starDetectors.set(type, preference.starDetectionRequest(type).get()) - } - for (const type of dropdownOptions.transform('LIVE_STACKER')) { - this.liveStackers.set(type, preference.liveStackingRequest(type).get()) - } - for (const type of dropdownOptions.transform('STACKER')) { - this.stackers.set(type, preference.stackingRequest(type).get()) - } - - Object.assign(this.cameraCaptureNamingFormat, preference.cameraCaptureNamingFormatPreference.get(this.cameraCaptureNamingFormat)) - this.locationChangeSubscription = this.locationChangePublisher.pipe(debounceTime(2000)).subscribe((location) => { - return this.electron.send('LOCATION.CHANGED', location) + return this.electronService.send('LOCATION.CHANGED', location) }) } + ngAfterViewInit() { + this.loadPreference() + } + ngOnDestroy() { this.locationChangeSubscription?.unsubscribe() } - addLocation() { - const location = structuredClone(EMPTY_LOCATION) + protected addLocation() { + const location = structuredClone(DEFAULT_LOCATION) location.id = +new Date() - this.locations.push(location) - this.location = location - this.save() - this.locationChangePublisher.next(this.location) + this.preference.locations.push(location) + this.preference.location = this.preference.locations.length - 1 + + this.locationChanged() } - deleteLocation() { - if (this.locations.length > 1) { - const index = this.locations.findIndex((e) => e.id === this.location.id) + protected deleteLocation() { + if (this.preference.locations.length > 1) { + const index = this.preference.locations.indexOf(this.location) if (index >= 0) { - this.locations.splice(index, 1) - this.location = this.locations[0]! + this.preference.locations.splice(index, 1) + this.preference.location = 0 - this.save() - this.locationChangePublisher.next(this.location) + this.locationChanged() } } } - locationChanged() { - console.log(this.locations) - this.save() + protected locationChanged(location?: Location) { + if (location) { + this.preference.location = this.preference.locations.indexOf(location) + } + + this.savePreference() + this.locationChangePublisher.next(this.location) } - resetCameraCaptureNamingFormat(type: FrameType) { - resetCameraCaptureNamingFormat(type, this.cameraCaptureNamingFormat, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT) - this.save() + protected resetCameraCaptureNamingFormat(type: FrameType) { + resetCameraCaptureNamingFormat(type, this.preference.namingFormat, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT) + this.savePreference() } - save() { - if (this.location.name) { - this.preference.locations.set(this.locations) - this.preference.selectedLocation.set(this.location) - } - - for (const type of this.dropdownOptions.transform('PLATE_SOLVER')) { - this.preference.plateSolverRequest(type).set(this.plateSolvers.get(type)) - } - for (const type of this.dropdownOptions.transform('STAR_DETECTOR')) { - this.preference.starDetectionRequest(type).set(this.starDetectors.get(type)) - } - for (const type of this.dropdownOptions.transform('LIVE_STACKER')) { - this.preference.liveStackingRequest(type).set(this.liveStackers.get(type)) - } - for (const type of this.dropdownOptions.transform('STACKER')) { - this.preference.stackingRequest(type).set(this.stackers.get(type)) - } + private loadPreference() { + Object.assign(this.preference, this.preferenceService.settings.get()) + } - this.preference.cameraCaptureNamingFormatPreference.set(this.cameraCaptureNamingFormat) + protected savePreference() { + this.preferenceService.settings.set(this.preference) } } diff --git a/desktop/src/app/stacker/stacker.component.html b/desktop/src/app/stacker/stacker.component.html index 6f5cc6800..5c9e9ca81 100644 --- a/desktop/src/app/stacker/stacker.component.html +++ b/desktop/src/app/stacker/stacker.component.html @@ -1,7 +1,7 @@
@@ -123,7 +123,7 @@ [disabled]="!request.flatEnabled" [directory]="false" label="Flat File" - key="STACKER_FLAT_PATH" + key="stacker.flatPath" [(path)]="request.flatPath" class="w-full" (pathChange)="savePreference()" /> @@ -137,7 +137,7 @@ [disabled]="!request.biasEnabled" [directory]="false" label="Bias File" - key="STACKER_BIAS_PATH" + key="stacker.biasPath" [(path)]="request.biasPath" class="w-full" (pathChange)="savePreference()" /> diff --git a/desktop/src/app/stacker/stacker.component.ts b/desktop/src/app/stacker/stacker.component.ts index 9464cb456..af943bac9 100644 --- a/desktop/src/app/stacker/stacker.component.ts +++ b/desktop/src/app/stacker/stacker.component.ts @@ -4,7 +4,7 @@ import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' -import { EMPTY_STACKING_REQUEST, StackingRequest, StackingTarget } from '../../shared/types/stacker.types' +import { DEFAULT_STACKER_PREFERENCE, StackingRequest, StackingTarget } from '../../shared/types/stacker.types' import { AppComponent } from '../app.component' @Component({ @@ -12,8 +12,9 @@ import { AppComponent } from '../app.component' templateUrl: './stacker.component.html', }) export class StackerComponent implements AfterViewInit { - running = false - readonly request = structuredClone(EMPTY_STACKING_REQUEST) + protected running = false + protected readonly preference = structuredClone(DEFAULT_STACKER_PREFERENCE) + protected request = this.preference.request get referenceTarget() { return this.request.targets.find((e) => e.enabled && e.reference && e.type === 'LIGHT') @@ -29,10 +30,10 @@ export class StackerComponent implements AfterViewInit { constructor( app: AppComponent, - private readonly electron: ElectronService, + private readonly electronService: ElectronService, private readonly api: ApiService, - private readonly preference: PreferenceService, - private readonly browserWindow: BrowserWindowService, + private readonly preferenceService: PreferenceService, + private readonly browserWindowService: BrowserWindowService, ) { app.title = 'Stacker' } @@ -43,12 +44,11 @@ export class StackerComponent implements AfterViewInit { this.running = await this.api.stackerIsRunning() } - async openImages() { + protected async openImages() { try { this.running = true - const stackerPreference = this.preference.stackerPreference.get() - const images = await this.electron.openImages({ defaultPath: stackerPreference.defaultPath }) + const images = await this.electronService.openImages({ defaultPath: this.preference.defaultPath }) if (images && images.length) { const targets: StackingTarget[] = [...this.request.targets] @@ -70,15 +70,15 @@ export class StackerComponent implements AfterViewInit { this.request.targets = targets - stackerPreference.defaultPath = dirname(images[0]) - this.preference.stackerPreference.set(stackerPreference) + this.preference.defaultPath = dirname(images[0]) + this.savePreference() } } finally { this.running = false } } - referenceChanged(target: StackingTarget, enabled: boolean) { + protected referenceChanged(target: StackingTarget, enabled: boolean) { if (enabled) { for (const item of this.request.targets) { if (item.reference && item !== target) { @@ -88,11 +88,11 @@ export class StackerComponent implements AfterViewInit { } } - openTargetImage(target: StackingTarget) { - return this.browserWindow.openImage({ path: target.path, id: 'stacker', source: 'PATH' }) + protected openTargetImage(target: StackingTarget) { + return this.browserWindowService.openImage({ path: target.path, id: 'stacker', source: 'PATH' }) } - deleteTarget(target: StackingTarget) { + protected deleteTarget(target: StackingTarget) { const index = this.request.targets.findIndex((e) => e === target) if (index >= 0) { @@ -100,14 +100,13 @@ export class StackerComponent implements AfterViewInit { } } - async startStacking() { - const stackingRequest = this.preference.stackingRequest(this.request.type).get() - this.request.executablePath = stackingRequest.executablePath - this.request.slot = stackingRequest.slot || 1 - this.request.referencePath = this.referenceTarget!.path + protected async startStacking() { + const settings = this.preferenceService.settings.get() const request: StackingRequest = { ...this.request, + ...settings.stacker[this.request.type], + referencePath: this.referenceTarget!.path, targets: this.request.targets.filter((e) => e.enabled), } @@ -118,40 +117,23 @@ export class StackerComponent implements AfterViewInit { const path = await this.api.stackerStart(request) if (path) { - await this.browserWindow.openImage({ path, source: 'STACKER' }) + await this.browserWindowService.openImage({ path, source: 'STACKER' }) } } finally { this.running = false } } - stopStacking() { + protected stopStacking() { return this.api.stackerStop() } private loadPreference() { - const stackerPreference = this.preference.stackerPreference.get() - - this.request.outputDirectory = stackerPreference.outputDirectory ?? '' - this.request.darkPath = stackerPreference.darkPath - this.request.darkEnabled = stackerPreference.darkEnabled ?? false - this.request.flatPath = stackerPreference.flatPath - this.request.flatEnabled = stackerPreference.flatEnabled ?? false - this.request.biasPath = stackerPreference.biasPath - this.request.biasEnabled = stackerPreference.biasEnabled ?? false - this.request.type = stackerPreference.type ?? 'PIXINSIGHT' + Object.assign(this.preference, this.preferenceService.stacker.get()) + this.request = this.preference.request } - savePreference() { - const stackerPreference = this.preference.stackerPreference.get() - stackerPreference.outputDirectory = this.request.outputDirectory - stackerPreference.darkPath = this.request.darkPath - stackerPreference.darkEnabled = this.request.darkEnabled - stackerPreference.flatPath = this.request.flatPath - stackerPreference.flatEnabled = this.request.flatEnabled - stackerPreference.biasPath = this.request.biasPath - stackerPreference.biasEnabled = this.request.biasEnabled - stackerPreference.type = this.request.type - this.preference.stackerPreference.set(stackerPreference) + protected savePreference() { + this.preferenceService.stacker.set(this.preference) } } diff --git a/desktop/src/shared/components/camera-exposure/camera-exposure.component.ts b/desktop/src/shared/components/camera-exposure/camera-exposure.component.ts index e01882614..1c51b1a50 100644 --- a/desktop/src/shared/components/camera-exposure/camera-exposure.component.ts +++ b/desktop/src/shared/components/camera-exposure/camera-exposure.component.ts @@ -1,5 +1,5 @@ import { Component, Input } from '@angular/core' -import { CameraCaptureEvent, CameraCaptureState, EMPTY_CAMERA_CAPTURE_INFO, EMPTY_CAMERA_STEP_INFO } from '../../types/camera.types' +import { CameraCaptureEvent, CameraCaptureState, DEFAULT_CAMERA_CAPTURE_INFO, DEFAULT_CAMERA_STEP_INFO } from '../../types/camera.types' @Component({ selector: 'neb-camera-exposure', @@ -8,18 +8,22 @@ import { CameraCaptureEvent, CameraCaptureState, EMPTY_CAMERA_CAPTURE_INFO, EMPT }) export class CameraExposureComponent { @Input() - info?: string + protected info?: string @Input() - showRemainingTime: boolean = true + protected showRemainingTime: boolean = true @Input() - readonly step = structuredClone(EMPTY_CAMERA_STEP_INFO) + protected readonly step = structuredClone(DEFAULT_CAMERA_STEP_INFO) @Input() - readonly capture = structuredClone(EMPTY_CAMERA_CAPTURE_INFO) + protected readonly capture = structuredClone(DEFAULT_CAMERA_CAPTURE_INFO) - state?: CameraCaptureState = 'IDLE' + protected state: CameraCaptureState = 'IDLE' + + get currentState() { + return this.state + } handleCameraCaptureEvent(event: CameraCaptureEvent, looping: boolean = false) { this.capture.elapsedTime = event.captureElapsedTime @@ -50,13 +54,13 @@ export class CameraExposureComponent { this.state = event.state } - return this.state !== undefined && this.state !== 'CAPTURE_FINISHED' && this.state !== 'IDLE' + return this.state !== 'CAPTURE_FINISHED' && this.state !== 'IDLE' } reset() { this.state = 'IDLE' - Object.assign(this.step, EMPTY_CAMERA_STEP_INFO) - Object.assign(this.capture, EMPTY_CAMERA_CAPTURE_INFO) + Object.assign(this.step, DEFAULT_CAMERA_STEP_INFO) + Object.assign(this.capture, DEFAULT_CAMERA_CAPTURE_INFO) } } diff --git a/desktop/src/shared/components/camera-info/camera-info.component.ts b/desktop/src/shared/components/camera-info/camera-info.component.ts index dd180f422..4e62ec9c4 100644 --- a/desktop/src/shared/components/camera-info/camera-info.component.ts +++ b/desktop/src/shared/components/camera-info/camera-info.component.ts @@ -1,6 +1,6 @@ import { Component, Input } from '@angular/core' import { CameraStartCapture } from '../../types/camera.types' -import { FilterWheel } from '../../types/wheel.types' +import { Wheel } from '../../types/wheel.types' @Component({ selector: 'neb-camera-info', @@ -9,16 +9,16 @@ import { FilterWheel } from '../../types/wheel.types' }) export class CameraInfoComponent { @Input({ required: true }) - readonly info!: CameraStartCapture + protected readonly info!: CameraStartCapture @Input() - readonly wheel?: FilterWheel + protected readonly wheel?: Wheel @Input() - readonly hasType: boolean = true + protected readonly hasType: boolean = true @Input() - readonly hasExposure: boolean = true + protected readonly hasExposure: boolean = true get hasFilter() { return !!this.wheel && !!this.info.filterPosition && this.wheel.connected diff --git a/desktop/src/shared/components/device-chooser/device-chooser.component.ts b/desktop/src/shared/components/device-chooser/device-chooser.component.ts index 3af1562c6..a2b835954 100644 --- a/desktop/src/shared/components/device-chooser/device-chooser.component.ts +++ b/desktop/src/shared/components/device-chooser/device-chooser.component.ts @@ -12,22 +12,22 @@ import { MenuItem } from '../menu-item/menu-item.component' }) export class DeviceChooserComponent { @Input({ required: true }) - readonly title!: string + protected readonly title!: string @Input() - readonly noDeviceMessage?: string + protected readonly noDeviceMessage?: string @Input({ required: true }) - readonly icon!: string + protected readonly icon!: string @Input({ required: true }) - readonly devices!: T[] + protected readonly devices!: T[] @Input() - readonly hasNone: boolean = false + protected readonly hasNone: boolean = false @Input() - device?: T + protected device?: T @Output() readonly deviceChange = new EventEmitter() @@ -67,48 +67,66 @@ export class DeviceChooserComponent { } static async handleConnectDevice(api: ApiService, device: Device, item: MenuItem) { + if (device.connected) return undefined + await api.indiDeviceConnect(device) item.disabled = true - return new Promise>((resolve) => { - setTimeout(async () => { + return new Promise((resolve) => { + let counter = 0 + + const timer = setInterval(async () => { Object.assign(device, await api.indiDevice(device)) if (device.connected) { item.icon = 'mdi mdi-close' item.severity = 'danger' item.label = 'Disconnect' + clearInterval(timer) resolve({ device, item }) - } else { + } else if (counter >= 10) { + clearInterval(timer) resolve(undefined) + } else { + counter++ + return } item.disabled = false - }, 1000) + }, 1500) }) } static async handleDisconnectDevice(api: ApiService, device: Device, item: MenuItem) { + if (!device.connected) return undefined + await api.indiDeviceDisconnect(device) item.disabled = true return new Promise>((resolve) => { - setTimeout(async () => { + let counter = 0 + + const timer = setTimeout(async () => { Object.assign(device, await api.indiDevice(device)) if (!device.connected) { item.icon = 'mdi mdi-connection' item.severity = 'info' item.label = 'Connect' + clearInterval(timer) resolve({ device, item }) - } else { + } else if (counter >= 10) { + clearInterval(timer) resolve(undefined) + } else { + counter++ + return } item.disabled = false - }, 1000) + }, 1500) }) } } diff --git a/desktop/src/shared/components/device-list-menu/device-list-menu.component.scss b/desktop/src/shared/components/device-list-menu/device-list-menu.component.scss index 5581d9d1b..ef8a048d3 100644 --- a/desktop/src/shared/components/device-list-menu/device-list-menu.component.scss +++ b/desktop/src/shared/components/device-list-menu/device-list-menu.component.scss @@ -1,5 +1,5 @@ -:host { - ::ng-deep .p-menuitem-link { +neb-device-list-menu { + .p-menuitem-link { padding: 0.5rem 0.75rem; min-height: 43px; } diff --git a/desktop/src/shared/components/device-list-menu/device-list-menu.component.ts b/desktop/src/shared/components/device-list-menu/device-list-menu.component.ts index 5af2dc2b5..ce6d0db6b 100644 --- a/desktop/src/shared/components/device-list-menu/device-list-menu.component.ts +++ b/desktop/src/shared/components/device-list-menu/device-list-menu.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core' +import { Component, EventEmitter, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core' import { SEPARATOR_MENU_ITEM } from '../../constants' import { PrimeService } from '../../services/prime.service' import { isGuideHead } from '../../types/camera.types' @@ -17,22 +17,26 @@ export interface DeviceConnectionCommandEvent { selector: 'neb-device-list-menu', templateUrl: './device-list-menu.component.html', styleUrls: ['./device-list-menu.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class DeviceListMenuComponent { @Input() - readonly model: SlideMenuItem[] = [] + protected readonly model: SlideMenuItem[] = [] @Input() - readonly modelAtFirst: boolean = true + protected readonly modelAtFirst: boolean = true @Input() - readonly disableIfDeviceIsNotConnected: boolean = true + protected readonly disableIfDeviceIsNotConnected: boolean = true @Input() - header?: string + protected header?: string @Input() - readonly hasNone: boolean = false + protected readonly hasNone: boolean = false + + @Input() + protected readonly toolbarBuilder?: (device: Device) => MenuItem[] @Output() readonly deviceConnect = new EventEmitter() @@ -45,9 +49,11 @@ export class DeviceListMenuComponent { constructor(private readonly prime: PrimeService) {} - show(devices: T[], selected?: NoInfer) { + show(devices: T[], selected?: NoInfer, header?: string) { const model: SlideMenuItem[] = [] + if (header) this.header = header + return new Promise>((resolve) => { if (devices.length <= 0) { resolve(undefined) @@ -92,12 +98,15 @@ export class DeviceListMenuComponent { } for (const device of devices.sort(deviceComparator)) { + const toolbarMenu = this.toolbarBuilder?.(device) ?? [] + model.push({ label: device.name, selected: selected === device, disabled: this.disableIfDeviceIsNotConnected && !device.connected, slideMenu: [], toolbarMenu: [ + ...toolbarMenu, { icon: 'mdi ' + (device.connected ? 'mdi-close' : 'mdi-connection'), severity: device.connected ? 'danger' : 'info', @@ -122,8 +131,7 @@ export class DeviceListMenuComponent { populateWithModel() } - this.menu.model = model - this.menu.show() + this.menu.show(model) }) } diff --git a/desktop/src/shared/components/dialog-menu/dialog-menu.component.html b/desktop/src/shared/components/dialog-menu/dialog-menu.component.html index 1bd0f9b85..453f951ab 100644 --- a/desktop/src/shared/components/dialog-menu/dialog-menu.component.html +++ b/desktop/src/shared/components/dialog-menu/dialog-menu.component.html @@ -10,9 +10,9 @@ (onHide)="hide()" [style]="{ width: 'auto' }"> - {{ header }} + {{ currentHeader }} () @Input() - model: SlideMenuItem[] = [] + protected model: SlideMenuItem[] = [] @Input() - header?: string + protected header?: string @Input() - updateHeaderWithMenuLabel: boolean = true + protected updateHeaderWithMenuLabel: boolean = true + protected currentHeader = this.header private readonly navigationHeader: Undefinable[] = [] - show() { + show(model?: SlideMenuItem[]) { + if (model?.length) this.model = model + this.currentHeader = this.header this.visible = true this.visibleChange.emit(true) } @@ -36,14 +40,14 @@ export class DialogMenuComponent { this.visibleChange.emit(false) } - next(event: MenuItemCommandEvent) { + protected next(event: MenuItemCommandEvent) { if (!event.item?.slideMenu?.length) { this.hide() } else { - this.navigationHeader.push(this.header) + this.navigationHeader.push(this.currentHeader) if (this.updateHeaderWithMenuLabel) { - this.header = event.item.label + this.currentHeader = event.item.label } } } @@ -53,7 +57,7 @@ export class DialogMenuComponent { const header = this.navigationHeader.splice(this.navigationHeader.length - 1, 1)[0] if (this.updateHeaderWithMenuLabel) { - this.header = header + this.currentHeader = header } } } diff --git a/desktop/src/shared/components/map/map.component.html b/desktop/src/shared/components/map/map.component.html index f742cb275..6a925dbe8 100644 --- a/desktop/src/shared/components/map/map.component.html +++ b/desktop/src/shared/components/map/map.component.html @@ -1,4 +1,4 @@
+ style="height: 150px" + class="border-round-md relative">
diff --git a/desktop/src/shared/components/map/map.component.scss b/desktop/src/shared/components/map/map.component.scss index bb0bcd3bd..2486878d8 100644 --- a/desktop/src/shared/components/map/map.component.scss +++ b/desktop/src/shared/components/map/map.component.scss @@ -2,7 +2,3 @@ display: block; width: 100%; } - -::ng-deep .leaflet-marker-shadow { - display: none; -} diff --git a/desktop/src/shared/components/map/map.component.ts b/desktop/src/shared/components/map/map.component.ts index 99d80671a..7a41533ab 100644 --- a/desktop/src/shared/components/map/map.component.ts +++ b/desktop/src/shared/components/map/map.component.ts @@ -7,21 +7,21 @@ import * as L from 'leaflet' styleUrls: ['./map.component.scss'], }) export class MapComponent implements AfterViewInit, OnChanges { - @ViewChild('map') - private readonly mapRef!: ElementRef - @Input() - latitude = 0 + protected latitude = 0 @Output() readonly latitudeChange = new EventEmitter() @Input() - longitude = 0 + protected longitude = 0 @Output() readonly longitudeChange = new EventEmitter() + @ViewChild('map') + private readonly mapRef!: ElementRef + private map?: L.Map private marker?: L.Marker diff --git a/desktop/src/shared/components/menu-bar/menu-bar.component.html b/desktop/src/shared/components/menu-bar/menu-bar.component.html index 3a594981a..903a9e8c3 100644 --- a/desktop/src/shared/components/menu-bar/menu-bar.component.html +++ b/desktop/src/shared/components/menu-bar/menu-bar.component.html @@ -39,7 +39,10 @@ } @else { + [severity]="item.badgeSeverity ?? 'danger'" + [value]="item.badge" + styleClass="absolute flex justify-content-center align-items-center top-0" + [style]="{ width: '14px', minWidth: '14px', height: '14px', minHeight: '14px', right: '-2px' }" /> () diff --git a/desktop/src/shared/components/menu-item/menu-item.component.ts b/desktop/src/shared/components/menu-item/menu-item.component.ts index 85f0ff880..605102cd0 100644 --- a/desktop/src/shared/components/menu-item/menu-item.component.ts +++ b/desktop/src/shared/components/menu-item/menu-item.component.ts @@ -57,5 +57,5 @@ export interface SlideMenuItem extends MenuItem { }) export class MenuItemComponent { @Input({ required: true }) - readonly item!: MenuItem + protected readonly item!: MenuItem } diff --git a/desktop/src/shared/components/moon/moon.component.ts b/desktop/src/shared/components/moon/moon.component.ts index 77a77e97c..4825b51b1 100644 --- a/desktop/src/shared/components/moon/moon.component.ts +++ b/desktop/src/shared/components/moon/moon.component.ts @@ -6,20 +6,20 @@ import { AfterViewInit, Component, ElementRef, Input, OnChanges, ViewChild } fro styleUrls: ['./moon.component.scss'], }) export class MoonComponent implements AfterViewInit, OnChanges { - @ViewChild('moon') - private readonly moon?: ElementRef - @Input() - height = 256 + protected height = 256 @Input() - width = 256 + protected width = 256 @Input() - illuminationRatio = 0 + protected illuminationRatio = 0 @Input() - waning = false + protected waning = false + + @ViewChild('moon') + private readonly moon?: ElementRef ngAfterViewInit() { this.draw() diff --git a/desktop/src/shared/components/path-chooser/path-chooser.component.scss b/desktop/src/shared/components/path-chooser/path-chooser.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/shared/components/path-chooser/path-chooser.component.ts b/desktop/src/shared/components/path-chooser/path-chooser.component.ts index 090302db1..4191b402f 100644 --- a/desktop/src/shared/components/path-chooser/path-chooser.component.ts +++ b/desktop/src/shared/components/path-chooser/path-chooser.component.ts @@ -1,57 +1,46 @@ -import { Component, EventEmitter, Input, OnChanges, Output, SimpleChange, SimpleChanges } from '@angular/core' +import { Component, EventEmitter, Input, Output } from '@angular/core' import { dirname } from 'path' import { ElectronService } from '../../services/electron.service' -import { Undefinable } from '../../utils/types' @Component({ selector: 'neb-path-chooser', templateUrl: './path-chooser.component.html', - styleUrls: ['./path-chooser.component.scss'], }) -export class PathChooserComponent implements OnChanges { +export class PathChooserComponent { @Input({ required: true }) - readonly key!: string + protected readonly key!: string @Input() - readonly label?: string + protected readonly label?: string @Input() - readonly placeholder?: string + protected readonly placeholder?: string @Input() - readonly disabled: boolean = false + protected readonly disabled: boolean = false @Input() - readonly readonly: boolean = false + protected readonly readonly: boolean = false @Input({ required: true }) - readonly directory!: boolean + protected readonly directory!: boolean @Input() - path?: string + protected readonly path?: string @Output() readonly pathChange = new EventEmitter() constructor(private readonly electron: ElectronService) {} - ngOnChanges(changes: SimpleChanges) { - const pathChanged = changes['path'] as Undefinable - - if (pathChanged?.currentValue) { - this.path = pathChanged.currentValue as string - } - } - - async choosePath() { + protected async choosePath() { const key = `pathChooser.${this.key}.defaultPath` - const storedPath = localStorage.getItem(key) - const defaultPath = storedPath && !this.directory ? dirname(storedPath) : this.path + const lastPath = localStorage.getItem(key) || undefined + const defaultPath = lastPath && !this.directory ? dirname(lastPath) : lastPath const path = await (this.directory ? this.electron.openDirectory({ defaultPath }) : this.electron.openFile({ defaultPath })) if (path) { - this.path = path this.pathChange.emit(path) localStorage.setItem(key, path) } diff --git a/desktop/src/shared/components/slide-menu/slide-menu.component.ts b/desktop/src/shared/components/slide-menu/slide-menu.component.ts index 0b1df0c79..a180c25cc 100644 --- a/desktop/src/shared/components/slide-menu/slide-menu.component.ts +++ b/desktop/src/shared/components/slide-menu/slide-menu.component.ts @@ -20,7 +20,7 @@ export class SlideMenuComponent implements OnInit { @Output() readonly onBack = new EventEmitter() - currentMenu!: SlideMenuItem[] + protected currentMenu!: SlideMenuItem[] private readonly navigation: SlideMenuItem[][] = [] diff --git a/desktop/src/shared/dialogs/confirm/confirm.dialog.scss b/desktop/src/shared/dialogs/confirm/confirm.dialog.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/shared/dialogs/confirm/confirm.dialog.ts b/desktop/src/shared/dialogs/confirm/confirm.dialog.ts index 802fb7a07..9a60a74ca 100644 --- a/desktop/src/shared/dialogs/confirm/confirm.dialog.ts +++ b/desktop/src/shared/dialogs/confirm/confirm.dialog.ts @@ -4,8 +4,7 @@ import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog' import { PrimeService } from '../../services/prime.service' @Component({ - templateUrl: './confirm.dialog.html', - styleUrls: ['./confirm.dialog.scss'], + templateUrl: './confirm.dialog.html' }) export class ConfirmDialog { readonly header: string diff --git a/desktop/src/shared/dialogs/location/location.dialog.html b/desktop/src/shared/dialogs/location/location.dialog.html index e7b01f44e..8bb727601 100644 --- a/desktop/src/shared/dialogs/location/location.dialog.html +++ b/desktop/src/shared/dialogs/location/location.dialog.html @@ -21,7 +21,7 @@ (ngModelChange)="locationChanged()" [showButtons]="true" [allowEmpty]="false" - scrollableNumber /> + spinnableNumber />
@@ -37,7 +37,7 @@ (ngModelChange)="locationChanged()" [showButtons]="true" [allowEmpty]="false" - scrollableNumber /> + spinnableNumber /> @@ -52,7 +52,7 @@ [(ngModel)]="location.latitude" (ngModelChange)="locationChanged()" [allowEmpty]="false" - scrollableNumber /> + spinnableNumber /> @@ -67,7 +67,7 @@ [(ngModel)]="location.longitude" (ngModelChange)="locationChanged()" [allowEmpty]="false" - scrollableNumber /> + spinnableNumber /> diff --git a/desktop/src/shared/dialogs/location/location.dialog.scss b/desktop/src/shared/dialogs/location/location.dialog.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/shared/dialogs/location/location.dialog.ts b/desktop/src/shared/dialogs/location/location.dialog.ts index 1b7e979b8..be8865098 100644 --- a/desktop/src/shared/dialogs/location/location.dialog.ts +++ b/desktop/src/shared/dialogs/location/location.dialog.ts @@ -1,12 +1,11 @@ import { AfterViewInit, Component, EventEmitter, Input, Optional, Output, ViewChild } from '@angular/core' import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog' import { MapComponent } from '../../components/map/map.component' -import { EMPTY_LOCATION, Location } from '../../types/atlas.types' +import { DEFAULT_LOCATION, Location } from '../../types/atlas.types' @Component({ selector: 'neb-location', templateUrl: './location.dialog.html', - styleUrls: ['./location.dialog.scss'], }) export class LocationDialog implements AfterViewInit { @ViewChild('map') @@ -27,7 +26,7 @@ export class LocationDialog implements AfterViewInit { @Optional() config?: DynamicDialogConfig, ) { if (config) { - this.location = config.data ?? structuredClone(EMPTY_LOCATION) + this.location = config.data ?? structuredClone(DEFAULT_LOCATION) } } diff --git a/desktop/src/shared/directives/input-number-scrollable.ts b/desktop/src/shared/directives/spinnable-number.directive.ts similarity index 83% rename from desktop/src/shared/directives/input-number-scrollable.ts rename to desktop/src/shared/directives/spinnable-number.directive.ts index a7797ddd4..a3b588cd2 100644 --- a/desktop/src/shared/directives/input-number-scrollable.ts +++ b/desktop/src/shared/directives/spinnable-number.directive.ts @@ -1,8 +1,8 @@ import { Directive, Host, HostListener } from '@angular/core' import { InputNumber } from 'primeng/inputnumber' -@Directive({ selector: '[scrollableNumber]' }) -export class ScrollableNumberDirective { +@Directive({ selector: '[spinnableNumber]' }) +export class SpinnableNumberDirective { constructor(@Host() private readonly inputNumber: InputNumber) {} @HostListener('wheel', ['$event']) diff --git a/desktop/src/shared/directives/stop-propagation.directive.ts b/desktop/src/shared/directives/stop-propagation.directive.ts index 29726b68b..5de9883da 100644 --- a/desktop/src/shared/directives/stop-propagation.directive.ts +++ b/desktop/src/shared/directives/stop-propagation.directive.ts @@ -3,13 +3,13 @@ import { Directive, HostListener, Input } from '@angular/core' @Directive({ selector: '[stopPropagation]' }) export class StopPropagationDirective { @Input('spEnabled') - readonly enabled: boolean = true + protected readonly enabled: boolean = true @Input('spImmediate') - readonly immediate: boolean = true + protected readonly immediate: boolean = true @Input('spPreventDefault') - readonly preventDefault: boolean = false + protected readonly preventDefault: boolean = false @HostListener('click', ['$event']) @HostListener('contextmenu', ['$event']) diff --git a/desktop/src/shared/interceptors/location.interceptor.ts b/desktop/src/shared/interceptors/location.interceptor.ts index 3efc4f402..b45d9a143 100644 --- a/desktop/src/shared/interceptors/location.interceptor.ts +++ b/desktop/src/shared/interceptors/location.interceptor.ts @@ -11,10 +11,10 @@ export class LocationInterceptor implements HttpInterceptor { intercept(req: HttpRequest, next: HttpHandler): Observable> { if (req.urlWithParams.includes('hasLocation')) { - const location = this.preference.selectedLocation.get() + const { location, locations } = this.preference.settings.get() req = req.clone({ - headers: req.headers.set(LocationInterceptor.HEADER_KEY, JSON.stringify(location)), + headers: req.headers.set(LocationInterceptor.HEADER_KEY, JSON.stringify(locations[location])), }) } diff --git a/desktop/src/shared/pipes/dropdown-options.pipe.ts b/desktop/src/shared/pipes/dropdown-options.pipe.ts index 0f231c974..7daf27113 100644 --- a/desktop/src/shared/pipes/dropdown-options.pipe.ts +++ b/desktop/src/shared/pipes/dropdown-options.pipe.ts @@ -3,6 +3,7 @@ import { Hemisphere } from '../types/alignment.types' import { AutoFocusFittingMode, BacklashCompensationMode } from '../types/autofocus.type' import { ExposureMode, FrameType, LiveStackerType } from '../types/camera.types' import { GuideDirection, GuiderPlotMode, GuiderYAxisUnit } from '../types/guider.types' +import { ConnectionType } from '../types/home.types' import { Bitpix, ImageChannel, ImageFormat, SCNRProtectionMethod } from '../types/image.types' import { MountRemoteControlType } from '../types/mount.types' import { PlateSolverType } from '../types/platesolver.types' @@ -34,6 +35,7 @@ export interface DropdownOptions { STACKER: StackerType[] SETTINGS_TAB: SettingsTabKey[] STACKER_GROUP_TYPE: StackerGroupType[] + CONNECTION_TYPE: ConnectionType[] } @Pipe({ name: 'dropdownOptions' }) @@ -84,6 +86,8 @@ export class DropdownOptionsPipe implements PipeTransform { return ['LOCATION', 'PLATE_SOLVER', 'STAR_DETECTOR', 'LIVE_STACKER', 'STACKER', 'CAPTURE_NAMING_FORMAT'] as DropdownOptions[K] case 'STACKER_GROUP_TYPE': return ['LUMINANCE', 'RED', 'GREEN', 'BLUE', 'MONO', 'RGB'] as DropdownOptions[K] + case 'CONNECTION_TYPE': + return ['INDI', 'ALPACA'] as DropdownOptions[K] } return [] diff --git a/desktop/src/shared/pipes/enum.pipe.ts b/desktop/src/shared/pipes/enum.pipe.ts index a681c0a5a..607919209 100644 --- a/desktop/src/shared/pipes/enum.pipe.ts +++ b/desktop/src/shared/pipes/enum.pipe.ts @@ -2,7 +2,7 @@ import { Pipe, PipeTransform } from '@angular/core' import { DARVState, Hemisphere, TPPAState } from '../types/alignment.types' import { Constellation, SatelliteGroupType, SkyObjectType } from '../types/atlas.types' import { AutoFocusFittingMode, AutoFocusState, BacklashCompensationMode } from '../types/autofocus.type' -import { CameraCaptureState, ExposureMode, FrameType, LiveStackerType } from '../types/camera.types' +import { CameraCaptureState, ExposureMode, ExposureTimeUnit, FrameType, LiveStackerType } from '../types/camera.types' import { FlatWizardState } from '../types/flat-wizard.types' import { GuideDirection, GuideState, GuiderPlotMode, GuiderYAxisUnit } from '../types/guider.types' import { Bitpix, SCNRProtectionMethod } from '../types/image.types' @@ -43,6 +43,7 @@ export type EnumPipeKey = | StackerGroupType | SettingsTabKey | SequencerState + | ExposureTimeUnit | 'ALL' @Pipe({ name: 'enum' }) @@ -271,11 +272,14 @@ export class EnumPipe implements PipeTransform { MEN: 'Mensa', METRIC_RADIO_SOURCE: 'Metric Radio Source', MIC: 'Microscopium', + MICROSECOND: 'ยตs', MICRO_LENSING_EVENT: '(Micro)Lensing Event', MID_IR_SOURCE_3_TO_30_M: 'Mid-IR Source (3 to 30 ยตm)', MILITARY: 'Miscellaneous Military', + MILLISECOND: 'ms', MILLIMETRIC_RADIO_SOURCE: 'Millimetric Radio Source', MINIMUM_NEUTRAL: 'Minimum Neutral', + MINUTE: 'm', MIRA_VARIABLE: 'Mira Variable', MOLECULAR_CLOUD: 'Molecular Cloud', MOLNIYA: 'Molniya', @@ -362,6 +366,7 @@ export class EnumPipe implements PipeTransform { SCO: 'Scorpius', SCT: 'Scutum', SELECTED: 'Selected', + SECOND: 's', SER: 'Serpens', SES: 'SES', SETTLING: 'Settling', diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts index 0c5d9f7d4..5cd060b33 100644 --- a/desktop/src/shared/services/api.service.ts +++ b/desktop/src/shared/services/api.service.ts @@ -10,7 +10,7 @@ import { FlatWizardRequest } from '../types/flat-wizard.types' import { Focuser } from '../types/focuser.types' import { HipsSurvey } from '../types/framing.types' import { GuideDirection, GuideOutput, Guider, GuiderHistoryStep, SettleInfo } from '../types/guider.types' -import { ConnectionStatus, ConnectionType, Equipment } from '../types/home.types' +import { ConnectionStatus, ConnectionType } from '../types/home.types' import { CoordinateInterpolation, DetectedStar, FOVCamera, FOVTelescope, ImageAnnotation, ImageInfo, ImageSaveDialog, ImageSolved, ImageTransformation } from '../types/image.types' import { CelestialLocationType, Mount, MountRemoteControl, MountRemoteControlType, SlewRate, TrackMode } from '../types/mount.types' import { PlateSolverRequest } from '../types/platesolver.types' @@ -18,7 +18,7 @@ import { Rotator } from '../types/rotator.types' import { SequencePlan } from '../types/sequencer.types' import { AnalyzedTarget, StackingRequest } from '../types/stacker.types' import { StarDetectionRequest } from '../types/stardetector.types' -import { FilterWheel } from '../types/wheel.types' +import { Wheel } from '../types/wheel.types' import { Undefinable } from '../utils/types' import { HttpService } from './http.service' @@ -71,12 +71,6 @@ export class ApiService { return this.http.get(`cameras/${camera.id}/capturing`) } - cameraSnoop(camera: Camera, equipment: Equipment) { - const { mount, wheel, focuser, rotator } = equipment - const query = this.http.query({ mount: mount?.id, wheel: wheel?.id, focuser: focuser?.id, rotator: rotator?.id }) - return this.http.put(`cameras/${camera.id}/snoop?${query}`) - } - cameraCooler(camera: Camera, enabled: boolean) { return this.http.put(`cameras/${camera.id}/cooler?enabled=${enabled}`) } @@ -85,8 +79,7 @@ export class ApiService { return this.http.put(`cameras/${camera.id}/temperature/setpoint?temperature=${temperature}`) } - cameraStartCapture(camera: Camera, data: CameraStartCapture, equipment: Equipment) { - const { mount, wheel, focuser, rotator } = equipment + cameraStartCapture(camera: Camera, data: CameraStartCapture, mount?: Mount, wheel?: Wheel, focuser?: Focuser, rotator?: Rotator) { const query = this.http.query({ mount: mount?.id, wheel: wheel?.id, focuser: focuser?.id, rotator: rotator?.id }) return this.http.put(`cameras/${camera.id}/capture/start?${query}`, data) } @@ -249,30 +242,30 @@ export class ApiService { // FILTER WHEEL wheels() { - return this.http.get(`wheels`) + return this.http.get(`wheels`) } wheel(id: string) { - return this.http.get(`wheels/${id}`) + return this.http.get(`wheels/${id}`) } - wheelConnect(wheel: FilterWheel) { + wheelConnect(wheel: Wheel) { return this.http.put(`wheels/${wheel.id}/connect`) } - wheelDisconnect(wheel: FilterWheel) { + wheelDisconnect(wheel: Wheel) { return this.http.put(`wheels/${wheel.id}/disconnect`) } - wheelMoveTo(wheel: FilterWheel, position: number) { + wheelMoveTo(wheel: Wheel, position: number) { return this.http.put(`wheels/${wheel.id}/move-to?position=${position}`) } - wheelSync(wheel: FilterWheel, names: string[]) { + wheelSync(wheel: Wheel, names: string[]) { return this.http.put(`wheels/${wheel.id}/sync?names=${names.join(',')}`) } - wheelListen(wheel: FilterWheel) { + wheelListen(wheel: Wheel) { return this.http.put(`wheels/${wheel.id}/listen`) } @@ -388,14 +381,10 @@ export class ApiService { return this.http.put(`guiding/dither?${query}`) } - setGuidingSettle(settle: SettleInfo) { + guidingSettle(settle: SettleInfo) { return this.http.put(`guiding/settle`, settle) } - getGuidingSettle() { - return this.http.get(`guiding/settle`) - } - guidingStop() { return this.http.put(`guiding/stop`) } diff --git a/desktop/src/shared/services/browser-window.service.ts b/desktop/src/shared/services/browser-window.service.ts index 1cf09cac6..0b2b1d638 100644 --- a/desktop/src/shared/services/browser-window.service.ts +++ b/desktop/src/shared/services/browser-window.service.ts @@ -1,14 +1,14 @@ import { Injectable } from '@angular/core' -import { FramingData } from '../../app/framing/framing.component' import { OpenWindow, WindowPreference } from '../types/app.types' import { SkyAtlasInput } from '../types/atlas.types' import { Camera, CameraDialogInput, CameraStartCapture } from '../types/camera.types' import { Device } from '../types/device.types' import { Focuser } from '../types/focuser.types' +import { LoadFraming } from '../types/framing.types' import { ImageSource, OpenImage } from '../types/image.types' import { Mount } from '../types/mount.types' import { Rotator } from '../types/rotator.types' -import { FilterWheel, WheelDialogInput } from '../types/wheel.types' +import { Wheel, WheelDialogInput } from '../types/wheel.types' import { Undefinable } from '../utils/types' import { ElectronService } from './electron.service' @@ -32,7 +32,7 @@ export class BrowserWindowService { } openCamera(data: Camera, preference: WindowPreference = {}) { - Object.assign(preference, { icon: 'camera', width: 400, height: 467 }) + Object.assign(preference, { icon: 'camera', width: 400, height: 477 }) return this.openWindow({ preference, data, id: `camera.${data.name}`, path: 'camera' }) } @@ -51,7 +51,7 @@ export class BrowserWindowService { return this.openWindow({ preference, data, id: `focuser.${data.name}`, path: 'focuser' }) } - openWheel(data: FilterWheel, preference: WindowPreference = {}) { + openWheel(data: Wheel, preference: WindowPreference = {}) { Object.assign(preference, { icon: 'filter-wheel', width: 280, height: 195 }) return this.openWindow({ preference, data, id: `wheel.${data.name}`, path: 'wheel' }) } @@ -72,7 +72,7 @@ export class BrowserWindowService { } openGuider(preference: WindowPreference = {}) { - Object.assign(preference, { icon: 'guider', width: 440, height: 455 }) + Object.assign(preference, { icon: 'guider', width: 380, height: 444 }) return this.openWindow({ preference, id: 'guider', path: 'guider' }) } @@ -103,7 +103,7 @@ export class BrowserWindowService { return this.openWindow({ preference, data, id: 'atlas', path: 'atlas' }) } - openFraming(data?: FramingData, preference: WindowPreference = {}) { + openFraming(data?: LoadFraming, preference: WindowPreference = {}) { Object.assign(preference, { icon: 'framing', width: 280, height: 303 }) return this.openWindow({ preference, data, id: 'framing', path: 'framing' }) } @@ -149,7 +149,7 @@ export class BrowserWindowService { } openAbout() { - const preference: WindowPreference = { icon: 'about', width: 430, height: 307, bringToFront: true } + const preference: WindowPreference = { icon: 'about', width: 430, height: 340, bringToFront: true } return this.openWindow({ preference, id: 'about', path: 'about' }) } } diff --git a/desktop/src/shared/services/electron.service.ts b/desktop/src/shared/services/electron.service.ts index 06d1637e7..1e275d470 100644 --- a/desktop/src/shared/services/electron.service.ts +++ b/desktop/src/shared/services/electron.service.ts @@ -22,7 +22,7 @@ import { ROISelected } from '../types/image.types' import { Mount } from '../types/mount.types' import { Rotator } from '../types/rotator.types' import { SequencerEvent } from '../types/sequencer.types' -import { FilterWheel, WheelRenamed } from '../types/wheel.types' +import { Wheel, WheelRenamed } from '../types/wheel.types' export const IMAGE_FILE_FILTER: Electron.FileFilter[] = [ { name: 'All', extensions: ['fits', 'fit', 'xisf'] }, @@ -49,9 +49,9 @@ interface EventMappedType { 'ROTATOR.UPDATED': DeviceMessageEvent 'ROTATOR.ATTACHED': DeviceMessageEvent 'ROTATOR.DETACHED': DeviceMessageEvent - 'WHEEL.UPDATED': DeviceMessageEvent - 'WHEEL.ATTACHED': DeviceMessageEvent - 'WHEEL.DETACHED': DeviceMessageEvent + 'WHEEL.UPDATED': DeviceMessageEvent + 'WHEEL.ATTACHED': DeviceMessageEvent + 'WHEEL.DETACHED': DeviceMessageEvent 'GUIDE_OUTPUT.UPDATED': DeviceMessageEvent 'GUIDE_OUTPUT.ATTACHED': DeviceMessageEvent 'GUIDE_OUTPUT.DETACHED': DeviceMessageEvent diff --git a/desktop/src/shared/services/pinger.service.ts b/desktop/src/shared/services/pinger.service.ts deleted file mode 100644 index dd4123a81..000000000 --- a/desktop/src/shared/services/pinger.service.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Injectable } from '@angular/core' - -export interface Pingable { - ping(): void -} - -@Injectable({ providedIn: 'root' }) -export class Pinger { - private readonly pingables = new Map() - - isRegistered(pingable: Pingable) { - return this.pingables.has(pingable) - } - - register(pingable: Pingable, interval: number, initialDelay: number = 1000) { - this.unregister(pingable) - - if (interval > 0) { - if (initialDelay > 0 && initialDelay < interval - 1000) { - setTimeout(() => { - pingable.ping() - }, initialDelay) - } - - const ping = setInterval(() => { - pingable.ping() - }, interval) as unknown as number - - this.pingables.set(pingable, ping) - } - } - - unregister(pingable: Pingable) { - clearInterval(this.pingables.get(pingable)) - this.pingables.delete(pingable) - } -} diff --git a/desktop/src/shared/services/preference.service.ts b/desktop/src/shared/services/preference.service.ts index c410e4917..832b42255 100644 --- a/desktop/src/shared/services/preference.service.ts +++ b/desktop/src/shared/services/preference.service.ts @@ -1,21 +1,21 @@ import { Injectable } from '@angular/core' -import { AlignmentPreference, EMPTY_ALIGNMENT_PREFERENCE } from '../types/alignment.types' -import { EMPTY_LOCATION, EMPTY_SKY_ATLAS_PREFERENCE, Location, SkyAtlasPreference } from '../types/atlas.types' -import { AutoFocusPreference, EMPTY_AUTO_FOCUS_PREFERENCE } from '../types/autofocus.type' +import { AlignmentPreference, alignmentPreferenceWithDefault, DEFAULT_ALIGNMENT_PREFERENCE } from '../types/alignment.types' +import { DEFAULT_SKY_ATLAS_PREFERENCE, SkyAtlasPreference } from '../types/atlas.types' +import { AutoFocusPreference, autoFocusPreferenceWithDefault, DEFAULT_AUTO_FOCUS_PREFERENCE } from '../types/autofocus.type' import { CalibrationPreference } from '../types/calibration.types' -import { Camera, CameraPreference, CameraStartCapture, EMPTY_CAMERA_PREFERENCE, EMPTY_LIVE_STACKING_REQUEST, LiveStackerType, LiveStackingRequest } from '../types/camera.types' -import { Device } from '../types/device.types' -import { Focuser, FocuserPreference } from '../types/focuser.types' -import { ConnectionDetails, Equipment, HomePreference } from '../types/home.types' -import { EMPTY_IMAGE_PREFERENCE, FOV, ImagePreference } from '../types/image.types' -import { EMPTY_MOUNT_PREFERENCE, Mount, MountPreference } from '../types/mount.types' -import { EMPTY_PLATE_SOLVER_REQUEST, PlateSolverRequest, PlateSolverType } from '../types/platesolver.types' -import { Rotator, RotatorPreference } from '../types/rotator.types' -import { EMPTY_SEQUENCER_PREFERENCE, SequencerPreference } from '../types/sequencer.types' -import { CameraCaptureNamingFormat, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT } from '../types/settings.types' -import { EMPTY_STACKER_PREFERENCE, EMPTY_STACKING_REQUEST, StackerPreference, StackerType, StackingRequest } from '../types/stacker.types' -import { EMPTY_STAR_DETECTION_REQUEST, StarDetectionRequest, StarDetectorType } from '../types/stardetector.types' -import { FilterWheel, WheelPreference } from '../types/wheel.types' +import { Camera, CameraPreference, cameraPreferenceWithDefault, DEFAULT_CAMERA_PREFERENCE } from '../types/camera.types' +import { DEFAULT_FLAT_WIZARD_PREFERENCE, FlatWizardPreference, flatWizardPreferenceWithDefault } from '../types/flat-wizard.types' +import { DEFAULT_FOCUSER_PREFERENCE, Focuser, FocuserPreference, focuserPreferenceWithDefault } from '../types/focuser.types' +import { DEFAULT_FRAMING_PREFERENCE, FramingPreference, framingPreferenceWithDefault } from '../types/framing.types' +import { DEFAULT_GUIDER_PREFERENCE, GuiderPreference, guiderPreferenceWithDefault } from '../types/guider.types' +import { DEFAULT_HOME_PREFERENCE, HomePreference, homePreferenceWithDefault } from '../types/home.types' +import { DEFAULT_IMAGE_PREFERENCE, FOV, ImagePreference } from '../types/image.types' +import { DEFAULT_MOUNT_PREFERENCE, Mount, MountPreference, mountPreferenceWithDefault } from '../types/mount.types' +import { DEFAULT_ROTATOR_PREFERENCE, Rotator, RotatorPreference, rotatorPreferenceWithDefault } from '../types/rotator.types' +import { DEFAULT_SEQUENCER_PREFERENCE, SequencerPreference } from '../types/sequencer.types' +import { DEFAULT_SETTINGS_PREFERENCE, SettingsPreference, settingsPreferenceWithDefault } from '../types/settings.types' +import { DEFAULT_STACKER_PREFERENCE, StackerPreference, stackerPreferenceWithDefault } from '../types/stacker.types' +import { DEFAULT_WHEEL_PREFERENCE, Wheel, WheelPreference, wheelPreferenceWithDefault } from '../types/wheel.types' import { Undefinable } from '../utils/types' import { LocalStorageService } from './local-storage.service' @@ -24,6 +24,7 @@ export class PreferenceData { private readonly storage: LocalStorageService, private readonly key: string, private readonly defaultValue: T | (() => T), + private readonly withDefault?: (value: T) => T, ) {} has() { @@ -31,7 +32,8 @@ export class PreferenceData { } get(defaultValue?: T | (() => T)): T { - return this.storage.get(this.key, defaultValue ?? this.defaultValue) + const value = this.storage.get(this.key, defaultValue ?? this.defaultValue) + return this.withDefault?.(value) ?? value } set(value: Undefinable) { @@ -47,77 +49,47 @@ export class PreferenceData { export class PreferenceService { constructor(private readonly storage: LocalStorageService) {} - wheelPreference(wheel: FilterWheel) { - return new PreferenceData(this.storage, `wheel.${wheel.name}`, {}) + wheel(wheel: Wheel) { + return new PreferenceData(this.storage, `wheel.${wheel.name}`, () => structuredClone(DEFAULT_WHEEL_PREFERENCE), wheelPreferenceWithDefault) } - cameraPreference(camera: Camera) { - return new PreferenceData(this.storage, `camera.${camera.name}`, () => structuredClone(EMPTY_CAMERA_PREFERENCE)) + camera(camera: Camera) { + return new PreferenceData(this.storage, `camera.${camera.name}`, () => structuredClone(DEFAULT_CAMERA_PREFERENCE), cameraPreferenceWithDefault) } - cameraStartCaptureForFlatWizard(camera: Camera) { - return new PreferenceData(this.storage, `camera.${camera.name}.flatWizard`, () => this.cameraPreference(camera).get()) + mount(mount: Mount) { + return new PreferenceData(this.storage, `mount.${mount.name}`, () => structuredClone(DEFAULT_MOUNT_PREFERENCE), mountPreferenceWithDefault) } - cameraStartCaptureForDARV(camera: Camera) { - return new PreferenceData(this.storage, `camera.${camera.name}.darv`, () => this.cameraPreference(camera).get()) - } - - cameraStartCaptureForTPPA(camera: Camera) { - return new PreferenceData(this.storage, `camera.${camera.name}.tppa`, () => this.cameraPreference(camera).get()) - } - - cameraStartCaptureForAutoFocus(camera: Camera) { - return new PreferenceData(this.storage, `camera.${camera.name}.autoFocus`, () => this.cameraPreference(camera).get()) - } - - mountPreference(mount: Mount) { - return new PreferenceData(this.storage, `mount.${mount.name}`, () => structuredClone(EMPTY_MOUNT_PREFERENCE)) - } - - plateSolverRequest(type: PlateSolverType) { - return new PreferenceData(this.storage, `plateSolver.${type}`, () => ({ ...EMPTY_PLATE_SOLVER_REQUEST, type }) as PlateSolverRequest) - } - - starDetectionRequest(type: StarDetectorType) { - return new PreferenceData(this.storage, `starDetection.${type}`, () => ({ ...EMPTY_STAR_DETECTION_REQUEST, type }) as StarDetectionRequest) - } - - liveStackingRequest(type: LiveStackerType) { - return new PreferenceData(this.storage, `liveStacking.${type}`, () => ({ ...EMPTY_LIVE_STACKING_REQUEST, type }) as LiveStackingRequest) - } - - stackingRequest(type: StackerType) { - return new PreferenceData(this.storage, `stacking.${type}`, () => ({ ...EMPTY_STACKING_REQUEST, type }) as StackingRequest) + focusOffsets(wheel: Wheel, focuser: Focuser) { + return new PreferenceData(this.storage, `focusOffsets.${wheel.name}.${focuser.name}`, () => new Array(wheel.count).fill(0)) } - equipmentForDevice(device: Device) { - return new PreferenceData(this.storage, `equipment.${device.name}`, () => ({}) as Equipment) + focuser(focuser: Focuser) { + return new PreferenceData(this.storage, `focuser.${focuser.name}`, () => structuredClone(DEFAULT_FOCUSER_PREFERENCE), focuserPreferenceWithDefault) } - focusOffsets(wheel: FilterWheel, focuser: Focuser) { - return new PreferenceData(this.storage, `focusOffsets.${wheel.name}.${focuser.name}`, () => new Array(wheel.count).fill(0)) + rotator(rotator: Rotator) { + return new PreferenceData(this.storage, `rotator.${rotator.name}`, () => structuredClone(DEFAULT_ROTATOR_PREFERENCE), rotatorPreferenceWithDefault) } - focuserPreference(focuser: Focuser) { - return new PreferenceData(this.storage, `focuser.${focuser.name}`, {}) + flatWizard(camera: Camera) { + return new PreferenceData(this.storage, `flatWizard.${camera.name}`, () => structuredClone(DEFAULT_FLAT_WIZARD_PREFERENCE), flatWizardPreferenceWithDefault) } - rotatorPreference(rotator: Rotator) { - return new PreferenceData(this.storage, `rotator.${rotator.name}`, {}) + autoFocus(camera: Camera) { + return new PreferenceData(this.storage, `autoFocus.${camera.name}`, () => structuredClone(DEFAULT_AUTO_FOCUS_PREFERENCE), autoFocusPreferenceWithDefault) } - readonly connections = new PreferenceData(this.storage, 'home.connections', () => []) - readonly locations = new PreferenceData(this.storage, 'locations', () => [structuredClone(EMPTY_LOCATION)]) - readonly selectedLocation = new PreferenceData(this.storage, 'locations.selected', () => structuredClone(EMPTY_LOCATION)) - readonly homePreference = new PreferenceData(this.storage, 'home', () => ({}) as HomePreference) - readonly imagePreference = new PreferenceData(this.storage, 'image', () => structuredClone(EMPTY_IMAGE_PREFERENCE)) - readonly skyAtlasPreference = new PreferenceData(this.storage, 'atlas', () => structuredClone(EMPTY_SKY_ATLAS_PREFERENCE)) - readonly alignmentPreference = new PreferenceData(this.storage, 'alignment', () => structuredClone(EMPTY_ALIGNMENT_PREFERENCE)) + readonly home = new PreferenceData(this.storage, 'home', () => structuredClone(DEFAULT_HOME_PREFERENCE), homePreferenceWithDefault) + readonly imagePreference = new PreferenceData(this.storage, 'image', () => structuredClone(DEFAULT_IMAGE_PREFERENCE)) + readonly skyAtlasPreference = new PreferenceData(this.storage, 'atlas', () => structuredClone(DEFAULT_SKY_ATLAS_PREFERENCE)) + readonly alignment = new PreferenceData(this.storage, 'alignment', () => structuredClone(DEFAULT_ALIGNMENT_PREFERENCE), alignmentPreferenceWithDefault) readonly imageFOVs = new PreferenceData(this.storage, 'image.fovs', () => []) readonly calibrationPreference = new PreferenceData(this.storage, 'calibration', () => ({}) as CalibrationPreference) - readonly autoFocusPreference = new PreferenceData(this.storage, 'autoFocus', () => structuredClone(EMPTY_AUTO_FOCUS_PREFERENCE)) - readonly sequencerPreference = new PreferenceData(this.storage, 'sequencer', () => structuredClone(EMPTY_SEQUENCER_PREFERENCE)) - readonly cameraCaptureNamingFormatPreference = new PreferenceData(this.storage, 'camera.namingFormat', () => structuredClone(DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT)) - readonly stackerPreference = new PreferenceData(this.storage, 'stacker', () => structuredClone(EMPTY_STACKER_PREFERENCE)) + readonly sequencerPreference = new PreferenceData(this.storage, 'sequencer', () => structuredClone(DEFAULT_SEQUENCER_PREFERENCE)) + readonly stacker = new PreferenceData(this.storage, 'stacker', () => structuredClone(DEFAULT_STACKER_PREFERENCE), stackerPreferenceWithDefault) + readonly guider = new PreferenceData(this.storage, 'guider', () => structuredClone(DEFAULT_GUIDER_PREFERENCE), guiderPreferenceWithDefault) + readonly framing = new PreferenceData(this.storage, 'framing', () => structuredClone(DEFAULT_FRAMING_PREFERENCE), framingPreferenceWithDefault) + readonly settings = new PreferenceData(this.storage, 'settings', () => structuredClone(DEFAULT_SETTINGS_PREFERENCE), settingsPreferenceWithDefault) } diff --git a/desktop/src/shared/services/ticker.service.ts b/desktop/src/shared/services/ticker.service.ts new file mode 100644 index 000000000..04ddd9afc --- /dev/null +++ b/desktop/src/shared/services/ticker.service.ts @@ -0,0 +1,37 @@ +import { Injectable } from '@angular/core' + +export interface Tickable { + tick(): void +} + +@Injectable({ providedIn: 'root' }) +export class Ticker { + private readonly tickables = new Map() + + isRegistered(tickable: Tickable) { + return this.tickables.has(tickable) + } + + register(tickable: Tickable, interval: number, initialDelay: number = 1000) { + this.unregister(tickable) + + if (interval > 0) { + if (initialDelay > 0 && initialDelay < interval - 1000) { + setTimeout(() => { + tickable.tick() + }, initialDelay) + } + + const ping = setInterval(() => { + tickable.tick() + }, interval) as unknown as number + + this.tickables.set(tickable, ping) + } + } + + unregister(tickable: Tickable) { + clearInterval(this.tickables.get(tickable)) + this.tickables.delete(tickable) + } +} diff --git a/desktop/src/shared/types/about.types.ts b/desktop/src/shared/types/about.types.ts new file mode 100644 index 000000000..23ef5a80f --- /dev/null +++ b/desktop/src/shared/types/about.types.ts @@ -0,0 +1,13 @@ +export interface IconItem { + name: string + author: string + link: string +} + +export interface DependencyItem { + name: string + version: string + link: string +} + +export const FLAT_ICON_URL = 'https://www.flaticon.com/free-icon' diff --git a/desktop/src/shared/types/alignment.types.ts b/desktop/src/shared/types/alignment.types.ts index 3752c29ab..9bb245529 100644 --- a/desktop/src/shared/types/alignment.types.ts +++ b/desktop/src/shared/types/alignment.types.ts @@ -1,7 +1,7 @@ import type { Angle } from './atlas.types' -import type { Camera, CameraCaptureEvent, CameraStartCapture } from './camera.types' +import { cameraStartCaptureWithDefault, DEFAULT_CAMERA_START_CAPTURE, type Camera, type CameraCaptureEvent, type CameraStartCapture } from './camera.types' import type { GuideDirection } from './guider.types' -import type { PlateSolverRequest, PlateSolverType } from './platesolver.types' +import { DEFAULT_PLATE_SOLVER_REQUEST, plateSolverRequestWithDefault, type PlateSolverRequest } from './platesolver.types' export type Hemisphere = 'NORTHERN' | 'SOUTHERN' @@ -12,33 +12,13 @@ export type TPPAState = 'IDLE' | 'SLEWING' | 'SLEWED' | 'SETTLING' | 'EXPOSURING export type AlignmentMethod = 'DARV' | 'TPPA' export interface AlignmentPreference { - darvInitialPause: number - darvExposureTime: number darvHemisphere: Hemisphere - tppaStartFromCurrentPosition: boolean - tppaStepDirection: GuideDirection - tppaCompensateRefraction: boolean - tppaStopTrackingWhenDone: boolean - tppaStepDuration: number - tppaPlateSolverType: PlateSolverType -} - -export const EMPTY_ALIGNMENT_PREFERENCE: AlignmentPreference = { - darvInitialPause: 5, - darvExposureTime: 30, - darvHemisphere: 'NORTHERN', - tppaStartFromCurrentPosition: true, - tppaStepDirection: 'EAST', - tppaCompensateRefraction: true, - tppaStopTrackingWhenDone: true, - tppaStepDuration: 5, - tppaPlateSolverType: 'ASTAP', + darvRequest: DARVStart + tppaRequest: TPPAStart } export interface DARVStart { capture: CameraStartCapture - exposureTime: number - initialPause: number direction: GuideDirection reversed: boolean } @@ -61,6 +41,17 @@ export interface TPPAStart { stepSpeed?: string } +export interface TPPAResult { + failed: boolean + rightAscension: Angle + declination: Angle + azimuthError: Angle + azimuthErrorDirection: string + altitudeError: Angle + altitudeErrorDirection: string + totalError: Angle +} + export interface TPPAEvent extends MessageEvent { camera: Camera state: TPPAState @@ -73,3 +64,80 @@ export interface TPPAEvent extends MessageEvent { altitudeErrorDirection: string capture?: CameraCaptureEvent } + +export interface DARVResult { + direction?: GuideDirection +} + +export const DEFAULT_CAMERA_START_CAPTURE_TPPA: CameraStartCapture = { + ...DEFAULT_CAMERA_START_CAPTURE, +} + +export const DEFAULT_TPPA_START: TPPAStart = { + capture: DEFAULT_CAMERA_START_CAPTURE_TPPA, + plateSolver: DEFAULT_PLATE_SOLVER_REQUEST, + startFromCurrentPosition: true, + stepDirection: 'EAST', + compensateRefraction: true, + stopTrackingWhenDone: true, + stepDuration: 5, +} + +export const DEFAULT_TPPA_RESULT: TPPAResult = { + failed: false, + rightAscension: `00h00m00s`, + declination: `00ยฐ00'00"`, + azimuthError: `00ยฐ00'00"`, + azimuthErrorDirection: '', + altitudeError: `00ยฐ00'00"`, + altitudeErrorDirection: '', + totalError: `00ยฐ00'00"`, +} + +export const DEFAULT_CAMERA_START_CAPTURE_DARV: CameraStartCapture = { + ...DEFAULT_CAMERA_START_CAPTURE, + exposureDelay: 5, + exposureTime: 30000000, +} + +export const DEFAULT_DARV_START: DARVStart = { + capture: DEFAULT_CAMERA_START_CAPTURE_DARV, + direction: 'NORTH', + reversed: false, +} + +export const DEFAULT_DARV_RESULT: DARVResult = {} + +export const DEFAULT_ALIGNMENT_PREFERENCE: AlignmentPreference = { + darvHemisphere: 'NORTHERN', + darvRequest: DEFAULT_DARV_START, + tppaRequest: DEFAULT_TPPA_START, +} + +export function darvStartWithDefault(request?: Partial, source: DARVStart = DEFAULT_DARV_START) { + if (!request) return structuredClone(source) + request.capture = cameraStartCaptureWithDefault(request.capture, source.capture) + request.direction ||= source.direction + request.reversed ??= source.reversed + return request as DARVStart +} + +export function tppaStartWithDefault(request?: Partial, source: TPPAStart = DEFAULT_TPPA_START) { + if (!request) return structuredClone(source) + request.capture = cameraStartCaptureWithDefault(request.capture, source.capture) + request.plateSolver = plateSolverRequestWithDefault(request.plateSolver, source.plateSolver) + request.startFromCurrentPosition ??= source.startFromCurrentPosition + request.stepDirection ||= source.stepDirection + request.compensateRefraction ??= source.compensateRefraction + request.stopTrackingWhenDone ??= source.stopTrackingWhenDone + request.stepDuration ??= source.stepDuration + return request as TPPAStart +} + +export function alignmentPreferenceWithDefault(preference?: Partial, source: AlignmentPreference = DEFAULT_ALIGNMENT_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.darvHemisphere ||= source.darvHemisphere + preference.darvRequest = darvStartWithDefault(preference.darvRequest, source.darvRequest) + preference.tppaRequest = tppaStartWithDefault(preference.tppaRequest, source.tppaRequest) + return preference as AlignmentPreference +} diff --git a/desktop/src/shared/types/app.types.ts b/desktop/src/shared/types/app.types.ts index 5c95403fe..f2bef9531 100644 --- a/desktop/src/shared/types/app.types.ts +++ b/desktop/src/shared/types/app.types.ts @@ -89,14 +89,3 @@ export interface JsonFile { } export interface SaveJson extends OpenFile, JsonFile {} - -export type StoredWindowDataKey = `window.${string}` - -export interface StoredWindowDataValue { - x: number - y: number - width: number - height: number -} - -export type StoredWindowData = Record diff --git a/desktop/src/shared/types/atlas.types.ts b/desktop/src/shared/types/atlas.types.ts index 8ef9bca6b..656afae5e 100644 --- a/desktop/src/shared/types/atlas.types.ts +++ b/desktop/src/shared/types/atlas.types.ts @@ -19,7 +19,7 @@ export interface SearchFilter { types: (SkyObjectType | 'ALL')[] } -export const EMPTY_SEARCH_FILTER: SearchFilter = { +export const DEFAULT_SEARCH_FILTER: SearchFilter = { text: '', rightAscension: '00h00m00s', declination: `+000ยฐ00'00"`, @@ -40,7 +40,7 @@ export interface SkyAtlasPreference { fast: boolean } -export const EMPTY_SKY_ATLAS_PREFERENCE: SkyAtlasPreference = { +export const DEFAULT_SKY_ATLAS_PREFERENCE: SkyAtlasPreference = { satellites: [], fast: false, } @@ -342,7 +342,7 @@ export interface BodyPosition extends EquatorialCoordinate, EquatorialCoordinate leading: boolean } -export const EMPTY_BODY_POSITION: BodyPosition = { +export const DEFAULT_BODY_POSITION: BodyPosition = { rightAscensionJ2000: '00h00m00s', declinationJ2000: `+000ยฐ00'00"`, rightAscension: '00h00m00s', @@ -438,7 +438,7 @@ export interface ComputedLocation extends EquatorialCoordinate, EquatorialCoordi pierSide: PierSide } -export const EMPTY_COMPUTED_LOCATION: ComputedLocation = { +export const DEFAULT_COMPUTED_LOCATION: ComputedLocation = { constellation: 'AND', meridianAt: '00:00', timeLeftToMeridianFlip: '00:00', @@ -525,7 +525,7 @@ export interface Location { offsetInMinutes: number } -export const EMPTY_LOCATION: Location = { +export const DEFAULT_LOCATION: Location = { id: 0, name: 'Null Island', latitude: 0, diff --git a/desktop/src/shared/types/autofocus.type.ts b/desktop/src/shared/types/autofocus.type.ts index 2e1357061..874f452e5 100644 --- a/desktop/src/shared/types/autofocus.type.ts +++ b/desktop/src/shared/types/autofocus.type.ts @@ -1,7 +1,7 @@ import type { Point } from 'electron' -import type { CameraCaptureEvent, CameraStartCapture } from './camera.types' +import { cameraStartCaptureWithDefault, DEFAULT_CAMERA_START_CAPTURE, type CameraCaptureEvent, type CameraStartCapture } from './camera.types' import type { StarDetectionRequest } from './stardetector.types' -import { EMPTY_STAR_DETECTION_REQUEST } from './stardetector.types' +import { DEFAULT_STAR_DETECTION_REQUEST, starDetectionRequestWithDefault } from './stardetector.types' export type AutoFocusState = 'IDLE' | 'MOVING' | 'EXPOSURING' | 'EXPOSURED' | 'ANALYSING' | 'ANALYSED' | 'CURVE_FITTED' | 'FAILED' | 'FINISHED' @@ -26,20 +26,8 @@ export interface AutoFocusRequest { starDetector: StarDetectionRequest } -export type AutoFocusPreference = Omit - -export const EMPTY_AUTO_FOCUS_PREFERENCE: AutoFocusPreference = { - fittingMode: 'HYPERBOLIC', - rSquaredThreshold: 0.5, - initialOffsetSteps: 4, - stepSize: 100, - totalNumberOfAttempts: 1, - backlashCompensation: { - mode: 'NONE', - backlashIn: 0, - backlashOut: 0, - }, - starDetector: EMPTY_STAR_DETECTION_REQUEST, +export interface AutoFocusPreference { + request: AutoFocusRequest } export interface Curve { @@ -91,3 +79,55 @@ export interface AutoFocusEvent { chart?: AutoFocusChart capture?: CameraCaptureEvent } + +export const DEFAULT_CAMERA_START_CAPTURE_AUTO_FOCUS: CameraStartCapture = { + ...DEFAULT_CAMERA_START_CAPTURE, +} + +export const DEFAULT_BACKLASH_COMPENSATION: BacklashCompensation = { + mode: 'NONE', + backlashIn: 0, + backlashOut: 0, +} + +export const DEFAULT_AUTO_FOCUS_REQUEST: AutoFocusRequest = { + capture: DEFAULT_CAMERA_START_CAPTURE_AUTO_FOCUS, + fittingMode: 'HYPERBOLIC', + rSquaredThreshold: 0.5, + initialOffsetSteps: 4, + stepSize: 100, + totalNumberOfAttempts: 1, + backlashCompensation: DEFAULT_BACKLASH_COMPENSATION, + starDetector: DEFAULT_STAR_DETECTION_REQUEST, +} + +export const DEFAULT_AUTO_FOCUS_PREFERENCE: AutoFocusPreference = { + request: DEFAULT_AUTO_FOCUS_REQUEST, +} + +export function backlashCompensationWithDefault(compensation?: Partial, source: BacklashCompensation = DEFAULT_BACKLASH_COMPENSATION) { + if (!compensation) return structuredClone(source) + compensation.mode ||= source.mode + compensation.backlashIn ??= source.backlashIn + compensation.backlashOut ??= source.backlashOut + return compensation as BacklashCompensation +} + +export function autoFocusRequestWithDefault(request?: Partial, source: AutoFocusRequest = DEFAULT_AUTO_FOCUS_REQUEST) { + if (!request) return structuredClone(source) + request.capture = cameraStartCaptureWithDefault(request.capture, source.capture) + request.fittingMode ??= source.fittingMode + request.rSquaredThreshold ??= source.rSquaredThreshold + request.initialOffsetSteps ??= source.initialOffsetSteps + request.stepSize ??= source.stepSize + request.totalNumberOfAttempts ??= source.totalNumberOfAttempts + request.backlashCompensation = backlashCompensationWithDefault(request.backlashCompensation, source.backlashCompensation) + request.starDetector = starDetectionRequestWithDefault(request.starDetector, source.starDetector) + return request as AutoFocusRequest +} + +export function autoFocusPreferenceWithDefault(preference?: Partial, source: AutoFocusPreference = DEFAULT_AUTO_FOCUS_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.request = autoFocusRequestWithDefault(preference.request, source.request) + return preference as AutoFocusPreference +} diff --git a/desktop/src/shared/types/camera.types.ts b/desktop/src/shared/types/camera.types.ts index 4948c7139..60136dc83 100644 --- a/desktop/src/shared/types/camera.types.ts +++ b/desktop/src/shared/types/camera.types.ts @@ -2,10 +2,13 @@ import type { MessageEvent } from './api.types' import type { Thermometer } from './auxiliary.types' import type { CompanionDevice, Device, PropertyState } from './device.types' import { isCompanionDevice } from './device.types' +import type { Focuser } from './focuser.types' import type { GuideOutput } from './guider.types' -import { type CameraCaptureNamingFormat } from './settings.types' +import type { Mount } from './mount.types' +import type { Rotator } from './rotator.types' +import type { Wheel } from './wheel.types' -export type CameraDialogMode = 'CAPTURE' | 'SEQUENCER' | 'FLAT_WIZARD' | 'TPPA' | 'DARV' | 'AUTO_FOCUS' +export type CameraMode = 'CAPTURE' | 'SEQUENCER' | 'FLAT_WIZARD' | 'TPPA' | 'DARV' | 'AUTO_FOCUS' export type FrameType = 'LIGHT' | 'DARK' | 'FLAT' | 'BIAS' @@ -17,73 +20,187 @@ export type ExposureMode = 'SINGLE' | 'FIXED' | 'LOOP' export type LiveStackerType = 'SIRIL' | 'PIXINSIGHT' +export type CameraCaptureState = 'IDLE' | 'CAPTURE_STARTED' | 'EXPOSURE_STARTED' | 'EXPOSURING' | 'WAITING' | 'SETTLING' | 'DITHERING' | 'STACKING' | 'PAUSING' | 'PAUSED' | 'EXPOSURE_FINISHED' | 'CAPTURE_FINISHED' + export enum ExposureTimeUnit { - MINUTE = 'm', - SECOND = 's', - MILLISECOND = 'ms', - MICROSECOND = 'ยตs', + MINUTE = 'MINUTE', + SECOND = 'SECOND', + MILLISECOND = 'MILLISECOND', + MICROSECOND = 'MICROSECOND', } -export function isCamera(device?: Device): device is Camera { - return !!device && 'exposuring' in device +export interface Camera extends GuideOutput, Thermometer { + readonly exposuring: boolean + readonly hasCoolerControl: boolean + readonly coolerPower: number + readonly cooler: boolean + readonly hasDewHeater: boolean + readonly dewHeater: boolean + readonly frameFormats: string[] + readonly canAbort: boolean + readonly cfaOffsetX: number + readonly cfaOffsetY: number + readonly cfaType: CfaPattern + readonly exposureMin: number + readonly exposureMax: number + readonly exposureState: PropertyState + readonly exposureTime: number + readonly hasCooler: boolean + readonly canSetTemperature: boolean + readonly canSubFrame: boolean + readonly x: number + readonly minX: number + readonly maxX: number + readonly y: number + readonly minY: number + readonly maxY: number + readonly width: number + readonly minWidth: number + readonly maxWidth: number + readonly height: number + readonly minHeight: number + readonly maxHeight: number + readonly canBin: boolean + readonly maxBinX: number + readonly maxBinY: number + readonly binX: number + readonly binY: number + readonly gain: number + readonly gainMin: number + readonly gainMax: number + readonly offset: number + readonly offsetMin: number + readonly offsetMax: number + readonly hasGuideHead: boolean + readonly pixelSizeX: number + readonly pixelSizeY: number + readonly capturesPath: string + readonly guideHead?: Device } -export function isGuideHead(device?: Device): device is GuideHead { - return isCamera(device) && isCompanionDevice(device) && !!device.main +export interface GuideHead extends Camera, CompanionDevice {} + +export interface Dither { + enabled: boolean + amount: number + raOnly: boolean + afterExposures: number } -export interface Camera extends GuideOutput, Thermometer { - exposuring: boolean - hasCoolerControl: boolean - coolerPower: number - cooler: boolean - hasDewHeater: boolean - dewHeater: boolean - frameFormats: string[] - canAbort: boolean - cfaOffsetX: number - cfaOffsetY: number - cfaType: CfaPattern - exposureMin: number - exposureMax: number - exposureState: PropertyState +export interface CameraCaptureNamingFormat { + light?: string + dark?: string + flat?: string + bias?: string +} + +export interface CameraStartCapture { + enabled: boolean exposureTime: number - hasCooler: boolean - canSetTemperature: boolean - canSubFrame: boolean + exposureAmount: number + exposureDelay: number x: number - minX: number - maxX: number y: number - minY: number - maxY: number width: number - minWidth: number - maxWidth: number height: number - minHeight: number - maxHeight: number - canBin: boolean - maxBinX: number - maxBinY: number + frameFormat?: string + frameType: FrameType binX: number binY: number gain: number - gainMin: number - gainMax: number offset: number - offsetMin: number - offsetMax: number - hasGuideHead: boolean - pixelSizeX: number - pixelSizeY: number - capturesPath: string - guideHead?: Device + autoSave: boolean + savePath?: string + autoSubFolderMode: AutoSubFolderMode + dither: Dither + filterPosition: number + shutterPosition: number + focusOffset: number + calibrationGroup?: string + liveStacking: LiveStackingRequest + namingFormat: CameraCaptureNamingFormat } -export interface GuideHead extends Camera, CompanionDevice {} +export interface CameraCaptureEvent extends MessageEvent { + camera: Camera + exposureAmount: number + exposureCount: number + captureElapsedTime: number + captureProgress: number + captureRemainingTime: number + stepElapsedTime: number + stepProgress: number + stepRemainingTime: number + savedPath?: string + liveStackedPath?: string + state: CameraCaptureState + capture?: CameraStartCapture +} + +export interface CameraDialogInput { + mode: CameraMode + camera: Camera + request: CameraStartCapture +} + +export interface CameraPreference { + request: CameraStartCapture + setpointTemperature: number + exposureTimeUnit: ExposureTimeUnit + exposureMode: ExposureMode + subFrame: boolean + mount?: Mount + focuser?: Focuser + wheel?: Wheel + rotator?: Rotator +} + +export interface CameraStepInfo { + remainingTime: number + progress: number + elapsedTime: number +} + +export interface CameraCaptureInfo { + looping: boolean + amount: number + remainingTime: number + elapsedTime: number + progress: number + count: number +} + +export interface LiveStackerSettings { + executablePath: string + slot: number +} + +export interface LiveStackingRequest extends LiveStackerSettings { + enabled: boolean + type: LiveStackerType + darkPath?: string + flatPath?: string + biasPath?: string + use32Bits: boolean +} + +export interface CameraDitherDialog { + showDialog: boolean + request: Dither +} + +export interface CameraLiveStackingDialog { + showDialog: boolean + request: LiveStackingRequest +} -export const EMPTY_CAMERA: Camera = { +export interface CameraNamingFormatDialog { + showDialog: boolean + format: CameraCaptureNamingFormat +} + +export const DEFAULT_CAMERA: Camera = { + type: 'CAMERA', sender: '', id: '', exposuring: false, @@ -139,41 +256,48 @@ export const EMPTY_CAMERA: Camera = { temperature: 0, } -export interface Dither { - enabled: boolean - amount: number - raOnly: boolean - afterExposures: number +export const DEFAULT_CAMERA_CAPTURE_INFO: CameraCaptureInfo = { + looping: false, + amount: 0, + remainingTime: 0, + elapsedTime: 0, + progress: 0, + count: 0, } -export interface CameraStartCapture { - enabled?: boolean - exposureTime: number - exposureAmount: number - exposureDelay: number - x: number - y: number - width: number - height: number - frameFormat?: string - frameType: FrameType - binX: number - binY: number - gain: number - offset: number - autoSave: boolean - savePath?: string - autoSubFolderMode: AutoSubFolderMode - dither: Dither - filterPosition?: number - shutterPosition?: number - focusOffset?: number - calibrationGroup?: string - liveStacking: LiveStackingRequest - namingFormat: CameraCaptureNamingFormat +export const DEFAULT_LIVE_STACKER_SETTINGS: LiveStackerSettings = { + executablePath: '', + slot: 0, +} + +export const DEFAULT_LIVE_STACKING_REQUEST: LiveStackingRequest = { + ...DEFAULT_LIVE_STACKER_SETTINGS, + enabled: false, + type: 'SIRIL', + use32Bits: false, +} + +export const CAMERA_CAPTURE_NAMING_FORMAT_LIGHT = '[camera]_[type]_[year:2][month][day][hour][min][sec][ms]_[filter]_[width]_[height]_[exp]_[bin]_[gain]' +export const CAMERA_CAPTURE_NAMING_FORMAT_DARK = '[camera]_[type]_[width]_[height]_[exp]_[bin]_[gain]' +export const CAMERA_CAPTURE_NAMING_FORMAT_FLAT = '[camera]_[type]_[filter]_[width]_[height]_[bin]' +export const CAMERA_CAPTURE_NAMING_FORMAT_BIAS = '[camera]_[type]_[width]_[height]_[bin]_[gain]' + +export const DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT: CameraCaptureNamingFormat = { + light: CAMERA_CAPTURE_NAMING_FORMAT_LIGHT, + dark: CAMERA_CAPTURE_NAMING_FORMAT_DARK, + flat: CAMERA_CAPTURE_NAMING_FORMAT_FLAT, + bias: CAMERA_CAPTURE_NAMING_FORMAT_BIAS, +} + +export const DEFAULT_DITHER: Dither = { + enabled: false, + amount: 1.5, + raOnly: false, + afterExposures: 5, } -export const EMPTY_CAMERA_START_CAPTURE: CameraStartCapture = { +export const DEFAULT_CAMERA_START_CAPTURE: CameraStartCapture = { + enabled: true, exposureTime: 1, exposureAmount: 1, exposureDelay: 0, @@ -188,22 +312,57 @@ export const EMPTY_CAMERA_START_CAPTURE: CameraStartCapture = { offset: 0, autoSave: false, autoSubFolderMode: 'OFF', - dither: { - enabled: false, - afterExposures: 1, - amount: 1.5, - raOnly: false, - }, - liveStacking: { - enabled: false, - type: 'SIRIL', - executablePath: '', - use32Bits: false, - slot: 1, - }, + filterPosition: 0, + shutterPosition: 0, + focusOffset: 0, + dither: DEFAULT_DITHER, + liveStacking: DEFAULT_LIVE_STACKING_REQUEST, namingFormat: {}, } +export const DEFAULT_CAMERA_PREFERENCE: CameraPreference = { + request: DEFAULT_CAMERA_START_CAPTURE, + setpointTemperature: 0, + exposureTimeUnit: ExposureTimeUnit.MICROSECOND, + exposureMode: 'SINGLE', + subFrame: false, +} + +export const DEFAULT_CAMERA_STEP_INFO: CameraStepInfo = { + remainingTime: 0, + progress: 0, + elapsedTime: 0, +} + +export function cameraStartCaptureWithDefault(request?: Partial, source: CameraStartCapture = DEFAULT_CAMERA_START_CAPTURE) { + if (!request) return structuredClone(source) + request.enabled ??= source.enabled + request.exposureTime ??= source.exposureTime + request.exposureAmount ??= source.exposureAmount + request.exposureDelay ??= source.exposureDelay + request.x ??= source.x + request.y ??= source.y + request.width ??= source.width + request.height ??= source.height + request.frameFormat ||= source.frameFormat + request.frameType ||= source.frameType + request.binX ??= source.binX + request.binY ??= source.binY + request.gain ??= source.gain + request.offset ??= source.offset + request.autoSave ??= source.autoSave + request.savePath ||= source.savePath + request.autoSubFolderMode ||= source.autoSubFolderMode + request.filterPosition ??= source.filterPosition + request.shutterPosition ??= source.shutterPosition + request.focusOffset ??= source.focusOffset + request.calibrationGroup ||= source.calibrationGroup + request.dither = ditherWithDefault(request.dither, source.dither) + request.liveStacking = liveStackingRequestWithDefault(request.liveStacking, source.liveStacking) + request.namingFormat = cameraCaptureNamingFormatWithDefault(request.namingFormat, source.namingFormat) + return request as CameraStartCapture +} + export function updateCameraStartCaptureFromCamera(request: CameraStartCapture, camera: Camera) { if (camera.maxX > 1) request.x = Math.max(camera.minX, Math.min(request.x, camera.maxX)) if (camera.maxY > 1) request.y = Math.max(camera.minY, Math.min(request.y, camera.maxY)) @@ -220,105 +379,54 @@ export function updateCameraStartCaptureFromCamera(request: CameraStartCapture, if (camera.frameFormats.length && (!request.frameFormat || !camera.frameFormats.includes(request.frameFormat))) request.frameFormat = camera.frameFormats[0] } -export interface CameraCaptureEvent extends MessageEvent { - camera: Camera - exposureAmount: number - exposureCount: number - captureElapsedTime: number - captureProgress: number - captureRemainingTime: number - stepElapsedTime: number - stepProgress: number - stepRemainingTime: number - savedPath?: string - liveStackedPath?: string - state: CameraCaptureState - capture?: CameraStartCapture +export function cameraPreferenceWithDefault(preference?: Partial, source: CameraPreference = DEFAULT_CAMERA_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.request = cameraStartCaptureWithDefault(preference.request, source.request) + preference.setpointTemperature ??= source.setpointTemperature + preference.exposureTimeUnit ??= source.exposureTimeUnit + preference.exposureMode ||= source.exposureMode + preference.subFrame ??= source.subFrame + return preference as CameraPreference } -export type CameraCaptureState = 'IDLE' | 'CAPTURE_STARTED' | 'EXPOSURE_STARTED' | 'EXPOSURING' | 'WAITING' | 'SETTLING' | 'DITHERING' | 'STACKING' | 'PAUSING' | 'PAUSED' | 'EXPOSURE_FINISHED' | 'CAPTURE_FINISHED' - -export interface CameraDialogInput { - mode: CameraDialogMode - camera: Camera - request: CameraStartCapture +export function liveStackerSettingsWithDefault(settings?: Partial, source: LiveStackerSettings = DEFAULT_LIVE_STACKER_SETTINGS) { + if (!settings) return structuredClone(source) + settings.executablePath ||= source.executablePath + settings.slot ??= source.slot + return settings as LiveStackerSettings } -export interface CameraPreference extends CameraStartCapture { - setpointTemperature: number - exposureTimeUnit: ExposureTimeUnit - exposureMode: ExposureMode - subFrame: boolean +export function liveStackingRequestWithDefault(request?: Partial, source: LiveStackingRequest = DEFAULT_LIVE_STACKING_REQUEST) { + if (!request) return structuredClone(source) + liveStackerSettingsWithDefault(request, source) + request.enabled ??= source.enabled + request.type ??= source.type + request.use32Bits ??= source.use32Bits + return request as LiveStackingRequest } -export const EMPTY_CAMERA_PREFERENCE: CameraPreference = { - ...EMPTY_CAMERA_START_CAPTURE, - setpointTemperature: 0, - exposureTimeUnit: ExposureTimeUnit.MICROSECOND, - exposureMode: 'SINGLE', - subFrame: false, -} - -export interface CameraStepInfo { - remainingTime: number - progress: number - elapsedTime: number -} - -export const EMPTY_CAMERA_STEP_INFO: CameraStepInfo = { - remainingTime: 0, - progress: 0, - elapsedTime: 0, -} - -export interface CameraCaptureInfo { - looping: boolean - amount: number - remainingTime: number - elapsedTime: number - progress: number - count: number +export function cameraCaptureNamingFormatWithDefault(format?: Partial, source: CameraCaptureNamingFormat = DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT) { + if (!format) return structuredClone(source) + format.light ||= source.light + format.dark ||= source.dark + format.flat ||= source.flat + format.bias ||= source.bias + return format as CameraCaptureNamingFormat } -export const EMPTY_CAMERA_CAPTURE_INFO: CameraCaptureInfo = { - looping: false, - amount: 0, - remainingTime: 0, - elapsedTime: 0, - progress: 0, - count: 0, +export function ditherWithDefault(dither?: Partial, source: Dither = DEFAULT_DITHER) { + if (!dither) return structuredClone(source) + dither.enabled ??= source.enabled + dither.amount ??= source.amount + dither.raOnly ??= source.raOnly + dither.afterExposures ??= source.afterExposures + return dither as Dither } -export interface LiveStackingRequest { - enabled: boolean - type: LiveStackerType - executablePath: string - darkPath?: string - flatPath?: string - biasPath?: string - use32Bits: boolean - slot: number -} - -export const EMPTY_LIVE_STACKING_REQUEST: LiveStackingRequest = { - enabled: false, - type: 'SIRIL', - executablePath: '', - use32Bits: false, - slot: 1, -} - -export interface CameraDitherDialog { - showDialog: boolean - request: Dither -} - -export interface CameraLiveStackingDialog { - showDialog: boolean - request: LiveStackingRequest +export function isCamera(device?: Device): device is Camera { + return !!device && device.type === 'CAMERA' } -export interface CameraNamingFormatDialog { - showDialog: boolean - format: CameraCaptureNamingFormat +export function isGuideHead(device?: Device): device is GuideHead { + return isCamera(device) && isCompanionDevice(device) && !!device.main } diff --git a/desktop/src/shared/types/device.types.ts b/desktop/src/shared/types/device.types.ts index 63729dac7..90e2f2c44 100644 --- a/desktop/src/shared/types/device.types.ts +++ b/desktop/src/shared/types/device.types.ts @@ -11,6 +11,7 @@ export type SwitchRule = 'ONE_OF_MANY' | 'AT_MOST_ONE' | 'ANY_OF_MANY' export type DeviceType = 'CAMERA' | 'MOUNT' | 'WHEEL' | 'FOCUSER' | 'ROTATOR' | 'GPS' | 'DOME' | 'SWITCH' export interface Device { + readonly type: DeviceType readonly sender: string readonly id: string readonly name: string diff --git a/desktop/src/shared/types/flat-wizard.types.ts b/desktop/src/shared/types/flat-wizard.types.ts index d2f9aa9e8..d7565dfe5 100644 --- a/desktop/src/shared/types/flat-wizard.types.ts +++ b/desktop/src/shared/types/flat-wizard.types.ts @@ -1,4 +1,10 @@ -import type { CameraCaptureEvent, CameraStartCapture } from './camera.types' +import { cameraStartCaptureWithDefault, DEFAULT_CAMERA_START_CAPTURE, type CameraCaptureEvent, type CameraStartCapture } from './camera.types' + +export type FlatWizardState = 'EXPOSURING' | 'CAPTURED' | 'FAILED' + +export interface FlatWizardPreference { + request: FlatWizardRequest +} export interface FlatWizardRequest { capture: CameraStartCapture @@ -8,11 +14,42 @@ export interface FlatWizardRequest { meanTolerance: number } -export type FlatWizardState = 'EXPOSURING' | 'CAPTURED' | 'FAILED' - export interface FlatWizardEvent { state: FlatWizardState exposureTime: number capture?: CameraCaptureEvent savedPath?: string } + +export const DEFAULT_CAMERA_START_CAPTURE_FLAT_WIZARD: CameraStartCapture = { + ...DEFAULT_CAMERA_START_CAPTURE, + frameType: 'FLAT', +} + +export const DEFAULT_FLAT_WIZARD_REQUEST: FlatWizardRequest = { + capture: DEFAULT_CAMERA_START_CAPTURE_FLAT_WIZARD, + exposureMin: 1, + exposureMax: 2000, + meanTarget: 32768, + meanTolerance: 10, +} + +export const DEFAULT_FLAT_WIZARD_PREFERENCE: FlatWizardPreference = { + request: DEFAULT_FLAT_WIZARD_REQUEST, +} + +export function flatWizardRequestWithDefault(request?: Partial, source: FlatWizardRequest = DEFAULT_FLAT_WIZARD_REQUEST) { + if (!request) return structuredClone(source) + request.capture = cameraStartCaptureWithDefault(request.capture, source.capture) + request.exposureMin ??= source.exposureMin + request.exposureMax ??= source.exposureMax + request.meanTarget ??= source.meanTarget + request.meanTolerance ??= source.meanTolerance + return request as FlatWizardRequest +} + +export function flatWizardPreferenceWithDefault(preference?: Partial, source: FlatWizardPreference = DEFAULT_FLAT_WIZARD_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.request = flatWizardRequestWithDefault(preference.request, source.request) + return preference as FlatWizardPreference +} diff --git a/desktop/src/shared/types/focuser.types.ts b/desktop/src/shared/types/focuser.types.ts index b2263cc71..b73e9f815 100644 --- a/desktop/src/shared/types/focuser.types.ts +++ b/desktop/src/shared/types/focuser.types.ts @@ -14,7 +14,13 @@ export interface Focuser extends Device, Thermometer { maxPosition: number } -export const EMPTY_FOCUSER: Focuser = { +export interface FocuserPreference { + stepsRelative: number + stepsAbsolute: number +} + +export const DEFAULT_FOCUSER: Focuser = { + type: 'FOCUSER', sender: '', id: '', moving: false, @@ -33,11 +39,18 @@ export const EMPTY_FOCUSER: Focuser = { temperature: 0, } -export interface FocuserPreference { - stepsRelative?: number - stepsAbsolute?: number +export const DEFAULT_FOCUSER_PREFERENCE: FocuserPreference = { + stepsRelative: 100, + stepsAbsolute: 0, } export function isFocuser(device?: Device): device is Focuser { - return !!device && 'maxPosition' in device + return !!device && device.type === 'FOCUSER' +} + +export function focuserPreferenceWithDefault(preference?: Partial, source: FocuserPreference = DEFAULT_FOCUSER_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.stepsAbsolute ??= source.stepsAbsolute + preference.stepsAbsolute ??= source.stepsAbsolute + return preference as FocuserPreference } diff --git a/desktop/src/shared/types/framing.types.ts b/desktop/src/shared/types/framing.types.ts index a4952b463..3791856f7 100644 --- a/desktop/src/shared/types/framing.types.ts +++ b/desktop/src/shared/types/framing.types.ts @@ -1,3 +1,5 @@ +import type { Angle } from './atlas.types' + export interface HipsSurvey { id: string category: string @@ -7,3 +9,43 @@ export interface HipsSurvey { pixelScale: number skyFraction: number } + +export interface FramingPreference { + rightAscension: Angle + declination: Angle + width: number + height: number + fov: number + rotation: number + hipsSurvey?: HipsSurvey +} + +export interface LoadFraming { + rightAscension: Angle + declination: Angle + width?: number + height?: number + fov?: number + rotation?: number +} + +export const DEFAULT_FRAMING_PREFERENCE: FramingPreference = { + rightAscension: '00h00m00s', + declination: `000ยฐ00'00"`, + width: 1024, + height: 720, + fov: 1, + rotation: 0, +} + +export function framingPreferenceWithDefault(preference?: Partial, source: FramingPreference = DEFAULT_FRAMING_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.rightAscension ??= source.rightAscension + preference.declination ??= source.declination + preference.width ??= source.width + preference.height ??= source.height + preference.fov ??= source.fov + preference.rotation ??= source.rotation + preference.hipsSurvey ??= source.hipsSurvey + return preference as FramingPreference +} diff --git a/desktop/src/shared/types/guider.types.ts b/desktop/src/shared/types/guider.types.ts index 4ba757fcf..8a55d2327 100644 --- a/desktop/src/shared/types/guider.types.ts +++ b/desktop/src/shared/types/guider.types.ts @@ -6,16 +6,16 @@ export type GuideDirection = | 'WEST' // RA+ | 'EAST' // RA- -export const GUIDE_STATES = ['STOPPED', 'SELECTED', 'CALIBRATING', 'GUIDING', 'LOST_LOCK', 'PAUSED', 'LOOPING'] as const -export type GuideState = (typeof GUIDE_STATES)[number] +export type GuideState = 'STOPPED' | 'SELECTED' | 'CALIBRATING' | 'GUIDING' | 'LOST_LOCK' | 'PAUSED' | 'LOOPING' -export const GUIDER_TYPES = ['PHD2'] as const -export type GuiderType = (typeof GUIDER_TYPES)[number] +export type GuiderType = 'PHD2' export type GuiderPlotMode = 'RA/DEC' | 'DX/DY' export type GuiderYAxisUnit = 'ARCSEC' | 'PIXEL' +export type GuidePulseDurations = Record, number> + export interface GuidePoint { x: number y: number @@ -61,7 +61,54 @@ export interface GuideOutput extends Device { pulseGuiding: boolean } -export const EMPTY_GUIDE_OUTPUT: GuideOutput = { +export interface Guider { + connected: boolean + state: GuideState + settling: boolean + pixelScale: number +} + +export interface SettleInfo { + amount: number + time: number + timeout: number +} + +export interface GuiderMessageEvent extends MessageEvent { + data: T +} + +export interface GuiderPreference { + host: string + port: number + plotMode: GuiderPlotMode + yAxisUnit: GuiderYAxisUnit + settle: SettleInfo + pulseDuration: GuidePulseDurations +} + +export interface GuiderPHD2 { + connected: boolean + state: GuideState + step?: GuideStep + message: string +} + +export interface GuiderPulse { + connected: boolean + pulsing: boolean +} + +export interface GuiderChartInfo { + pixelScale: number + rmsRA: number + rmsDEC: number + rmsTotal: number + durationScale: number +} + +export const DEFAULT_GUIDE_OUTPUT: GuideOutput = { + type: 'CAMERA', sender: '', id: '', canPulseGuide: false, @@ -70,11 +117,45 @@ export const EMPTY_GUIDE_OUTPUT: GuideOutput = { connected: false, } -export interface Guider { - connected: boolean - state: GuideState - settling: boolean - pixelScale: number +export const DEFAULT_SETTLE: SettleInfo = { + amount: 1.5, + time: 10, + timeout: 30, +} + +export const DEFAULT_GUIDE_PULSE_DURATIONS: GuidePulseDurations = { + north: 1000, + south: 1000, + east: 1000, + west: 1000, +} + +export const DEFAULT_GUIDER_PHD2: GuiderPHD2 = { + connected: false, + state: 'STOPPED', + message: '', +} + +export const DEFAULT_GUIDER_PULSE: GuiderPulse = { + connected: false, + pulsing: false, +} + +export const DEFAULT_GUIDER_PREFERENCE: GuiderPreference = { + host: 'localhost', + port: 4400, + plotMode: 'RA/DEC', + yAxisUnit: 'ARCSEC', + settle: DEFAULT_SETTLE, + pulseDuration: DEFAULT_GUIDE_PULSE_DURATIONS, +} + +export const DEFAULT_GUIDER_CHART_INFO: GuiderChartInfo = { + pixelScale: 1.0, + rmsRA: 0.0, + rmsDEC: 0.0, + rmsTotal: 0.0, + durationScale: 1.0, } export function reverseGuideDirection(direction: GuideDirection): GuideDirection { @@ -92,12 +173,30 @@ export function reverseGuideDirection(direction: GuideDirection): GuideDirection } } -export interface SettleInfo { - amount: number - time: number - timeout: number +export function settleWithDefault(settle?: Partial, source: SettleInfo = DEFAULT_SETTLE) { + if (!settle) return structuredClone(source) + settle.amount ??= source.amount + settle.time ??= source.time + settle.timeout ??= source.timeout + return settle as SettleInfo } -export interface GuiderMessageEvent extends MessageEvent { - data: T +export function pulseDurationWithDefault(duration?: Partial, source: GuidePulseDurations = DEFAULT_GUIDE_PULSE_DURATIONS) { + if (!duration) return structuredClone(source) + duration.north ??= source.north + duration.south ??= source.south + duration.east ??= source.east + duration.west ??= source.west + return duration as GuidePulseDurations +} + +export function guiderPreferenceWithDefault(preference?: Partial, source: GuiderPreference = DEFAULT_GUIDER_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.host ||= source.host + preference.port ??= source.port + preference.plotMode ||= source.plotMode + preference.yAxisUnit ||= source.yAxisUnit + preference.settle = settleWithDefault(preference.settle, source.settle) + preference.pulseDuration = pulseDurationWithDefault(preference.pulseDuration, source.pulseDuration) + return preference as GuiderPreference } diff --git a/desktop/src/shared/types/home.types.ts b/desktop/src/shared/types/home.types.ts index 14a1c01f3..98ce89892 100644 --- a/desktop/src/shared/types/home.types.ts +++ b/desktop/src/shared/types/home.types.ts @@ -1,15 +1,10 @@ -import type { Camera } from './camera.types' import type { DeviceType } from './device.types' -import type { Focuser } from './focuser.types' -import type { Mount } from './mount.types' -import type { Rotator } from './rotator.types' -import type { FilterWheel } from './wheel.types' export type HomeWindowType = DeviceType | 'GUIDER' | 'SKY_ATLAS' | 'ALIGNMENT' | 'SEQUENCER' | 'IMAGE' | 'FRAMING' | 'INDI' | 'SETTINGS' | 'CALCULATOR' | 'ABOUT' | 'FLAT_WIZARD' | 'AUTO_FOCUS' | 'STACKER' -export const CONNECTION_TYPES = ['INDI', 'ALPACA'] as const +export type ConnectionType = 'INDI' | 'ALPACA' -export type ConnectionType = (typeof CONNECTION_TYPES)[number] +export type ConnectionStatus = Omit, 'connected' | 'name' | 'connectedAt'> export interface ConnectionDetails { name: string @@ -22,29 +17,45 @@ export interface ConnectionDetails { id?: string } -export type ConnectionStatus = Omit, 'connected' | 'name' | 'connectedAt'> +export interface ConnectionClosed { + id: string +} + +export interface HomePreference { + connections: ConnectionDetails[] + imagePath?: string +} + +export interface HomeConnectionDialog { + showDialog: boolean + connection: ConnectionDetails + edited: boolean +} + +export const DEFAULT_CONNECTION_HOST: string = 'localhost' +export const DEFAULT_CONNECTION_PORT: number = 7624 -export const EMPTY_CONNECTION_DETAILS: ConnectionDetails = { - name: '', - host: 'localhost', - port: 7624, +export const DEFAULT_CONNECTION_DETAILS: ConnectionDetails = { + name: 'Local', + host: DEFAULT_CONNECTION_HOST, + port: DEFAULT_CONNECTION_PORT, type: 'INDI', connected: false, } -export interface ConnectionClosed { - id: string +export const DEFAULT_HOME_PREFERENCE: HomePreference = { + connections: [], } -export interface HomePreference { - imagePath?: string +export const DEFAULT_HOME_CONNECTION_DIALOG: HomeConnectionDialog = { + showDialog: false, + edited: false, + connection: DEFAULT_CONNECTION_DETAILS, } -export interface Equipment { - camera?: Camera - guider?: Camera - mount?: Mount - focuser?: Focuser - wheel?: FilterWheel - rotator?: Rotator +export function homePreferenceWithDefault(preference?: Partial, source: HomePreference = DEFAULT_HOME_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.connections ??= source.connections + preference.imagePath ??= source.imagePath + return preference as HomePreference } diff --git a/desktop/src/shared/types/image.types.ts b/desktop/src/shared/types/image.types.ts index bac08fd39..d18844f8e 100644 --- a/desktop/src/shared/types/image.types.ts +++ b/desktop/src/shared/types/image.types.ts @@ -55,7 +55,7 @@ export interface ImageSolved extends EquatorialCoordinateJ2000 { radius: number } -export const EMPTY_IMAGE_SOLVED: ImageSolved = { +export const DEFAULT_IMAGE_SOLVED: ImageSolved = { solved: false, orientation: 0, scale: 0, @@ -136,7 +136,7 @@ export interface ImagePreference { starDetection?: StarDetectionImagePreference } -export const EMPTY_IMAGE_PREFERENCE: ImagePreference = { +export const DEFAULT_IMAGE_PREFERENCE: ImagePreference = { solver: { type: 'ASTAP', radius: 4, diff --git a/desktop/src/shared/types/mount.types.ts b/desktop/src/shared/types/mount.types.ts index 3f9c409f6..f37ecc686 100644 --- a/desktop/src/shared/types/mount.types.ts +++ b/desktop/src/shared/types/mount.types.ts @@ -42,7 +42,38 @@ export interface Mount extends EquatorialCoordinate, GPS, GuideOutput, Parkable guideRateNS: number } -export const EMPTY_MOUNT: Mount = { +export interface MountRemoteControl { + type: MountRemoteControlType + mount: Mount + running: boolean + rightAscension: Angle + declination: Angle + latitude: Angle + longitude: Angle + slewing: boolean + tracking: boolean + parked: boolean + host: string + port: number +} + +export interface MountRemoteControlDialog { + showDialog: boolean + type: MountRemoteControlType + host: string + port: number + data: MountRemoteControl[] +} + +export interface MountPreference { + targetCoordinateType: TargetCoordinateType + targetRightAscension: Angle + targetDeclination: Angle + targetCoordinateCommand: number +} + +export const DEFAULT_MOUNT: Mount = { + type: 'MOUNT', sender: '', id: '', slewing: false, @@ -74,41 +105,22 @@ export const EMPTY_MOUNT: Mount = { parked: false, } -export interface MountRemoteControl { - type: MountRemoteControlType - mount: Mount - running: boolean - rightAscension: Angle - declination: Angle - latitude: Angle - longitude: Angle - slewing: boolean - tracking: boolean - parked: boolean - host: string - port: number -} - -export interface MountRemoteControlDialog { - showDialog: boolean - type: MountRemoteControlType - host: string - port: number - data: MountRemoteControl[] -} - -export interface MountPreference { - targetCoordinateType: TargetCoordinateType - targetRightAscension: Angle - targetDeclination: Angle -} - -export const EMPTY_MOUNT_PREFERENCE: MountPreference = { +export const DEFAULT_MOUNT_PREFERENCE: MountPreference = { targetCoordinateType: 'JNOW', - targetRightAscension: '', - targetDeclination: '', + targetRightAscension: '00h00m00s', + targetDeclination: `000ยฐ00'00"`, + targetCoordinateCommand: 0, } export function isMount(device?: Device): device is Mount { - return !!device && 'tracking' in device + return !!device && device.type === 'MOUNT' +} + +export function mountPreferenceWithDefault(preference?: Partial, source: MountPreference = DEFAULT_MOUNT_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.targetCoordinateType ||= source.targetCoordinateType + preference.targetRightAscension ??= source.targetRightAscension + preference.targetDeclination ??= source.targetDeclination + preference.targetCoordinateCommand ??= source.targetCoordinateCommand + return preference as MountPreference } diff --git a/desktop/src/shared/types/platesolver.types.ts b/desktop/src/shared/types/platesolver.types.ts index e803b1a39..c573e17c5 100644 --- a/desktop/src/shared/types/platesolver.types.ts +++ b/desktop/src/shared/types/platesolver.types.ts @@ -1,21 +1,23 @@ export type PlateSolverType = 'ASTROMETRY_NET' | 'ASTROMETRY_NET_ONLINE' | 'ASTAP' | 'SIRIL' | 'PIXINSIGHT' -export interface PlateSolverRequest { - type: PlateSolverType +export interface PlateSolverSettings { executablePath: string downsampleFactor: number apiUrl: string apiKey: string timeout: number slot: number +} + +export interface PlateSolverRequest extends PlateSolverSettings { + type: PlateSolverType pixelSize?: number focalLength?: number } export const NOVA_ASTROMETRY_NET_URL = 'https://nova.astrometry.net/' -export const EMPTY_PLATE_SOLVER_REQUEST: PlateSolverRequest = { - type: 'ASTAP', +export const DEFAULT_PLATE_SOLVER_SETTINGS: PlateSolverSettings = { executablePath: '', downsampleFactor: 0, apiUrl: NOVA_ASTROMETRY_NET_URL, @@ -23,3 +25,28 @@ export const EMPTY_PLATE_SOLVER_REQUEST: PlateSolverRequest = { timeout: 300, slot: 1, } + +export const DEFAULT_PLATE_SOLVER_REQUEST: PlateSolverRequest = { + ...DEFAULT_PLATE_SOLVER_SETTINGS, + type: 'ASTAP', +} + +export function plateSolverSettingsWithDefault(settings?: Partial, source: PlateSolverSettings = DEFAULT_PLATE_SOLVER_SETTINGS) { + if (!settings) return structuredClone(source) + settings.executablePath ||= source.executablePath + settings.downsampleFactor ??= source.downsampleFactor + settings.apiUrl ||= source.apiUrl + settings.apiKey ||= source.apiKey + settings.timeout ??= source.timeout + settings.slot ??= source.slot + return settings as PlateSolverSettings +} + +export function plateSolverRequestWithDefault(request?: Partial, source: PlateSolverRequest = DEFAULT_PLATE_SOLVER_REQUEST) { + if (!request) return structuredClone(source) + plateSolverSettingsWithDefault(request, source) + request.type ??= source.type + request.pixelSize ??= source.pixelSize + request.focalLength ??= source.focalLength + return request as PlateSolverRequest +} diff --git a/desktop/src/shared/types/rotator.types.ts b/desktop/src/shared/types/rotator.types.ts index 2a73995e9..0b003d434 100644 --- a/desktop/src/shared/types/rotator.types.ts +++ b/desktop/src/shared/types/rotator.types.ts @@ -13,7 +13,12 @@ export interface Rotator extends Device { maxAngle: number } -export const EMPTY_ROTATOR: Rotator = { +export interface RotatorPreference { + angle: number +} + +export const DEFAULT_ROTATOR: Rotator = { + type: 'ROTATOR', sender: '', id: '', name: '', @@ -30,10 +35,16 @@ export const EMPTY_ROTATOR: Rotator = { connected: false, } -export interface RotatorPreference { - angle?: number +export const DEFAULT_ROTATOR_PREFERENCE: RotatorPreference = { + angle: 0, } export function isRotator(device?: Device): device is Rotator { - return !!device && 'angle' in device + return !!device && device.type === 'ROTATOR' +} + +export function rotatorPreferenceWithDefault(preference?: Partial, source: RotatorPreference = DEFAULT_ROTATOR_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.angle ??= source.angle + return preference as RotatorPreference } diff --git a/desktop/src/shared/types/sequencer.types.ts b/desktop/src/shared/types/sequencer.types.ts index fe102cb26..48f85619f 100644 --- a/desktop/src/shared/types/sequencer.types.ts +++ b/desktop/src/shared/types/sequencer.types.ts @@ -1,5 +1,4 @@ -import type { AutoSubFolderMode, CameraCaptureEvent, CameraStartCapture, Dither } from './camera.types' -import type { CameraCaptureNamingFormat } from './settings.types' +import { DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, DEFAULT_DITHER, type AutoSubFolderMode, type CameraCaptureEvent, type CameraCaptureNamingFormat, type CameraStartCapture, type Dither } from './camera.types' export type SequenceCaptureMode = 'FULLY' | 'INTERLEAVED' @@ -39,33 +38,6 @@ export interface SequencePlan { rotator?: string } -export const EMPTY_SEQUENCE_PLAN: SequencePlan = { - initialDelay: 0, - captureMode: 'FULLY', - autoSubFolderMode: 'OFF', - entries: [], - dither: { - enabled: false, - amount: 1.5, - raOnly: false, - afterExposures: 1, - }, - autoFocus: { - enabled: false, - onStart: false, - onFilterChange: false, - afterElapsedTime: 1800, // 30 min - afterExposures: 10, - afterTemperatureChange: 5, - afterHFDIncrease: 10, - afterElapsedTimeEnabled: false, - afterExposuresEnabled: false, - afterTemperatureChangeEnabled: false, - afterHFDIncreaseEnabled: false, - }, - namingFormat: {}, -} - export interface SequencerEvent extends MessageEvent { id: number elapsedTime: number @@ -80,6 +52,30 @@ export interface SequencerPreference { plan: SequencePlan } -export const EMPTY_SEQUENCER_PREFERENCE: SequencerPreference = { - plan: structuredClone(EMPTY_SEQUENCE_PLAN), +export const DEFAULT_AUTO_FOCUS_AFTER_CONDITIONS: AutoFocusAfterConditions = { + enabled: false, + onStart: false, + onFilterChange: false, + afterElapsedTime: 1800, // 30 min + afterExposures: 10, + afterTemperatureChange: 5, + afterHFDIncrease: 10, + afterElapsedTimeEnabled: false, + afterExposuresEnabled: false, + afterTemperatureChangeEnabled: false, + afterHFDIncreaseEnabled: false, +} + +export const DEFAULT_SEQUENCE_PLAN: SequencePlan = { + initialDelay: 0, + captureMode: 'FULLY', + autoSubFolderMode: 'OFF', + entries: [], + dither: DEFAULT_DITHER, + autoFocus: DEFAULT_AUTO_FOCUS_AFTER_CONDITIONS, + namingFormat: DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, +} + +export const DEFAULT_SEQUENCER_PREFERENCE: SequencerPreference = { + plan: structuredClone(DEFAULT_SEQUENCE_PLAN), } diff --git a/desktop/src/shared/types/settings.types.ts b/desktop/src/shared/types/settings.types.ts index 402676bb3..c21133100 100644 --- a/desktop/src/shared/types/settings.types.ts +++ b/desktop/src/shared/types/settings.types.ts @@ -1,24 +1,78 @@ -import type { FrameType } from './camera.types' - -export interface CameraCaptureNamingFormat { - light?: string - dark?: string - flat?: string - bias?: string -} +import type { Location } from './atlas.types' +import { DEFAULT_LOCATION } from './atlas.types' +import type { LiveStackerSettings, LiveStackerType } from './camera.types' +import { cameraCaptureNamingFormatWithDefault, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, DEFAULT_LIVE_STACKER_SETTINGS, liveStackerSettingsWithDefault, type CameraCaptureNamingFormat, type FrameType } from './camera.types' +import { DEFAULT_PLATE_SOLVER_SETTINGS, plateSolverSettingsWithDefault, type PlateSolverSettings, type PlateSolverType } from './platesolver.types' +import { DEFAULT_STACKER_SETTINGS, stackerSettingsWithDefault, type StackerSettings, type StackerType } from './stacker.types' +import { DEFAULT_STAR_DETECTOR_SETTINGS, starDetectorSettingsWithDefault, type StarDetectorSettings, type StarDetectorType } from './stardetector.types' export type SettingsTabKey = 'LOCATION' | 'PLATE_SOLVER' | 'STAR_DETECTOR' | 'LIVE_STACKER' | 'STACKER' | 'CAPTURE_NAMING_FORMAT' -export interface SettingsTab { - id: SettingsTabKey - name: string +export interface SettingsPreference { + plateSolver: Record + starDetector: Record + liveStacker: Record + stacker: Record + namingFormat: CameraCaptureNamingFormat + locations: Location[] + location: number // selected location index +} + +export const DEFAULT_SETTINGS_PREFERENCE: SettingsPreference = { + plateSolver: { + ASTROMETRY_NET: structuredClone(DEFAULT_PLATE_SOLVER_SETTINGS), + ASTROMETRY_NET_ONLINE: structuredClone(DEFAULT_PLATE_SOLVER_SETTINGS), + ASTAP: structuredClone(DEFAULT_PLATE_SOLVER_SETTINGS), + SIRIL: structuredClone(DEFAULT_PLATE_SOLVER_SETTINGS), + PIXINSIGHT: structuredClone(DEFAULT_PLATE_SOLVER_SETTINGS), + }, + starDetector: { + ASTAP: structuredClone(DEFAULT_STAR_DETECTOR_SETTINGS), + SIRIL: structuredClone(DEFAULT_STAR_DETECTOR_SETTINGS), + PIXINSIGHT: structuredClone(DEFAULT_STAR_DETECTOR_SETTINGS), + }, + liveStacker: { + SIRIL: structuredClone(DEFAULT_LIVE_STACKER_SETTINGS), + PIXINSIGHT: structuredClone(DEFAULT_LIVE_STACKER_SETTINGS), + }, + stacker: { + PIXINSIGHT: structuredClone(DEFAULT_STACKER_SETTINGS), + }, + namingFormat: DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, + locations: [DEFAULT_LOCATION], + location: 0, } -export const DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT: CameraCaptureNamingFormat = { - light: '[camera]_[type]_[year:2][month][day][hour][min][sec][ms]_[filter]_[width]_[height]_[exp]_[bin]_[gain]', - dark: '[camera]_[type]_[width]_[height]_[exp]_[bin]_[gain]', - flat: '[camera]_[type]_[filter]_[width]_[height]_[bin]', - bias: '[camera]_[type]_[width]_[height]_[bin]_[gain]', +export function settingsPreferenceWithDefault(preference?: Partial, source: SettingsPreference = DEFAULT_SETTINGS_PREFERENCE) { + if (!preference) return structuredClone(source) + + preference.plateSolver ??= structuredClone(source.plateSolver) + preference.starDetector ??= structuredClone(source.starDetector) + preference.liveStacker ??= structuredClone(source.liveStacker) + preference.stacker ??= structuredClone(source.stacker) + + for (const [key, value] of Object.entries(preference.plateSolver)) { + plateSolverSettingsWithDefault(value, source.plateSolver[key as never]) + } + for (const [key, value] of Object.entries(preference.starDetector)) { + starDetectorSettingsWithDefault(value, source.starDetector[key as never]) + } + for (const [key, value] of Object.entries(preference.liveStacker)) { + liveStackerSettingsWithDefault(value, source.liveStacker[key as never]) + } + for (const [key, value] of Object.entries(preference.stacker)) { + stackerSettingsWithDefault(value, source.stacker[key as never]) + } + + preference.namingFormat = cameraCaptureNamingFormatWithDefault(preference.namingFormat, source.namingFormat) + preference.location ??= source.location + + if (!preference.locations?.length) { + preference.locations = structuredClone(source.locations) + preference.location = 0 + } + + return preference as SettingsPreference } export function resetCameraCaptureNamingFormat(type: FrameType, format: CameraCaptureNamingFormat, defaultValue?: CameraCaptureNamingFormat) { diff --git a/desktop/src/shared/types/stacker.types.ts b/desktop/src/shared/types/stacker.types.ts index f2971eeff..c7250dd8c 100644 --- a/desktop/src/shared/types/stacker.types.ts +++ b/desktop/src/shared/types/stacker.types.ts @@ -4,10 +4,14 @@ export type StackerType = 'PIXINSIGHT' export type StackerGroupType = 'LUMINANCE' | 'RED' | 'GREEN' | 'BLUE' | 'MONO' | 'RGB' -export interface StackingRequest { +export interface StackerSettings { + executablePath: string + slot: number +} + +export interface StackingRequest extends StackerSettings { outputDirectory: string type: StackerType - executablePath: string darkPath?: string darkEnabled: boolean flatPath?: string @@ -15,24 +19,10 @@ export interface StackingRequest { biasPath?: string biasEnabled: boolean use32Bits: boolean - slot: number referencePath: string targets: StackingTarget[] } -export const EMPTY_STACKING_REQUEST: StackingRequest = { - outputDirectory: '', - type: 'PIXINSIGHT', - executablePath: '', - use32Bits: false, - slot: 1, - referencePath: '', - targets: [], - darkEnabled: false, - flatEnabled: false, - biasEnabled: false, -} - export interface StackingTarget { enabled: boolean path: string @@ -54,19 +44,58 @@ export interface AnalyzedTarget { } export interface StackerPreference { - type?: StackerType - outputDirectory?: string + request: StackingRequest defaultPath?: string - darkPath?: string - darkEnabled?: boolean - flatPath?: string - flatEnabled?: boolean - biasPath?: string - biasEnabled?: boolean } -export const EMPTY_STACKER_PREFERENCE: StackerPreference = { +export const DEFAULT_STACKER_SETTINGS: StackerSettings = { + executablePath: '', + slot: 0, +} + +export const DEFAULT_STACKING_REQUEST: StackingRequest = { + ...DEFAULT_STACKER_SETTINGS, + outputDirectory: '', + type: 'PIXINSIGHT', + use32Bits: false, + referencePath: '', + targets: [], darkEnabled: false, flatEnabled: false, biasEnabled: false, } + +export const DEFAULT_STACKER_PREFERENCE: StackerPreference = { + request: DEFAULT_STACKING_REQUEST, +} + +export function stackerSettingsWithDefault(preference?: Partial, source: StackerSettings = DEFAULT_STACKER_SETTINGS) { + if (!preference) return structuredClone(source) + preference.executablePath ||= source.executablePath + preference.slot ??= source.slot + return preference as StackerSettings +} + +export function stackingRequestWithDefault(request?: Partial, source: StackingRequest = DEFAULT_STACKING_REQUEST) { + if (!request) return structuredClone(source) + stackerSettingsWithDefault(request, source) + request.outputDirectory ||= source.outputDirectory + request.type ||= source.type + request.darkPath ||= source.darkPath + request.darkEnabled ??= source.darkEnabled + request.flatPath ||= source.flatPath + request.flatEnabled ??= source.flatEnabled + request.biasPath ||= source.biasPath + request.biasEnabled ??= source.biasEnabled + request.use32Bits ??= source.use32Bits + request.referencePath ||= source.referencePath + request.targets ??= source.targets + return request as StackingRequest +} + +export function stackerPreferenceWithDefault(preference?: Partial, source: StackerPreference = DEFAULT_STACKER_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.request = stackingRequestWithDefault(preference.request, source.request) + preference.defaultPath ??= source.defaultPath + return preference as StackerPreference +} diff --git a/desktop/src/shared/types/stardetector.types.ts b/desktop/src/shared/types/stardetector.types.ts index d0d344c41..5093e3ccf 100644 --- a/desktop/src/shared/types/stardetector.types.ts +++ b/desktop/src/shared/types/stardetector.types.ts @@ -1,19 +1,43 @@ export type StarDetectorType = 'ASTAP' | 'PIXINSIGHT' | 'SIRIL' -export interface StarDetectionRequest { - type: StarDetectorType +export interface StarDetectorSettings { executablePath: string timeout: number + slot: number +} + +export interface StarDetectionRequest extends StarDetectorSettings { + type: StarDetectorType minSNR?: number maxStars?: number - slot: number } -export const EMPTY_STAR_DETECTION_REQUEST: StarDetectionRequest = { - type: 'ASTAP', +export const DEFAULT_STAR_DETECTOR_SETTINGS: StarDetectorSettings = { executablePath: '', timeout: 300, + slot: 0, +} + +export const DEFAULT_STAR_DETECTION_REQUEST: StarDetectionRequest = { + ...DEFAULT_STAR_DETECTOR_SETTINGS, + type: 'ASTAP', minSNR: 0, maxStars: 0, - slot: 1, +} + +export function starDetectorSettingsWithDefault(settings?: Partial, source: StarDetectorSettings = DEFAULT_STAR_DETECTOR_SETTINGS) { + if (!settings) return structuredClone(source) + settings.executablePath ||= source.executablePath + settings.timeout ??= source.timeout + settings.slot ??= source.slot + return settings as StarDetectorSettings +} + +export function starDetectionRequestWithDefault(request?: Partial, source: StarDetectionRequest = DEFAULT_STAR_DETECTION_REQUEST) { + if (!request) return structuredClone(source) + starDetectorSettingsWithDefault(request, source) + request.type ||= source.type + request.minSNR ??= source.minSNR + request.maxStars ??= source.maxStars + return request as StarDetectionRequest } diff --git a/desktop/src/shared/types/wheel.types.ts b/desktop/src/shared/types/wheel.types.ts index bb2c7168f..5287170a7 100644 --- a/desktop/src/shared/types/wheel.types.ts +++ b/desktop/src/shared/types/wheel.types.ts @@ -1,52 +1,41 @@ import type { CameraStartCapture } from './camera.types' import type { Device } from './device.types' -export type WheelDialogMode = 'CAPTURE' | 'SEQUENCER' | 'FLAT_WIZARD' +export type WheelMode = 'CAPTURE' | 'SEQUENCER' | 'FLAT_WIZARD' -export interface FilterWheel extends Device { +export interface Wheel extends Device { count: number position: number moving: boolean names: string[] } -export const EMPTY_WHEEL: FilterWheel = { - sender: '', - id: '', - count: 0, - position: 0, - moving: false, - name: '', - connected: false, - names: [], -} - export interface WheelDialogInput { - mode: WheelDialogMode - wheel: FilterWheel + mode: WheelMode + wheel: Wheel request: CameraStartCapture } export interface WheelPreference { - shutterPosition?: number + shutterPosition: number } -export interface FilterSlot { +export interface Filter { position: number name: string dark: boolean } export interface WheelRenamed { - wheel: FilterWheel - filter: FilterSlot + wheel: Wheel + filter: Filter } -export function makeFilterSlots(wheel: FilterWheel, filters: FilterSlot[], shutterPosition: number = 0) { +export function makeFilter(wheel: Wheel, filters: Filter[], shutterPosition: number = 0) { if (wheel.count <= 0) { filters = [] } else if (wheel.count !== filters.length) { - filters = new Array(wheel.count) + filters = new Array(wheel.count) } if (filters.length) { @@ -66,6 +55,28 @@ export function makeFilterSlots(wheel: FilterWheel, filters: FilterSlot[], shutt return filters } -export function isFilterWheel(device?: Device): device is FilterWheel { - return !!device && 'count' in device +export const DEFAULT_WHEEL: Wheel = { + type: 'WHEEL', + sender: '', + id: '', + count: 0, + position: 0, + moving: false, + name: '', + connected: false, + names: [], +} + +export const DEFAULT_WHEEL_PREFERENCE: WheelPreference = { + shutterPosition: 0, +} + +export function isFilterWheel(device?: Device): device is Wheel { + return !!device && device.type === 'WHEEL' +} + +export function wheelPreferenceWithDefault(preference?: Partial, source: WheelPreference = DEFAULT_WHEEL_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.shutterPosition ??= source.shutterPosition + return preference as WheelPreference } diff --git a/desktop/src/styles.scss b/desktop/src/styles.scss index 4449da541..d8421db68 100644 --- a/desktop/src/styles.scss +++ b/desktop/src/styles.scss @@ -249,8 +249,8 @@ i.mdi { .p-menuitem-link { &.p-menuitem-selected { - background-color: $successButtonBg; - color: #212121 !important; + background-color: rgb(0 255 0 / 10%); + border-radius: 4px; } } @@ -318,6 +318,10 @@ p-tieredmenu *, } } +.p-listbox-header { + border-bottom: 0px; +} + .pixelated { image-rendering: pixelated; } diff --git a/desktop/tsconfig.json b/desktop/tsconfig.json index 69c0debbb..10bca42d5 100644 --- a/desktop/tsconfig.json +++ b/desktop/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "strict": true, "outDir": "./dist/out-tsc", - "module": "ES2022", + "module": "ESNext", "sourceMap": true, "declaration": false, "moduleResolution": "node", @@ -12,7 +12,7 @@ "resolveJsonModule": true, "allowSyntheticDefaultImports": true, "noUncheckedIndexedAccess": false, - "noUnusedLocals": true, + "noUnusedLocals": false, "noUnusedParameters": false, "noImplicitReturns": true, "noImplicitThis": true, diff --git a/desktop/tsconfig.serve.json b/desktop/tsconfig.serve.json index 1c64234ca..44fe8ddb5 100644 --- a/desktop/tsconfig.serve.json +++ b/desktop/tsconfig.serve.json @@ -9,11 +9,12 @@ "module": "CommonJS", "target": "ES2022", "noFallthroughCasesInSwitch": true, + "esModuleInterop": true, "incremental": true, "types": ["node"], "lib": ["es2022", "es2018", "es2017", "es2016", "es2015", "dom"] }, - "files": ["app/main.ts", "app/preload.ts", "app/argument.parser.ts", "app/local.storage.ts", "app/window.manager.ts"], + "files": ["app/main.ts", "app/preload.ts", "app/argument.parser.ts", "app/window.manager.ts"], "include": ["src/shared/types/*.ts", "src/typings.d.ts"], "exclude": ["node_modules", "**/*.spec.ts"] } diff --git a/nebulosa-hips2fits/src/main/kotlin/nebulosa/hips2fits/Hips2FitsService.kt b/nebulosa-hips2fits/src/main/kotlin/nebulosa/hips2fits/Hips2FitsService.kt index 888c00588..87deb6d54 100644 --- a/nebulosa-hips2fits/src/main/kotlin/nebulosa/hips2fits/Hips2FitsService.kt +++ b/nebulosa-hips2fits/src/main/kotlin/nebulosa/hips2fits/Hips2FitsService.kt @@ -35,6 +35,7 @@ class Hips2FitsService( coordSystem.name.lowercase(), rotation.toDegrees, format.name.lowercase(), ) + // https://alasky.cds.unistra.fr/MocServer/query?get=record&fmt=json&expr=ID%3DCDS*%20%26%26%20hips_service_url*%3D*alasky*%20%26%26%20dataproduct_type%3Dimage%20%26%26%20moc_sky_fraction%20%3E%3D%200.99%20%26%26%20obs_regime%3DOptical%2CInfrared%2CUV%2CRadio%2CX-ray%2CGamma-ray fun availableSurveys() = service .availableSurveys("ID=CDS* && hips_service_url*=*alasky* && dataproduct_type=image && moc_sky_fraction >= 0.99 && obs_regime=Optical,Infrared,UV,Radio,X-ray,Gamma-ray") diff --git a/nebulosa-indi-client/src/main/kotlin/nebulosa/indi/client/device/GPSDevice.kt b/nebulosa-indi-client/src/main/kotlin/nebulosa/indi/client/device/GPSDevice.kt index e13d4d49f..c06331961 100644 --- a/nebulosa-indi-client/src/main/kotlin/nebulosa/indi/client/device/GPSDevice.kt +++ b/nebulosa-indi-client/src/main/kotlin/nebulosa/indi/client/device/GPSDevice.kt @@ -1,6 +1,7 @@ package nebulosa.indi.client.device import nebulosa.indi.client.INDIClient +import nebulosa.indi.device.DeviceType import nebulosa.indi.device.gps.GPS import nebulosa.indi.device.gps.GPSCoordinateChanged import nebulosa.indi.device.gps.GPSTimeChanged @@ -17,6 +18,9 @@ internal open class GPSDevice( override val name: String, ) : INDIDevice(), GPS { + override val type + get() = DeviceType.GPS + @Volatile final override var hasGPS = true @Volatile final override var longitude = 0.0 @Volatile final override var latitude = 0.0 diff --git a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/Device.kt b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/Device.kt index 60757ac91..edce9e775 100644 --- a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/Device.kt +++ b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/Device.kt @@ -6,6 +6,8 @@ import java.io.Closeable interface Device : INDIProtocolHandler, Closeable, Comparable { + val type: DeviceType + val sender: MessageSender val id: String diff --git a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/DeviceType.kt b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/DeviceType.kt new file mode 100644 index 000000000..c3fa6f460 --- /dev/null +++ b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/DeviceType.kt @@ -0,0 +1,12 @@ +package nebulosa.indi.device + +enum class DeviceType { + CAMERA, + MOUNT, + WHEEL, + FOCUSER, + ROTATOR, + GPS, + DOME, + SWITCH +} diff --git a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/camera/Camera.kt b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/camera/Camera.kt index 49e72e3b4..3430142b9 100644 --- a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/camera/Camera.kt +++ b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/camera/Camera.kt @@ -2,6 +2,7 @@ package nebulosa.indi.device.camera import nebulosa.image.algorithms.transformation.CfaPattern import nebulosa.image.format.HeaderCard +import nebulosa.indi.device.DeviceType import nebulosa.indi.device.guide.GuideOutput import nebulosa.indi.device.thermometer.Thermometer import nebulosa.indi.protocol.PropertyState @@ -9,6 +10,9 @@ import java.time.Duration interface Camera : GuideOutput, Thermometer { + override val type + get() = DeviceType.CAMERA + val exposuring: Boolean val hasCoolerControl: Boolean diff --git a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/dome/Dome.kt b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/dome/Dome.kt index 9331f44f2..e2641eb6e 100644 --- a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/dome/Dome.kt +++ b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/dome/Dome.kt @@ -1,5 +1,10 @@ package nebulosa.indi.device.dome import nebulosa.indi.device.Device +import nebulosa.indi.device.DeviceType -interface Dome : Device +interface Dome : Device { + + override val type + get() = DeviceType.DOME +} diff --git a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/filterwheel/FilterWheel.kt b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/filterwheel/FilterWheel.kt index 90c27c12f..92f9af5ef 100644 --- a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/filterwheel/FilterWheel.kt +++ b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/filterwheel/FilterWheel.kt @@ -1,9 +1,13 @@ package nebulosa.indi.device.filterwheel import nebulosa.indi.device.Device +import nebulosa.indi.device.DeviceType interface FilterWheel : Device { + override val type + get() = DeviceType.WHEEL + val count: Int val position: Int diff --git a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/focuser/Focuser.kt b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/focuser/Focuser.kt index 920702192..547a5e513 100644 --- a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/focuser/Focuser.kt +++ b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/focuser/Focuser.kt @@ -1,10 +1,14 @@ package nebulosa.indi.device.focuser import nebulosa.indi.device.Device +import nebulosa.indi.device.DeviceType import nebulosa.indi.device.thermometer.Thermometer interface Focuser : Device, Thermometer { + override val type + get() = DeviceType.FOCUSER + val moving: Boolean val position: Int diff --git a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/mount/Mount.kt b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/mount/Mount.kt index 847336c4e..b10d4b0d5 100644 --- a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/mount/Mount.kt +++ b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/mount/Mount.kt @@ -1,5 +1,6 @@ package nebulosa.indi.device.mount +import nebulosa.indi.device.DeviceType import nebulosa.indi.device.Parkable import nebulosa.indi.device.gps.GPS import nebulosa.indi.device.guide.GuideOutput @@ -9,6 +10,9 @@ import java.time.OffsetDateTime interface Mount : GuideOutput, GPS, Parkable { + override val type + get() = DeviceType.MOUNT + val slewing: Boolean val tracking: Boolean diff --git a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/rotator/Rotator.kt b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/rotator/Rotator.kt index d22861982..a154381d9 100644 --- a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/rotator/Rotator.kt +++ b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/rotator/Rotator.kt @@ -1,9 +1,13 @@ package nebulosa.indi.device.rotator import nebulosa.indi.device.Device +import nebulosa.indi.device.DeviceType interface Rotator : Device { + override val type + get() = DeviceType.ROTATOR + val moving: Boolean val canAbort: Boolean diff --git a/nebulosa-platesolver/src/main/kotlin/nebulosa/platesolver/PlateSolution.kt b/nebulosa-platesolver/src/main/kotlin/nebulosa/platesolver/PlateSolution.kt index 04a6d68df..97404a9ae 100644 --- a/nebulosa-platesolver/src/main/kotlin/nebulosa/platesolver/PlateSolution.kt +++ b/nebulosa-platesolver/src/main/kotlin/nebulosa/platesolver/PlateSolution.kt @@ -4,6 +4,7 @@ import nebulosa.fits.FitsHeader import nebulosa.fits.FitsKeyword import nebulosa.image.format.HeaderCard import nebulosa.image.format.ReadableHeader +import nebulosa.log.debug import nebulosa.log.loggerFor import nebulosa.math.* import nebulosa.wcs.computeCdMatrix @@ -44,11 +45,11 @@ data class PlateSolution( val width = header.getIntOrNull(FitsKeyword.NAXIS1) ?: header.getInt("IMAGEW", 0) val height = header.getIntOrNull(FitsKeyword.NAXIS2) ?: header.getInt("IMAGEH", 0) - LOG.info( - "solution from {}: ORIE={}, SCALE={}, RA={}, DEC={}", - header, crota2.formatSignedDMS(), cdelt2.toArcsec, - crval1.formatHMS(), crval2.formatSignedDMS(), - ) + LOG.debug { + "solution from %s: ORIE=%f, SCALE=%f, RA=%s, DEC=%s".format( + header, crota2.formatSignedDMS(), cdelt2.toArcsec, crval1.formatHMS(), crval2.formatSignedDMS(), + ) + } return PlateSolution( true, crota2, cdelt2, crval1, crval2, abs(cdelt1 * width), abs(cdelt2 * height), From 44a7086c0e199ebba8ea822b411e1236af6df867 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 22:15:18 +0000 Subject: [PATCH 085/104] [desktop]: Bump eslint from 8.57.0 to 9.8.0 in /desktop Bumps [eslint](https://github.com/eslint/eslint) from 8.57.0 to 9.8.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v8.57.0...v9.8.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 302 ++++++++++++++++---------------------- desktop/package.json | 2 +- 2 files changed, 126 insertions(+), 178 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 9f896053f..0f393534f 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -48,7 +48,7 @@ "@types/node": "20.14.11", "electron": "31.3.1", "electron-builder": "24.13.3", - "eslint": "8.57.0", + "eslint": "9.8.0", "node-polyfill-webpack-plugin": "4.0.0", "npm-run-all": "4.1.5", "prettier": "3.3.3", @@ -3547,16 +3547,52 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -3564,7 +3600,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -3597,15 +3633,12 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3629,18 +3662,6 @@ "node": "*" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { "version": "9.8.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", @@ -3650,6 +3671,15 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -3665,43 +3695,6 @@ "@hapi/hoek": "^9.0.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -3715,12 +3708,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "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==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@inquirer/checkbox": { "version": "2.4.0", @@ -5899,12 +5898,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "node_modules/@vitejs/plugin-basic-ssl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", @@ -8946,18 +8939,6 @@ "node": ">=6" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -9731,41 +9712,37 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -9779,23 +9756,23 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -9813,15 +9790,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -9909,6 +9877,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -9921,21 +9901,6 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -9975,30 +9940,30 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -10329,15 +10294,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/filelist": { @@ -10436,17 +10401,16 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -16002,22 +15966,6 @@ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", diff --git a/desktop/package.json b/desktop/package.json index 3d2b9b2e8..37f6c9953 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -72,7 +72,7 @@ "@types/node": "20.14.11", "electron": "31.3.1", "electron-builder": "24.13.3", - "eslint": "8.57.0", + "eslint": "9.8.0", "node-polyfill-webpack-plugin": "4.0.0", "npm-run-all": "4.1.5", "prettier": "3.3.3", From d19041101995bc66f68820c82318031ce407b897 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 22:15:05 +0000 Subject: [PATCH 086/104] [desktop]: Bump primeng from 17.18.6 to 17.18.7 in /desktop Bumps [primeng](https://github.com/primefaces/primeng) from 17.18.6 to 17.18.7. - [Release notes](https://github.com/primefaces/primeng/releases) - [Changelog](https://github.com/primefaces/primeng/blob/master/CHANGELOG.md) - [Commits](https://github.com/primefaces/primeng/compare/17.18.6...17.18.7) --- updated-dependencies: - dependency-name: primeng dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- desktop/package-lock.json | 8 ++++---- desktop/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 0f393534f..0d5e86040 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -30,7 +30,7 @@ "panzoom": "9.4.3", "primeflex": "3.3.1", "primeicons": "7.0.0", - "primeng": "17.18.6", + "primeng": "17.18.7", "primeng-sass-theme": "github:primefaces/primeng-sass-theme#17.18.3", "rxjs": "7.8.1", "tslib": "2.6.3", @@ -15283,9 +15283,9 @@ "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==" }, "node_modules/primeng": { - "version": "17.18.6", - "resolved": "https://registry.npmjs.org/primeng/-/primeng-17.18.6.tgz", - "integrity": "sha512-WnsUWUxNkeqiJf5yrdT/TTzVyCP6R7Z60sr87chh3D7BNuNqh2R5Yd6GI86QVRhE172yt3AjjSIWfqRhzyul5w==", + "version": "17.18.7", + "resolved": "https://registry.npmjs.org/primeng/-/primeng-17.18.7.tgz", + "integrity": "sha512-RKbUL69uTzDrVLOKxC8Qn7tyzoAUXetBsMOnNJJaomXTirC001vNTw/wzcuLxkTQpNXAOztxcKMpMTmZQMhe5Q==", "dependencies": { "tslib": "^2.3.0" }, diff --git a/desktop/package.json b/desktop/package.json index 37f6c9953..3855fa538 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -54,7 +54,7 @@ "panzoom": "9.4.3", "primeflex": "3.3.1", "primeicons": "7.0.0", - "primeng": "17.18.6", + "primeng": "17.18.7", "primeng-sass-theme": "github:primefaces/primeng-sass-theme#17.18.3", "rxjs": "7.8.1", "tslib": "2.6.3", From 0cd0e83d2a979989f3bc57a1a84554a95f10c886 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 3 Aug 2024 00:02:30 -0300 Subject: [PATCH 087/104] [api][desktop]: Improve Calibration --- api/schemas/objectbox.json | 92 ++-- .../calibration/CalibrationFrameController.kt | 31 +- .../api/calibration/CalibrationFrameEntity.kt | 31 +- .../api/calibration/CalibrationFrameGroup.kt | 8 - .../calibration/CalibrationFrameRepository.kt | 22 +- .../calibration/CalibrationFrameService.kt | 62 ++- .../api/calibration/CalibrationGroupKey.kt | 28 - desktop/app/window.manager.ts | 26 +- desktop/src/app/about/about.component.ts | 2 +- desktop/src/app/app.module.ts | 2 + .../calibration/calibration.component.html | 216 ++++---- .../calibration/calibration.component.scss | 31 -- .../app/calibration/calibration.component.ts | 483 ++++++++++++------ desktop/src/app/home/home.component.html | 12 +- desktop/src/app/home/home.component.ts | 22 +- .../src/app/stacker/stacker.component.html | 2 +- desktop/src/app/stacker/stacker.component.ts | 21 +- desktop/src/assets/icons/calibration.png | Bin 0 -> 862 bytes desktop/src/assets/icons/photo-filter.png | Bin 1657 -> 0 bytes .../menu-item/menu-item.component.ts | 3 + desktop/src/shared/pipes/path.pipe.ts | 26 + desktop/src/shared/services/api.service.ts | 9 +- .../shared/services/browser-window.service.ts | 2 +- .../src/shared/services/preference.service.ts | 4 +- desktop/src/shared/types/calibration.types.ts | 41 +- desktop/src/shared/types/home.types.ts | 2 +- desktop/src/shared/types/image.types.ts | 14 +- desktop/src/styles.scss | 4 +- 28 files changed, 679 insertions(+), 517 deletions(-) delete mode 100644 api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameGroup.kt delete mode 100644 api/src/main/kotlin/nebulosa/api/calibration/CalibrationGroupKey.kt delete mode 100644 desktop/src/app/calibration/calibration.component.scss create mode 100644 desktop/src/assets/icons/calibration.png delete mode 100644 desktop/src/assets/icons/photo-filter.png create mode 100644 desktop/src/shared/pipes/path.pipe.ts diff --git a/api/schemas/objectbox.json b/api/schemas/objectbox.json index 811401385..0f7413c13 100644 --- a/api/schemas/objectbox.json +++ b/api/schemas/objectbox.json @@ -4,77 +4,77 @@ "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", "entities": [ { - "id": "1:4508028933515523414", - "lastPropertyId": "13:5569629325911720184", + "id": "1:3544801173480775772", + "lastPropertyId": "13:3755368355153819967", "name": "CalibrationFrameEntity", "properties": [ { - "id": "1:279471804400581871", + "id": "1:6440158350156700816", "name": "id", "type": 6, "flags": 1 }, { - "id": "2:9048727858630632737", + "id": "2:7830549305901803879", "name": "type", - "indexId": "1:3018423918314968566", + "indexId": "1:3705837194399110688", "type": 5, "flags": 8 }, { - "id": "3:5712791023807889534", - "name": "name", - "indexId": "2:8432810603549739468", + "id": "3:8490362500884478696", + "name": "group", + "indexId": "2:2460719507268221169", "type": 9, "flags": 2048 }, { - "id": "4:3434117744352502900", + "id": "4:169758157435742191", "name": "filter", "type": 9 }, { - "id": "5:1871034143652415809", + "id": "5:5772177826523179837", "name": "exposureTime", "type": 6 }, { - "id": "6:8846123268014704509", + "id": "6:979735190507089416", "name": "temperature", "type": 8 }, { - "id": "7:8561154143050278063", + "id": "7:1567591787936780727", "name": "width", "type": 5 }, { - "id": "8:6920579444153489022", + "id": "8:804894592407875320", "name": "height", "type": 5 }, { - "id": "9:4300769060778976734", + "id": "9:7150567366206966047", "name": "binX", "type": 5 }, { - "id": "10:4693474237106002327", + "id": "10:6904147472104067341", "name": "binY", "type": 5 }, { - "id": "11:8369728096653684761", + "id": "11:5805422636156073861", "name": "gain", "type": 8 }, { - "id": "12:617052828938607363", + "id": "12:3861144650886065321", "name": "path", "type": 9 }, { - "id": "13:5569629325911720184", + "id": "13:3755368355153819967", "name": "enabled", "type": 1 } @@ -82,25 +82,25 @@ "relations": [] }, { - "id": "2:4800249862026080527", - "lastPropertyId": "3:211299529025119304", + "id": "2:5695036645028998704", + "lastPropertyId": "3:5935807626551879093", "name": "PreferenceEntity", "properties": [ { - "id": "1:3593540058272630983", + "id": "1:1241938942467328378", "name": "id", "type": 6, "flags": 1 }, { - "id": "2:2699303611424729430", + "id": "2:5066364999797986961", "name": "key", - "indexId": "3:2030544424571300028", + "indexId": "3:361394127200064680", "type": 9, "flags": 34848 }, { - "id": "3:211299529025119304", + "id": "3:5935807626551879093", "name": "value", "type": 9 } @@ -108,28 +108,28 @@ "relations": [] }, { - "id": "3:9190695617085753667", - "lastPropertyId": "4:411434182698925224", + "id": "3:13725857459345728", + "lastPropertyId": "4:8575761112465612996", "name": "SatelliteEntity", "properties": [ { - "id": "1:7748265871438465999", + "id": "1:7008444193321057279", "name": "id", "type": 6, "flags": 129 }, { - "id": "2:2980713713220488130", + "id": "2:7254931361809919912", "name": "name", "type": 9 }, { - "id": "3:8036745814034214740", + "id": "3:7655077553453802998", "name": "tle", "type": 9 }, { - "id": "4:411434182698925224", + "id": "4:8575761112465612996", "name": "groups", "type": 30 } @@ -137,68 +137,68 @@ "relations": [] }, { - "id": "4:6299583728620001761", - "lastPropertyId": "12:4179508964623201115", + "id": "4:2355261488865870711", + "lastPropertyId": "12:8881688937650635468", "name": "SimbadEntity", "properties": [ { - "id": "1:7284883107181783588", + "id": "1:8754753767317947963", "name": "id", "type": 6, "flags": 129 }, { - "id": "2:1059978401562504177", + "id": "2:875189598014282513", "name": "name", "type": 9 }, { - "id": "3:2238737597611607433", + "id": "3:1840539013499888018", "name": "type", "type": 5 }, { - "id": "4:6034348124979703831", + "id": "4:8380920369067256416", "name": "rightAscensionJ2000", "type": 8 }, { - "id": "5:6603670815168137185", + "id": "5:4114744755808135895", "name": "declinationJ2000", "type": 8 }, { - "id": "6:4798847469480514750", + "id": "6:5877086147655445788", "name": "magnitude", "type": 8 }, { - "id": "7:4280564484498302769", + "id": "7:4614518058111040649", "name": "pmRA", "type": 8 }, { - "id": "8:1070997648386390650", + "id": "8:5619165542749552220", "name": "pmDEC", "type": 8 }, { - "id": "9:7408560810497672822", + "id": "9:8196290885692683478", "name": "parallax", "type": 8 }, { - "id": "10:7464931444484734827", + "id": "10:2681231197677728845", "name": "radialVelocity", "type": 8 }, { - "id": "11:531497562996887037", + "id": "11:2414643968839286765", "name": "redshift", "type": 8 }, { - "id": "12:4179508964623201115", + "id": "12:8881688937650635468", "name": "constellation", "type": 5 } @@ -206,8 +206,8 @@ "relations": [] } ], - "lastEntityId": "4:6299583728620001761", - "lastIndexId": "3:2030544424571300028", + "lastEntityId": "4:2355261488865870711", + "lastIndexId": "3:361394127200064680", "lastRelationId": "0:0", "lastSequenceId": "0:0", "modelVersion": 5, diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameController.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameController.kt index 199bf8db7..d69ec5960 100644 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameController.kt +++ b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameController.kt @@ -1,7 +1,6 @@ package nebulosa.api.calibration import jakarta.validation.Valid -import jakarta.validation.constraints.NotBlank import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.* import java.nio.file.Path @@ -16,26 +15,24 @@ class CalibrationFrameController( @GetMapping fun groups() = calibrationFrameService.groups() - @GetMapping("{name}") - fun groupedCalibrationFrames(@PathVariable name: String): List { - var id = 0 - val groupedFrames = calibrationFrameService.groupedCalibrationFrames(name) - return groupedFrames.map { CalibrationFrameGroup(++id, name, it.key, it.value) } + @GetMapping("{group}") + fun frames(@PathVariable group: String): List { + return calibrationFrameService.frames(group).sorted() } - @PutMapping("{name}") - fun upload(@PathVariable name: String, @RequestParam path: Path): List { - return calibrationFrameService.upload(name, path) + @PutMapping("{group}") + fun upload(@PathVariable group: String, @RequestParam path: Path): List { + return calibrationFrameService.upload(group, path) } - @PatchMapping("{frame}") - fun edit( - frame: CalibrationFrameEntity, - @Valid @NotBlank @RequestParam name: String, @RequestParam enabled: Boolean, - ) = calibrationFrameService.edit(frame, name, enabled) + @PostMapping + fun update(@RequestBody @Valid body: CalibrationFrameEntity): CalibrationFrameEntity { + require(body.id > 0L) { "invalid frame id" } + return calibrationFrameService.edit(body) + } - @DeleteMapping("{frame}") - fun delete(frame: CalibrationFrameEntity) { - calibrationFrameService.delete(frame) + @DeleteMapping("{id}") + fun delete(@PathVariable id: Long) { + calibrationFrameService.delete(id) } } diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameEntity.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameEntity.kt index 1b15e657e..4e684e1b4 100644 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameEntity.kt +++ b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameEntity.kt @@ -7,6 +7,7 @@ import io.objectbox.annotation.Index import nebulosa.api.beans.converters.database.FrameTypePropertyConverter import nebulosa.api.beans.converters.database.PathPropertyConverter import nebulosa.api.database.BoxEntity +import nebulosa.fits.INVALID_TEMPERATURE import nebulosa.indi.device.camera.FrameType import java.nio.file.Path @@ -14,10 +15,10 @@ import java.nio.file.Path data class CalibrationFrameEntity( @Id override var id: Long = 0L, @JvmField @Index @Convert(converter = FrameTypePropertyConverter::class, dbType = Int::class) var type: FrameType = FrameType.LIGHT, - @JvmField @Index var name: String = "", + @JvmField @Index var group: String = "", @JvmField var filter: String? = null, @JvmField var exposureTime: Long = 0L, - @JvmField var temperature: Double = 0.0, + @JvmField var temperature: Double = INVALID_TEMPERATURE, @JvmField var width: Int = 0, @JvmField var height: Int = 0, @JvmField var binX: Int = 0, @@ -25,4 +26,28 @@ data class CalibrationFrameEntity( @JvmField var gain: Double = 0.0, @JvmField @Convert(converter = PathPropertyConverter::class, dbType = String::class) var path: Path? = null, @JvmField var enabled: Boolean = true, -) : BoxEntity +) : BoxEntity, Comparable { + + override fun compareTo(other: CalibrationFrameEntity): Int { + return if (type.ordinal > other.type.ordinal) 1 + else if (type.ordinal < other.type.ordinal) -1 + else if (exposureTime > other.exposureTime) 1 + else if (exposureTime < other.exposureTime) -1 + else if (width > other.width) 1 + else if (width < other.width) -1 + else if (height > other.height) 1 + else if (height < other.height) -1 + else if (binX > other.binX) 1 + else if (binX < other.binX) -1 + else if (binY > other.binY) 1 + else if (binY < other.binY) -1 + else if (gain > other.gain) 1 + else if (gain < other.gain) -1 + else if (temperature > other.temperature) 1 + else if (temperature < other.temperature) -1 + else if (filter != null && other.filter != null) filter!!.compareTo(other.filter!!) + else if (filter == null) -1 + else if (other.filter == null) 1 + else 0 + } +} diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameGroup.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameGroup.kt deleted file mode 100644 index df469a2cd..000000000 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameGroup.kt +++ /dev/null @@ -1,8 +0,0 @@ -package nebulosa.api.calibration - -data class CalibrationFrameGroup( - @JvmField val id: Int, - @JvmField val name: String, - @JvmField val key: CalibrationGroupKey, - @JvmField val frames: List, -) diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameRepository.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameRepository.kt index 056d8ac54..e91a4c454 100644 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameRepository.kt +++ b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameRepository.kt @@ -11,24 +11,24 @@ import org.springframework.stereotype.Component class CalibrationFrameRepository(@Qualifier("calibrationFrameBox") override val box: Box) : BoxRepository() { - fun groups() = box.all.map { it.name }.distinct() + fun groups() = box.all.map { it.group }.distinct() - fun findAll(name: String): List { - return box.query(CalibrationFrameEntity_.name equal name) + fun findAll(group: String): List { + return box.query(CalibrationFrameEntity_.group equal group) .build().use { it.find() } } @Synchronized - fun delete(name: String, path: String) { - val condition = and(CalibrationFrameEntity_.name equal name, CalibrationFrameEntity_.path equal path) + fun delete(group: String, path: String) { + val condition = and(CalibrationFrameEntity_.group equal group, CalibrationFrameEntity_.path equal path) return box.query(condition).build().use { it.remove() } } - fun darkFrames(name: String, width: Int, height: Int, bin: Int, exposureTime: Long, gain: Double): List { + fun darkFrames(group: String, width: Int, height: Int, bin: Int, exposureTime: Long, gain: Double): List { val condition = and( CalibrationFrameEntity_.type equal FrameType.DARK.ordinal, CalibrationFrameEntity_.enabled.isTrue, - CalibrationFrameEntity_.name equal name, + CalibrationFrameEntity_.group equal group, CalibrationFrameEntity_.width equal width, CalibrationFrameEntity_.height equal height, CalibrationFrameEntity_.binX equal bin, @@ -40,11 +40,11 @@ class CalibrationFrameRepository(@Qualifier("calibrationFrameBox") override val return box.query(condition).build().use { it.find() } } - fun biasFrames(name: String, width: Int, height: Int, bin: Int, gain: Double): List { + fun biasFrames(group: String, width: Int, height: Int, bin: Int, gain: Double): List { val condition = and( CalibrationFrameEntity_.type equal FrameType.BIAS.ordinal, CalibrationFrameEntity_.enabled.isTrue, - CalibrationFrameEntity_.name equal name, + CalibrationFrameEntity_.group equal group, CalibrationFrameEntity_.width equal width, CalibrationFrameEntity_.height equal height, CalibrationFrameEntity_.binX equal bin, @@ -55,11 +55,11 @@ class CalibrationFrameRepository(@Qualifier("calibrationFrameBox") override val return box.query(condition).build().use { it.find() } } - fun flatFrames(name: String, filter: String?, width: Int, height: Int, bin: Int): List { + fun flatFrames(group: String, filter: String?, width: Int, height: Int, bin: Int): List { val condition = and( CalibrationFrameEntity_.type equal FrameType.FLAT.ordinal, CalibrationFrameEntity_.enabled.isTrue, - CalibrationFrameEntity_.name equal name, + CalibrationFrameEntity_.group equal group, CalibrationFrameEntity_.width equal width, CalibrationFrameEntity_.height equal height, CalibrationFrameEntity_.binX equal bin, diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt index 5939b03d3..c5e25be84 100644 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt +++ b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationFrameService.kt @@ -28,11 +28,11 @@ class CalibrationFrameService( private val calibrationFrameRepository: CalibrationFrameRepository, ) : CalibrationFrameProvider { - fun calibrate(name: String, image: Image, createNew: Boolean = false): Image { + fun calibrate(group: String, image: Image, createNew: Boolean = false): Image { return synchronized(image) { - val darkFrame = findBestDarkFrames(name, image).firstOrNull() - val biasFrame = if (darkFrame == null) findBestBiasFrames(name, image).firstOrNull() else null - val flatFrame = findBestFlatFrames(name, image).firstOrNull() + val darkFrame = findBestDarkFrames(group, image).firstOrNull() + val biasFrame = if (darkFrame == null) findBestBiasFrames(group, image).firstOrNull() else null + val flatFrame = findBestFlatFrames(group, image).firstOrNull() val darkImage = darkFrame?.path?.fits()?.use(Image::open) val biasImage = biasFrame?.path?.fits()?.use(Image::open) @@ -92,27 +92,28 @@ class CalibrationFrameService( } } - fun groups() = calibrationFrameRepository.groups() + fun groups(): List { + return calibrationFrameRepository.groups() + } - fun groupedCalibrationFrames(name: String): Map> { - val frames = calibrationFrameRepository.findAll(name) - return frames.groupBy(CalibrationGroupKey::from) + fun frames(group: String): List { + return calibrationFrameRepository.findAll(group) } - fun upload(name: String, path: Path): List { + fun upload(group: String, path: Path): List { val files = if (path.isRegularFile()) listOf(path) else if (path.isDirectory()) path.listDirectoryEntries("*.{fits,fit,xisf}").filter { it.isRegularFile() } else return emptyList() - return upload(name, files) + return upload(group, files) } @Synchronized - fun upload(name: String, files: List): List { + fun upload(group: String, files: List): List { val frames = ArrayList(files.size) for (file in files) { - calibrationFrameRepository.delete(name, "$file") + calibrationFrameRepository.delete(group, "$file") try { val image = if (file.isFits()) file.fits() @@ -125,12 +126,12 @@ class CalibrationFrameService( val frameType = header.frameType?.takeIf { it != FrameType.LIGHT } ?: return@use val exposureTime = if (frameType == FrameType.DARK) header.exposureTimeInMicroseconds else 0L - val temperature = if (frameType == FrameType.DARK) header.temperature else 999.0 + val temperature = if (frameType == FrameType.DARK) header.temperature else INVALID_TEMPERATURE val gain = if (frameType != FrameType.FLAT) header.gain else 0.0 val filter = if (frameType == FrameType.FLAT) header.filter else null val frame = CalibrationFrameEntity( - 0L, frameType, name, filter, + 0L, frameType, group, filter, exposureTime, temperature, header.width, header.height, header.binX, header.binY, gain, file, @@ -147,23 +148,21 @@ class CalibrationFrameService( return frames } - fun edit(frame: CalibrationFrameEntity, name: String, enabled: Boolean): CalibrationFrameEntity { - frame.name = name - frame.enabled = enabled + fun edit(frame: CalibrationFrameEntity): CalibrationFrameEntity { return calibrationFrameRepository.save(frame) } - fun delete(frame: CalibrationFrameEntity) { - calibrationFrameRepository.delete(frame) + fun delete(id: Long) { + calibrationFrameRepository.delete(id) } override fun findBestDarkFrames( - name: String, temperature: Double, width: Int, height: Int, + group: String, temperature: Double, width: Int, height: Int, binX: Int, binY: Int, exposureTimeInMicroseconds: Long, gain: Double, ): List { val frames = calibrationFrameRepository - .darkFrames(name, width, height, binX, exposureTimeInMicroseconds, gain) + .darkFrames(group, width, height, binX, exposureTimeInMicroseconds, gain) if (frames.isEmpty()) return emptyList() @@ -175,46 +174,45 @@ class CalibrationFrameService( return groupedFrames.firstEntry().value } - fun findBestDarkFrames(name: String, image: Image): List { + fun findBestDarkFrames(group: String, image: Image): List { val header = image.header val temperature = header.temperature val binX = header.binX val exposureTime = header.exposureTimeInMicroseconds - return findBestDarkFrames(name, temperature, image.width, image.height, binX, binX, exposureTime, header.gain) + return findBestDarkFrames(group, temperature, image.width, image.height, binX, binX, exposureTime, header.gain) } override fun findBestFlatFrames( - name: String, width: Int, height: Int, + group: String, width: Int, height: Int, binX: Int, binY: Int, filter: String? ): List { // TODO: Generate master from matched frames. (Subtract the master bias frame from each flat frame) return calibrationFrameRepository - .flatFrames(name, filter, width, height, binX) + .flatFrames(group, filter, width, height, binX) } - fun findBestFlatFrames(name: String, image: Image): List { + fun findBestFlatFrames(group: String, image: Image): List { val header = image.header val filter = header.filter val binX = header.binX - return findBestFlatFrames(name, image.width, image.height, binX, binX, filter) + return findBestFlatFrames(group, image.width, image.height, binX, binX, filter) } override fun findBestBiasFrames( - name: String, width: Int, height: Int, + group: String, width: Int, height: Int, binX: Int, binY: Int, gain: Double, ): List { // TODO: Generate master from matched frames. - return calibrationFrameRepository - .biasFrames(name, width, height, binX, gain) + return calibrationFrameRepository.biasFrames(group, width, height, binX, gain) } - fun findBestBiasFrames(name: String, image: Image): List { + fun findBestBiasFrames(group: String, image: Image): List { val header = image.header val binX = header.binX - return findBestBiasFrames(name, image.width, image.height, binX, binX, image.header.gain) + return findBestBiasFrames(group, image.width, image.height, binX, binX, image.header.gain) } companion object { diff --git a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationGroupKey.kt b/api/src/main/kotlin/nebulosa/api/calibration/CalibrationGroupKey.kt deleted file mode 100644 index 5f63971b4..000000000 --- a/api/src/main/kotlin/nebulosa/api/calibration/CalibrationGroupKey.kt +++ /dev/null @@ -1,28 +0,0 @@ -package nebulosa.api.calibration - -import nebulosa.indi.device.camera.FrameType -import kotlin.math.roundToInt - -data class CalibrationGroupKey( - @JvmField val type: FrameType, - @JvmField val filter: String?, - @JvmField val width: Int, - @JvmField val height: Int, - @JvmField val binX: Int, - @JvmField val binY: Int, - @JvmField val exposureTime: Long, - @JvmField val temperature: Int, - @JvmField val gain: Double, -) { - - companion object { - - @JvmStatic - fun from(frame: CalibrationFrameEntity) = CalibrationGroupKey( - frame.type, frame.filter?.ifBlank { null }, - frame.width, frame.height, - frame.binX, frame.binY, frame.exposureTime, - frame.temperature.roundToInt(), frame.gain, - ) - } -} diff --git a/desktop/app/window.manager.ts b/desktop/app/window.manager.ts index 9959d0081..2e0b1d518 100644 --- a/desktop/app/window.manager.ts +++ b/desktop/app/window.manager.ts @@ -298,8 +298,12 @@ export class WindowManager { return undefined } + findWindowWith(command: WindowCommand, sender: Electron.WebContents) { + return this.findWindow(command.windowId) ?? this.findWindow(sender.id) + } + async handleFileOpen(event: Electron.IpcMainInvokeEvent, command: OpenFile) { - const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const window = this.findWindowWith(command, event.sender) if (window) { const properties: Electron.OpenDialogOptions['properties'] = ['openFile'] @@ -321,7 +325,7 @@ export class WindowManager { } async handleFileSave(event: Electron.IpcMainInvokeEvent, command: OpenFile) { - const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const window = this.findWindowWith(command, event.sender) if (window) { const ret = await dialog.showSaveDialog(window.browserWindow, { @@ -337,7 +341,7 @@ export class WindowManager { } async handleDirectoryOpen(event: Electron.IpcMainInvokeEvent, command: OpenDirectory) { - const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const window = this.findWindowWith(command, event.sender) if (window) { const ret = await dialog.showOpenDialog(window.browserWindow, { @@ -353,7 +357,7 @@ export class WindowManager { async handleWindowOpen(event: Electron.IpcMainInvokeEvent, command: OpenWindow) { if (command.preference.modal) { - const parentWindow = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const parentWindow = this.findWindowWith(command, event.sender) const appWindow = await this.createWindow(command, parentWindow?.browserWindow) return new Promise((resolve) => { @@ -373,7 +377,7 @@ export class WindowManager { } handleWindowClose(event: Electron.IpcMainInvokeEvent, command: CloseWindow) { - const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const window = this.findWindowWith(command, event.sender) if (window) { window.resolver?.(command.data) @@ -386,7 +390,7 @@ export class WindowManager { } handleWindowResize(event: Electron.IpcMainInvokeEvent, command: ResizeWindow) { - const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const window = this.findWindowWith(command, event.sender) if (window && !window.data.preference.resizable && window.data.preference.autoResizable !== false) { const [width] = window.browserWindow.getSize() @@ -405,30 +409,30 @@ export class WindowManager { } handleWindowMinimize(event: Electron.IpcMainInvokeEvent, command: WindowCommand) { - const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const window = this.findWindowWith(command, event.sender) window?.browserWindow.minimize() return !!window && window.browserWindow.isMinimized() } handleWindowMaximize(event: Electron.IpcMainInvokeEvent, command: WindowCommand) { - const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const window = this.findWindowWith(command, event.sender) return !!window && window.toggleMaximize() } handleWindowPin(event: Electron.IpcMainInvokeEvent, command: WindowCommand) { - const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const window = this.findWindowWith(command, event.sender) window?.browserWindow.setAlwaysOnTop(true) return !!window && window.browserWindow.isAlwaysOnTop() } handleWindowUnpin(event: Electron.IpcMainInvokeEvent, command: WindowCommand) { - const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const window = this.findWindowWith(command, event.sender) window?.browserWindow.setAlwaysOnTop(false) return !!window && window.browserWindow.isAlwaysOnTop() } handleWindowFullscreen(event: Electron.IpcMainInvokeEvent, command: FullscreenWindow) { - const window = this.findWindow(command.windowId) ?? this.findWindow(event.sender.id) + const window = this.findWindowWith(command, event.sender) if (window) { if (command.enabled) window.browserWindow.setFullScreen(true) diff --git a/desktop/src/app/about/about.component.ts b/desktop/src/app/about/about.component.ts index 9687dc168..16dd1149c 100644 --- a/desktop/src/app/about/about.component.ts +++ b/desktop/src/app/about/about.component.ts @@ -43,8 +43,8 @@ export class AboutComponent { this.icons.push({ link: `${FLAT_ICON_URL}/calculator_7182540`, name: 'Calculator', author: 'Iconic Panda - Flaticon' }) this.icons.push({ link: `${FLAT_ICON_URL}/target_10542035`, name: 'Target', author: 'Arkinasi - Flaticon' }) this.icons.push({ link: `${FLAT_ICON_URL}/stack_3342239`, name: 'Stack', author: 'Pixel perfect - Flaticon' }) - this.icons.push({ link: `${FLAT_ICON_URL}/photo-filter_4892829`, name: 'Photo filter', author: 'Freepik - Flaticon' }) this.icons.push({ link: `${FLAT_ICON_URL}/blackhole_6704410`, name: 'Blackhole', author: 'Freepik - Flaticon' }) + this.icons.push({ link: `${FLAT_ICON_URL}/calibration_2364169`, name: 'Calibration', author: 'Freepik - Flaticon' }) } private mapDependencies() { diff --git a/desktop/src/app/app.module.ts b/desktop/src/app/app.module.ts index 1e0b95071..3de22f9f2 100644 --- a/desktop/src/app/app.module.ts +++ b/desktop/src/app/app.module.ts @@ -96,6 +96,7 @@ import { RotatorComponent } from './rotator/rotator.component' import { SequencerComponent } from './sequencer/sequencer.component' import { SettingsComponent } from './settings/settings.component' import { StackerComponent } from './stacker/stacker.component' +import { PathPipe } from '../shared/pipes/path.pipe' @NgModule({ declarations: [ @@ -140,6 +141,7 @@ import { StackerComponent } from './stacker/stacker.component' MountComponent, NoDropdownDirective, PathChooserComponent, + PathPipe, RotatorComponent, SequencerComponent, SettingsComponent, diff --git a/desktop/src/app/calibration/calibration.component.html b/desktop/src/app/calibration/calibration.component.html index bee121072..53a446168 100644 --- a/desktop/src/app/calibration/calibration.component.html +++ b/desktop/src/app/calibration/calibration.component.html @@ -1,120 +1,124 @@ -
-
-
- -
-
- - -
- @if (node.data.type === 'NAME') { - {{ node.label }} - } @else if (node.data.type === 'GROUP') { -
- - - - - - - -
- } @else if (node.data.type === 'FRAME') { -
- - - {{ node.data.data.path }} - -
- } -
- @if (node.data.type === 'NAME') { +
+
+ + @for (key of groups; track $index) { + @let value = frames.get(key) ?? []; + +
+
+
+ (onClick)="openFilesToUpload(key)" /> + (onClick)="openDirectoryToUpload(key)" /> +
+ {{ this.frames.get(key)?.length ?? 0 }} frames +
+ - } - + size="small" + (onClick)="groupMenu.toggle($event)" /> +
+
+
+ + +
+
+
+
+ +
+ {{ item.type }} +
+ {{ item.exposureTime | exposureTime }} + {{ item.width }}x{{ item.height }} + {{ item.binX }}x{{ item.binY }} + GAIN: {{ item.gain }} + + {{ item.temperature }}ยฐC + +
+ {{ item.path }} +
+
+
+ + + +
+
+
+
+
+
- - -
+ + } +
@@ -122,18 +126,18 @@ + [(ngModel)]="groupDialog.group" />
+ (onClick)="groupDialog.save?.()" />
diff --git a/desktop/src/app/calibration/calibration.component.scss b/desktop/src/app/calibration/calibration.component.scss deleted file mode 100644 index 627dc317d..000000000 --- a/desktop/src/app/calibration/calibration.component.scss +++ /dev/null @@ -1,31 +0,0 @@ -neb-calibration { - .p-treenode-label { - width: 100%; - } - - .p-tree-wrapper { - max-height: 288px; - } - - .p-tree { - .p-tree-container { - padding-right: 4px; - - .p-treenode { - padding: 0; - - .p-treenode-content { - padding: 0 0.5rem; - } - } - } - } - - .p-treenode-leaf > .p-treenode-content .p-tree-toggler { - display: none; - } - - .p-tree-empty-message { - padding: 1rem 0.5rem; - } -} diff --git a/desktop/src/app/calibration/calibration.component.ts b/desktop/src/app/calibration/calibration.component.ts index e47421233..7fc78f33a 100644 --- a/desktop/src/app/calibration/calibration.component.ts +++ b/desktop/src/app/calibration/calibration.component.ts @@ -1,264 +1,411 @@ -import { AfterViewInit, Component, ViewEncapsulation } from '@angular/core' +import { AfterViewInit, Component, HostListener, OnDestroy, QueryList, ViewChildren, ViewEncapsulation } from '@angular/core' import { dirname } from 'path' -import { TreeDragDropService, TreeNode } from 'primeng/api' -import { TreeNodeDropEvent } from 'primeng/tree' +import { Listbox } from 'primeng/listbox' +import { MenuItem } from '../../shared/components/menu-item/menu-item.component' +import { SEPARATOR_MENU_ITEM } from '../../shared/constants' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' -import { CalibrationFrame, CalibrationFrameGroup } from '../../shared/types/calibration.types' +import { CalibrationFrame, DEFAULT_CALIBRATION_GROUP_DIALOG, DEFAULT_CALIBRATION_PREFERENCE } from '../../shared/types/calibration.types' +import { textComparator } from '../../shared/utils/comparators' import { AppComponent } from '../app.component' -export interface CalibrationNode extends TreeNode { - key: string - label: string - data: TreeNodeData - children: CalibrationNode[] - parent?: CalibrationNode -} - -export type TreeNodeData = { type: 'NAME'; data: string } | { type: 'GROUP'; data: CalibrationFrameGroup } | { type: 'FRAME'; data: CalibrationFrame } - @Component({ selector: 'neb-calibration', templateUrl: './calibration.component.html', - styleUrls: ['./calibration.component.scss'], - providers: [TreeDragDropService], encapsulation: ViewEncapsulation.None, }) -export class CalibrationComponent implements AfterViewInit { - readonly frames: CalibrationNode[] = [] +export class CalibrationComponent implements AfterViewInit, OnDestroy { + protected readonly frames = new Map() + protected readonly preference = structuredClone(DEFAULT_CALIBRATION_PREFERENCE) + protected readonly groupDialog = structuredClone(DEFAULT_CALIBRATION_GROUP_DIALOG) + protected selectedFrames: CalibrationFrame[] = [] + + protected tab = 0 + private frameId = '' + + private readonly renameSelectedFramesMenuItem: MenuItem = { + icon: 'mdi mdi-pencil', + label: 'Rename Group', + badge: '0', + visible: false, + command: () => { + this.showEditGroupDialogForSelectedFrames() + }, + } + + private readonly deleteSelectedFramesMenuItem: MenuItem = { + icon: 'mdi mdi-delete', + severity: 'danger', + label: 'Delete', + badge: '0', + visible: false, + command: () => this.deleteSelectedFrames(), + } + + protected activeGroup = '' + protected readonly groupModel: MenuItem[] = [ + { + icon: 'mdi mdi-checkbox-marked', + label: 'Select All', + command: () => { + const frames = this.activeFrames + + if (frames.length) { + const selectedFrames = new Set(this.selectedFrames) + + for (const frame of frames) { + selectedFrames.add(frame) + } + + this.selectedFrames = Array.from(selectedFrames) + this.frameSelected() + } + }, + }, + { + icon: 'mdi mdi-checkbox-blank-outline', + label: 'Unselect All', + command: () => { + const frames = this.activeFrames + + if (frames.length) { + const selectedFrames = new Set(this.selectedFrames) + + for (const frame of frames) { + selectedFrames.delete(frame) + } + + this.selectedFrames = Array.from(selectedFrames) + this.frameSelected() + } + }, + }, + SEPARATOR_MENU_ITEM, + { + icon: 'mdi mdi-checkbox-marked', + label: 'Enable All', + command: async () => { + const frames = this.activeFrames + + for (const frame of frames) { + if (!frame.enabled) { + await this.toggleFrame(frame, true) + } + } + }, + }, + { + icon: 'mdi mdi-checkbox-blank-outline', + label: 'Disable All', + command: async () => { + const frames = this.activeFrames + + for (const frame of frames) { + if (frame.enabled) { + await this.toggleFrame(frame, false) + } + } + }, + }, + SEPARATOR_MENU_ITEM, + { + icon: 'mdi mdi-pencil', + label: 'Rename Group', + command: () => { + if (this.activeGroup && this.activeFrames.length) { + this.showEditGroupDialog(this.activeGroup) + } + }, + }, + { + icon: 'mdi mdi-delete', + label: 'Delete All', + iconClass: 'text-danger', + command: async () => { + if (this.activeGroup && this.activeFrames.length) { + await this.deleteFrameGroup(this.activeGroup) + } + }, + }, + ] - showNewGroupDialog = false - newGroupName = '' - newGroupDialogSave: () => void = () => {} + @ViewChildren('frameListBox') + private readonly frameListBoxes!: QueryList + + get groups() { + return Array.from(this.frames.keys()).sort(textComparator) + } + + get activeFrames() { + return this.frames.get(this.activeGroup) ?? [] + } constructor( app: AppComponent, private readonly api: ApiService, - private readonly electron: ElectronService, - private readonly browserWindow: BrowserWindowService, - private readonly preference: PreferenceService, + private readonly electronService: ElectronService, + private readonly browserWindowService: BrowserWindowService, + private readonly preferenceService: PreferenceService, ) { app.title = 'Calibration' + + app.topMenu.push({ + icon: 'mdi mdi-plus', + label: 'New Group', + command: () => { + this.showNewGroupDialog() + }, + }) + + app.topMenu.push(this.renameSelectedFramesMenuItem) + app.topMenu.push(this.deleteSelectedFramesMenuItem) } - async ngAfterViewInit() { - await this.load() + ngAfterViewInit() { + this.loadPreference() + + return this.load() } - private makeTreeNode(key: string, label: string, data: TreeNodeData, parent?: CalibrationNode): CalibrationNode { - const draggable = data.type === 'FRAME' - const droppable = data.type === 'NAME' - return { key, label, data, children: [], parent, draggable, droppable } + @HostListener('window:unload') + ngOnDestroy() { + void this.closeFrameWindow() } - addGroup(name: string) { - const node = this.frames.find((e) => e.label === name) ?? this.makeTreeNode(`group-${name}`, name, { type: 'NAME', data: name }) + protected frameSelected() { + const count = this.selectedFrames.length + const visible = count > 0 - if (!this.frames.includes(node)) { - this.frames.push(node) - } + this.renameSelectedFramesMenuItem.visible = visible + this.deleteSelectedFramesMenuItem.visible = visible - return node + if (visible) { + this.renameSelectedFramesMenuItem.badge = `${count}` + this.deleteSelectedFramesMenuItem.badge = `${count}` + } } - addFrameGroup(name: string | CalibrationNode, group: CalibrationFrameGroup) { - const parent = typeof name === 'string' ? this.frames.find((e) => e.label === name) : name + protected async openFilesToUpload(group: string) { + const paths = await this.electronService.openImages({ defaultPath: this.preference.filePath }) - if (parent) { - const node = this.makeTreeNode(`frame-group-${group.id}`, `Frame`, { type: 'GROUP', data: group }, parent) - parent.children.push(node) - return node - } + if (paths && paths.length) { + this.preference.filePath = dirname(paths[0]) + this.savePreference() - return undefined + for (const path of paths) { + await this.upload(group, path) + } + } } - addFrame(group: string | CalibrationNode, frame: CalibrationFrame) { - const parent = typeof group === 'string' ? this.frames.find((e) => e.label === group) : group + protected async openDirectoryToUpload(group: string) { + const path = await this.electronService.openDirectory({ defaultPath: this.preference.directoryPath }) - if (parent) { - const node = this.makeTreeNode(`frame-${frame.id}`, `Frame`, { type: 'FRAME', data: frame }, parent) - parent.children.push(node) - return node + if (path) { + this.preference.directoryPath = path + this.savePreference() + await this.upload(group, path) } - - return undefined } - async openFileToUpload(node: CalibrationNode) { - if (node.data.type === 'NAME') { - const preference = this.preference.calibrationPreference.get() - const path = await this.electron.openImage({ defaultPath: preference.openPath }) + private async upload(group: string, path: string) { + const frames = await this.api.uploadCalibrationFrame(group, path) - if (path) { - preference.openPath = dirname(path) - this.preference.calibrationPreference.set(preference) - await this.upload(node, path) - } + if (frames.length > 0) { + await this.electronService.calibrationChanged() + await this.loadGroup(group) } } - async openDirectoryToUpload(node: CalibrationNode) { - if (node.data.type === 'NAME') { - const preference = this.preference.calibrationPreference.get() - const path = await this.electron.openDirectory({ defaultPath: preference.openPath }) + private async loadGroup(group: string) { + const frames = await this.api.calibrationFrames(group) - if (path) { - preference.openPath = path - this.preference.calibrationPreference.set(preference) - await this.upload(node, path) + for (let i = 0; i < this.selectedFrames.length; i++) { + for (const frame of frames) { + if (frame.id === this.selectedFrames[i].id) { + this.selectedFrames[i] = frame + } } } - } - private async upload(node: CalibrationNode, path: string) { - if (node.data.type === 'NAME') { - const frames = await this.api.uploadCalibrationFrame(node.data.data, path) + this.frames.set(group, frames) + } - if (frames.length > 0) { - await this.electron.calibrationChanged() - await this.load() - } + private loadDefaultGroupIfEmpty() { + if (!this.frames.size) { + this.frames.set('Group 1', []) } } private async load() { - this.frames.length = 0 - - const names = await this.api.calibrationGroups() + this.frames.clear() - for (const name of names) { - const nameNode = this.addGroup(name) + const groups = await this.api.calibrationGroups() - const groups = await this.api.calibrationFrames(name) + for (const group of groups) { + await this.loadGroup(group) + } - for (const group of groups) { - const frameGroupNode = this.addFrameGroup(nameNode, group) + this.loadDefaultGroupIfEmpty() + } - if (frameGroupNode) { - for (const frame of group.frames) { - this.addFrame(frameGroupNode, frame) - } - } - } - } + protected openImage(frame: CalibrationFrame) { + return this.browserWindowService.openImage({ path: frame.path, source: 'PATH' }) } - openImage(frame: CalibrationFrame) { - return this.browserWindow.openImage({ path: frame.path, source: 'PATH' }) + protected toggleFrame(frame: CalibrationFrame, enabled: boolean) { + frame.enabled = enabled + return this.api.updateCalibrationFrame(frame) } - async toggleCalibrationFrame(node: CalibrationNode, enabled: boolean) { - if (node.data.type === 'FRAME') { - await this.api.editCalibrationFrame(node.data.data) - } + protected async openFrame(frame: CalibrationFrame) { + this.frameId = await this.browserWindowService.openImage({ path: frame.path, id: 'calibration', source: 'PATH' }) } - async deleteFrame(node: CalibrationNode) { - const deleteFromParent = async () => { - if (node.parent) { - const idx = node.parent.children.indexOf(node) + protected async deleteFrame(frame: CalibrationFrame, box?: Listbox) { + await this.api.deleteCalibrationFrame(frame) - if (idx >= 0) { - node.parent.children.splice(idx, 1) - console.info('frame deleted', node) - } + let index = this.selectedFrames.indexOf(frame) - if (!node.parent.children.length) { - await this.deleteFrame(node.parent) - } - } else { - const idx = this.frames.indexOf(node) + if (index >= 0) { + console.log('selected frame removed', frame) + this.selectedFrames.splice(index, 1) + this.frameSelected() + } - if (idx >= 0) { - this.frames.splice(idx, 1) - console.info('frame deleted', node) - await this.electron.calibrationChanged() - } + const frames = this.frames.get(frame.group) + + if (frames?.length) { + index = frames.indexOf(frame) + + if (index >= 0) { + frames.splice(index, 1) + box?.cd.markForCheck() } } + } - if (node.data.type === 'FRAME') { - await this.api.deleteCalibrationFrame(node.data.data) - await deleteFromParent() - } else { - for (const frame of Array.from(node.children)) { - await this.deleteFrame(frame) - } + private async deleteSelectedFrames() { + const groups = new Set() + const frames = Array.from(this.selectedFrames) - if (!node.children.length) { - await deleteFromParent() - } + for (const frame of frames) { + groups.add(frame.group) + await this.deleteFrame(frame) } + + this.markFrameListBoxesForCheck() } - private calibrationFrameFromNode(node: CalibrationNode) { - const frames: CalibrationFrame[] = [] + private async deleteFrameGroup(group: string) { + const frames = Array.from(this.frames.get(group) ?? []) - function recursive(node: TreeNode) { - if (node.data) { - if (node.data.type === 'NAME' || node.data.type === 'GROUP') { - if (node.children) { - for (const child of node.children) { - recursive(child) - } - } - } else { - frames.push(node.data.data) + for (const frame of frames) { + await this.deleteFrame(frame) + } + + this.markFrameListBoxesForCheck() + } + + private showEditGroupDialogForSelectedFrames() { + this.groupDialog.save = async () => { + const groups = new Set() + + groups.add(this.groupDialog.group) + + for (const frame of this.selectedFrames) { + if (this.groupDialog.group !== frame.group) { + groups.add(frame.group) + frame.group = this.groupDialog.group + await this.api.updateCalibrationFrame(frame) } } + + this.groupDialog.showDialog = false + + for (const group of groups) { + await this.loadGroup(group) + } + + await this.electronService.calibrationChanged() } - recursive(node) + this.groupDialog.group = '' + this.groupDialog.showDialog = true + } - return frames + private async closeFrameWindow() { + if (this.frameId) { + await this.electronService.closeWindow(undefined, this.frameId) + } } - showNewGroupDialogForAdd() { - this.newGroupDialogSave = () => { - this.addGroup(this.newGroupName) - this.showNewGroupDialog = false + private showNewGroupDialog() { + this.groupDialog.save = () => { + if (this.groupDialog.group) { + this.frames.set(this.groupDialog.group, []) + this.groupDialog.showDialog = false + } } - this.newGroupName = '' - this.showNewGroupDialog = true + this.groupDialog.group = '' + this.groupDialog.showDialog = true } - showNewGroupDialogForEdit(node: CalibrationNode) { - if (node.data.type === 'NAME') { - this.newGroupDialogSave = async () => { - const frames = this.calibrationFrameFromNode(node) + protected showEditGroupDialog(value: CalibrationFrame | string) { + if (typeof value === 'string') { + this.groupDialog.save = async () => { + const frames = this.frames.get(value) - for (const frame of frames) { - frame.name = this.newGroupName - await this.api.editCalibrationFrame(frame) - await this.electron.calibrationChanged() + if (frames?.length && this.groupDialog.group) { + for (const frame of frames) { + frame.group = this.groupDialog.group + await this.api.updateCalibrationFrame(frame) + } + + await this.loadGroup(value) + await this.loadGroup(this.groupDialog.group) + await this.electronService.calibrationChanged() } - this.showNewGroupDialog = false - await this.load() + this.groupDialog.showDialog = false } - this.newGroupName = node.data.data - this.showNewGroupDialog = true + this.groupDialog.group = value + } else { + this.groupDialog.save = async () => { + const prevGroup = value.group + + if (this.groupDialog.group !== prevGroup) { + value.group = this.groupDialog.group + await this.api.updateCalibrationFrame(value) + await this.loadGroup(prevGroup) + await this.loadGroup(value.group) + await this.electronService.calibrationChanged() + } + + this.groupDialog.showDialog = false + } + + this.groupDialog.group = value.group } + + this.groupDialog.showDialog = true } - editGroupName() { - this.showNewGroupDialog = false + private loadPreference() { + Object.assign(this.preference, this.preferenceService.calibrationPreference.get()) } - async frameDropped(event: TreeNodeDropEvent) { - const dragNode = event.dragNode as CalibrationNode - const dropNode = event.dropNode as CalibrationNode + protected savePreference() { + this.preferenceService.calibrationPreference.set(this.preference) + } - if (dragNode.data.type === 'FRAME' && dropNode.data.type === 'NAME' && dragNode.data.data.name !== dropNode.data.data) { - dragNode.data.data.name = dropNode.data.data - await this.api.editCalibrationFrame(dragNode.data.data) - await this.electron.calibrationChanged() - await this.load() + private markFrameListBoxesForCheck() { + for (const box of this.frameListBoxes) { + box.cd.markForCheck() } } } diff --git a/desktop/src/app/home/home.component.html b/desktop/src/app/home/home.component.html index 7f00a41a1..f2de2bf52 100644 --- a/desktop/src/app/home/home.component.html +++ b/desktop/src/app/home/home.component.html @@ -236,6 +236,15 @@
Flat Wizard
+
+ + +
Calibration
+
+
+ (deviceDisconnect)="deviceDisconnected($event)" /> { - if (isCamera(device) && !isGuideHead(device)) { - return [ - { - icon: 'mdi mdi-wrench', - label: 'Calibration', - command: (e) => { - e.originalEvent?.stopImmediatePropagation() - return this.browserWindowService.openCalibration() - }, - }, - ] - } else { - return [] - } - } - private async openDevice(type: K) { this.deviceModel.length = 0 @@ -475,6 +458,9 @@ export class HomeComponent implements AfterContentInit { case 'CALCULATOR': await this.browserWindowService.openCalculator() break + case 'CALIBRATION': + await this.browserWindowService.openCalibration() + break case 'ABOUT': await this.browserWindowService.openAbout() break diff --git a/desktop/src/app/stacker/stacker.component.html b/desktop/src/app/stacker/stacker.component.html index 5c9e9ca81..4cc290230 100644 --- a/desktop/src/app/stacker/stacker.component.html +++ b/desktop/src/app/stacker/stacker.component.html @@ -31,7 +31,7 @@ [metaKeySelection]="false" [style]="{ width: '100%', height: '296px' }" [listStyle]="{ maxHeight: '296px', height: '296px' }" - emptyMessage="No files"> + emptyMessage="No frames"> diff --git a/desktop/src/app/stacker/stacker.component.ts b/desktop/src/app/stacker/stacker.component.ts index af943bac9..35ed8c021 100644 --- a/desktop/src/app/stacker/stacker.component.ts +++ b/desktop/src/app/stacker/stacker.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component } from '@angular/core' +import { AfterViewInit, Component, HostListener, OnDestroy } from '@angular/core' import { dirname } from 'path' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' @@ -11,11 +11,13 @@ import { AppComponent } from '../app.component' selector: 'neb-stacker', templateUrl: './stacker.component.html', }) -export class StackerComponent implements AfterViewInit { +export class StackerComponent implements AfterViewInit, OnDestroy { protected running = false protected readonly preference = structuredClone(DEFAULT_STACKER_PREFERENCE) protected request = this.preference.request + private frameId = '' + get referenceTarget() { return this.request.targets.find((e) => e.enabled && e.reference && e.type === 'LIGHT') } @@ -44,6 +46,11 @@ export class StackerComponent implements AfterViewInit { this.running = await this.api.stackerIsRunning() } + @HostListener('window:unload') + ngOnDestroy() { + void this.closeFrameWindow() + } + protected async openImages() { try { this.running = true @@ -88,8 +95,8 @@ export class StackerComponent implements AfterViewInit { } } - protected openTargetImage(target: StackingTarget) { - return this.browserWindowService.openImage({ path: target.path, id: 'stacker', source: 'PATH' }) + protected async openTargetImage(target: StackingTarget) { + this.frameId = await this.browserWindowService.openImage({ path: target.path, id: 'stacker', source: 'PATH' }) } protected deleteTarget(target: StackingTarget) { @@ -100,6 +107,12 @@ export class StackerComponent implements AfterViewInit { } } + private async closeFrameWindow() { + if (this.frameId) { + await this.electronService.closeWindow(undefined, this.frameId) + } + } + protected async startStacking() { const settings = this.preferenceService.settings.get() diff --git a/desktop/src/assets/icons/calibration.png b/desktop/src/assets/icons/calibration.png new file mode 100644 index 0000000000000000000000000000000000000000..77f50c6ae1a95cc59e43e14ace9097b3b5ea8f11 GIT binary patch literal 862 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=EX7WqAsj$Z!;#Vf4nJ zFx~)R#$PeZihzQWC9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NHH)l-S%{G z45^s&cD8S}aG*%r{p$2tTRc}AE?c^G$A&OXuBcT?9gD1&+8>y^;GIiMSHK0OrWZ~w z7hCHO_=-1ii#I87G$nCg6=TufqG`I)H#2Fnr&0WI->FK%Mdsfes^^6!$epWw&pr7} ziiCpzi=)6comc1EWAv`S+;vdVVWoy4$1Cd?^E=5#TcXyM?p}92@sU{f(O9*(wQ=3k zwf%N?&i+5sKSZlfw$w*+QHj>)7q6zCKHspF>De=}Jcd_h4Hb(Q&U=2aP-gPijhlj8 z)`poD74MugF}zUb2{)_q_s>sMK6Q8V_G_;#Oewff`|F3}opWj8dV(vf-6orJinRSO zF%;ZwXS8ck=NFE01-)a(j|WRFuzRNv6C%Sd)$ok(5Zgtudw-;Y7|I#)mN2|yxZ}Zi zhjGV5rX9=$%B%(K58SvO@EzzCIUw60t=VABU=CKet%kAe(@$^X&3n80m=*ubpc*$^EXIIf7bCJj^F=*ie4oPeZZV|LnW|Nf+$mpv1AKlNusI1AzajkV5!!5qG6+rBX?WYjfg3LfOQ5r~?# zORtjS?S+h5*V2YryQh6h^k0-`Vj`=zcz={p(cz=b2eQJ0^%*{tE&KV5QQ_jFBs0V8 zC+qb7Glb3F&G_%Srahw}c&~;yifc%1Y zKN8p9PiZvoyjF5;lhnTI4f9rB>NFG1x9(bXeg1ZzJ2{q%>nblMi#FVqef9Tlbh+QG hGeW?W*5Z36UwrwqPrtk~6M=bw!PC{xWt~$(698CEb@KoK literal 0 HcmV?d00001 diff --git a/desktop/src/assets/icons/photo-filter.png b/desktop/src/assets/icons/photo-filter.png deleted file mode 100644 index d3f7a892d75eaa33910f5b86a1205413c173088f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1657 zcmV-<28Q{GP)fUJ9K`vTe0zr>rflbV^-C7Wprhc@fh_?%gn33gh(J$JvBpa6017eN!KDLR0u<`C_~|#a3&<`O z%L^uJmBjdo2;ZUd8>DpNJdUj~AXhe9u)RfxSZ81*8RjT4eg#0I9+g@$*oh$DPKc(l z)dB>Xc?VK8u#iOgVJ!JkG=hZr1dTcy5t_%A03q?1Y1=_jlHjQ%$`MpfP4jes2>TeO z8d5Zt*b<;qtV6?ZXr~dNLwRAEr}{|pXAEkQ#5hTq&(UeM9IFww1c-`!Zg{pB+BJE$ z5hHhsCuWnMSfZ5(yNGepLZrsno(J4k-k?d@hCanOs^g>4vz=Du^(jh@CjXaZpORsQ zsU}Jll8}w4AH>m2u*LHh9m;x2^gqa!tw^B|5=&?kuMidmQ!WJUR3^0p@$~Ie2PZB<+3&ekU$NH6TnqSI4M#=?2X%}oFSqdCd+@< zQcf1ffEbAVz@PC;0muM|*U z5ugr49Z(GvgM1c5J8;o_^)rMy0YnGL-5~CoFm40U<}9i-B97nC4c494K~w^LjvUFp zEY=5x$x)myb7Sq!VgW!Aswd$8EO84E{{VY{uw#G8NfUr#T9_yssb;!)l_ zS#C;x1gYuXDFl!pjsZWWJ)oK3J^}9g%sm855MY|m+#Dw^fam~r17<#Ra|#QdD;4`b}$>eJzt zb`Qa39{^qb3g@r-lJ3Ltj!?3>H{>B2i@%qS-pRW>-2+~_`gJ-x<|V8nD?_IwKVr(C zs|2V%RlxacIb+vqECvjWUH^VLkD8`T`un;K>nffP-)w3zv~x`t=m~izCGV8BUbt@1 zQouz5WCwJzGm|&eD?(6|A2qadO&9Qcbv}BtjdKk-#8d%5SHGlo!e0!^3Zj&k#;9+U z$OLOEpAR;!>Lw?{SWwpp08p|p%H|E@Z|&M0FSWt(zx}ORI>_4_B5bZm!hXOAuIU0( zQM^zm!#n<}mlhkHG+W12E#Q9gvUEP)GRV20pYl?bHOn3{0RSq>R4U4*PW;R@9}RaE zUanAidWpRO)b#>P$EDj|zW+G@!09VK4(%8uKg;^AldH#oMBHj04}Dk_-08M=Ht4Dr z(AMLprXgo+Dm)$ajd^tRgqgTmd-QApSr_ALg$$o$rNEVL-nCSp!nnwc6 zbO19=It6gu8JzG4HGKj|`95$vZT<`p9-%53{$2kAgN^?Ks#Ak>00000NkvXXu0mjf DMA+lo diff --git a/desktop/src/shared/components/menu-item/menu-item.component.ts b/desktop/src/shared/components/menu-item/menu-item.component.ts index 605102cd0..3d25971c2 100644 --- a/desktop/src/shared/components/menu-item/menu-item.component.ts +++ b/desktop/src/shared/components/menu-item/menu-item.component.ts @@ -44,6 +44,9 @@ export interface MenuItem { command?: (event: MenuItemCommandEvent) => void check?: (event: CheckboxChangeEvent) => void toggle?: (event: InputSwitchChangeEvent) => void + + styleClass?: string + iconClass?: string } export interface SlideMenuItem extends MenuItem { diff --git a/desktop/src/shared/pipes/path.pipe.ts b/desktop/src/shared/pipes/path.pipe.ts new file mode 100644 index 000000000..dd61d2ea5 --- /dev/null +++ b/desktop/src/shared/pipes/path.pipe.ts @@ -0,0 +1,26 @@ +import { Pipe, PipeTransform } from '@angular/core' +import * as path from 'path' + +export type PathCommand = 'normalize' | 'basename' | 'dirname' | 'extname' | 'namespaced' + +@Pipe({ name: 'path' }) +export class PathPipe implements PipeTransform { + transform(value: string | undefined, command: PathCommand) { + if (!value) return value + + switch (command) { + case 'normalize': + return path.normalize(value) + case 'basename': + return path.basename(value) + case 'dirname': + return path.dirname(value) + case 'extname': + return path.extname(value) + case 'namespaced': + return path.toNamespacedPath(value) + default: + return value + } + } +} diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts index 5cd060b33..4972131e5 100644 --- a/desktop/src/shared/services/api.service.ts +++ b/desktop/src/shared/services/api.service.ts @@ -3,7 +3,7 @@ import moment from 'moment' import { DARVStart, TPPAStart } from '../types/alignment.types' import { Angle, BodyPosition, CloseApproach, ComputedLocation, Constellation, DeepSkyObject, MinorPlanet, Satellite, SatelliteGroupType, SkyObjectType, Twilight } from '../types/atlas.types' import { AutoFocusRequest } from '../types/autofocus.type' -import { CalibrationFrame, CalibrationFrameGroup } from '../types/calibration.types' +import { CalibrationFrame } from '../types/calibration.types' import { Camera, CameraStartCapture } from '../types/camera.types' import { Device, INDIProperty, INDISendProperty } from '../types/device.types' import { FlatWizardRequest } from '../types/flat-wizard.types' @@ -576,7 +576,7 @@ export class ApiService { } calibrationFrames(name: string) { - return this.http.get(`calibration-frames/${name}`) + return this.http.get(`calibration-frames/${name}`) } uploadCalibrationFrame(name: string, path: string) { @@ -584,9 +584,8 @@ export class ApiService { return this.http.put(`calibration-frames/${name}?${query}`) } - editCalibrationFrame(frame: CalibrationFrame) { - const query = this.http.query({ name: frame.name, enabled: frame.enabled }) - return this.http.patch(`calibration-frames/${frame.id}?${query}`) + updateCalibrationFrame(frame: CalibrationFrame) { + return this.http.post('calibration-frames', frame) } deleteCalibrationFrame(frame: CalibrationFrame) { diff --git a/desktop/src/shared/services/browser-window.service.ts b/desktop/src/shared/services/browser-window.service.ts index 0b2b1d638..ff3724398 100644 --- a/desktop/src/shared/services/browser-window.service.ts +++ b/desktop/src/shared/services/browser-window.service.ts @@ -139,7 +139,7 @@ export class BrowserWindowService { } openCalibration(preference: WindowPreference = {}) { - Object.assign(preference, { icon: 'photo-filter', width: 420, height: 400, minHeight: 400 }) + Object.assign(preference, { icon: 'calibration', width: 370, height: 442, minHeight: 400 }) return this.openWindow({ preference, id: 'calibration', path: 'calibration' }) } diff --git a/desktop/src/shared/services/preference.service.ts b/desktop/src/shared/services/preference.service.ts index 832b42255..f0635a816 100644 --- a/desktop/src/shared/services/preference.service.ts +++ b/desktop/src/shared/services/preference.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core' import { AlignmentPreference, alignmentPreferenceWithDefault, DEFAULT_ALIGNMENT_PREFERENCE } from '../types/alignment.types' import { DEFAULT_SKY_ATLAS_PREFERENCE, SkyAtlasPreference } from '../types/atlas.types' import { AutoFocusPreference, autoFocusPreferenceWithDefault, DEFAULT_AUTO_FOCUS_PREFERENCE } from '../types/autofocus.type' -import { CalibrationPreference } from '../types/calibration.types' +import { CalibrationPreference, calibrationPreferenceWithDefault, DEFAULT_CALIBRATION_PREFERENCE } from '../types/calibration.types' import { Camera, CameraPreference, cameraPreferenceWithDefault, DEFAULT_CAMERA_PREFERENCE } from '../types/camera.types' import { DEFAULT_FLAT_WIZARD_PREFERENCE, FlatWizardPreference, flatWizardPreferenceWithDefault } from '../types/flat-wizard.types' import { DEFAULT_FOCUSER_PREFERENCE, Focuser, FocuserPreference, focuserPreferenceWithDefault } from '../types/focuser.types' @@ -86,7 +86,7 @@ export class PreferenceService { readonly skyAtlasPreference = new PreferenceData(this.storage, 'atlas', () => structuredClone(DEFAULT_SKY_ATLAS_PREFERENCE)) readonly alignment = new PreferenceData(this.storage, 'alignment', () => structuredClone(DEFAULT_ALIGNMENT_PREFERENCE), alignmentPreferenceWithDefault) readonly imageFOVs = new PreferenceData(this.storage, 'image.fovs', () => []) - readonly calibrationPreference = new PreferenceData(this.storage, 'calibration', () => ({}) as CalibrationPreference) + readonly calibrationPreference = new PreferenceData(this.storage, 'calibration', () => structuredClone(DEFAULT_CALIBRATION_PREFERENCE), calibrationPreferenceWithDefault) readonly sequencerPreference = new PreferenceData(this.storage, 'sequencer', () => structuredClone(DEFAULT_SEQUENCER_PREFERENCE)) readonly stacker = new PreferenceData(this.storage, 'stacker', () => structuredClone(DEFAULT_STACKER_PREFERENCE), stackerPreferenceWithDefault) readonly guider = new PreferenceData(this.storage, 'guider', () => structuredClone(DEFAULT_GUIDER_PREFERENCE), guiderPreferenceWithDefault) diff --git a/desktop/src/shared/types/calibration.types.ts b/desktop/src/shared/types/calibration.types.ts index 51b3c445f..e5b798708 100644 --- a/desktop/src/shared/types/calibration.types.ts +++ b/desktop/src/shared/types/calibration.types.ts @@ -1,28 +1,33 @@ -import type { FrameType } from './camera.types' +import type { Image } from './image.types' -export interface CalibrationFrame { +export interface CalibrationFrame extends Image { id: number - type: FrameType - name: string - filter?: string - exposureTime: number - temperature: number - width: number - height: number - binX: number - binY: number - gain: number + group: string path: string enabled: boolean } -export interface CalibrationFrameGroup { - id: number - name: string - key: Omit - frames: CalibrationFrame[] +export interface CalibrationGroupDialog { + showDialog: boolean + group: string + save?: () => Promise | void } export interface CalibrationPreference { - openPath?: string + filePath?: string + directoryPath?: string +} + +export const DEFAULT_CALIBRATION_GROUP_DIALOG: CalibrationGroupDialog = { + showDialog: false, + group: '', +} + +export const DEFAULT_CALIBRATION_PREFERENCE: CalibrationPreference = {} + +export function calibrationPreferenceWithDefault(preference?: Partial, source: CalibrationPreference = DEFAULT_CALIBRATION_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.filePath ||= source.filePath + preference.directoryPath ||= source.directoryPath + return preference as CalibrationPreference } diff --git a/desktop/src/shared/types/home.types.ts b/desktop/src/shared/types/home.types.ts index 98ce89892..5004688fb 100644 --- a/desktop/src/shared/types/home.types.ts +++ b/desktop/src/shared/types/home.types.ts @@ -1,6 +1,6 @@ import type { DeviceType } from './device.types' -export type HomeWindowType = DeviceType | 'GUIDER' | 'SKY_ATLAS' | 'ALIGNMENT' | 'SEQUENCER' | 'IMAGE' | 'FRAMING' | 'INDI' | 'SETTINGS' | 'CALCULATOR' | 'ABOUT' | 'FLAT_WIZARD' | 'AUTO_FOCUS' | 'STACKER' +export type HomeWindowType = DeviceType | 'GUIDER' | 'SKY_ATLAS' | 'ALIGNMENT' | 'SEQUENCER' | 'IMAGE' | 'FRAMING' | 'INDI' | 'SETTINGS' | 'CALCULATOR' | 'ABOUT' | 'FLAT_WIZARD' | 'AUTO_FOCUS' | 'STACKER' | 'CALIBRATION' export type ConnectionType = 'INDI' | 'ALPACA' diff --git a/desktop/src/shared/types/image.types.ts b/desktop/src/shared/types/image.types.ts index d18844f8e..2da2f3a1f 100644 --- a/desktop/src/shared/types/image.types.ts +++ b/desktop/src/shared/types/image.types.ts @@ -1,6 +1,6 @@ import type { Point, Size } from 'electron' import type { Angle, AstronomicalObject, DeepSkyObject, EquatorialCoordinateJ2000, Star } from './atlas.types' -import type { Camera, CameraStartCapture } from './camera.types' +import type { Camera, CameraStartCapture, FrameType } from './camera.types' import type { PlateSolverRequest } from './platesolver.types' import type { StarDetectionRequest } from './stardetector.types' @@ -16,6 +16,18 @@ export type Bitpix = 'BYTE' | 'SHORT' | 'INTEGER' | 'LONG' | 'FLOAT' | 'DOUBLE' export type LiveStackingMode = 'NONE' | 'RAW' | 'STACKED' +export interface Image { + type: FrameType + width: number + height: number + binX: number + binY: number + exposureTime: number + temperature?: number + gain: number + filter?: string +} + export interface FITSHeaderItem { name: string value: string diff --git a/desktop/src/styles.scss b/desktop/src/styles.scss index d8421db68..7339a0894 100644 --- a/desktop/src/styles.scss +++ b/desktop/src/styles.scss @@ -483,8 +483,8 @@ p-tieredmenu *, } ::-webkit-scrollbar { - width: 6px; - height: 6px; + width: 4px; + height: 4px; } ::-webkit-scrollbar-thumb { From cd63f3f69ce151511aa4cf8068885fef75e6b711 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 3 Aug 2024 00:09:33 -0300 Subject: [PATCH 088/104] [desktop]: Upgrade NPM dependencies --- desktop/package-lock.json | 3126 +++++++++++++++++++++++++++---------- 1 file changed, 2264 insertions(+), 862 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 0d5e86040..181e67c23 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -66,6 +66,7 @@ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -79,6 +80,7 @@ "resolved": "https://registry.npmjs.org/@angular-builders/common/-/common-2.0.0.tgz", "integrity": "sha512-O5YJc++DtJVJhqA/OomRKN2jGYzvU/YXtfrPAqcA9Is3Ob5jvV0L0JHSAjSw/KaLvk/FjBIqoRVcYdLp5LKddA==", "dev": true, + "license": "MIT", "dependencies": { "@angular-devkit/core": "^18.0.0", "ts-node": "^10.0.0", @@ -93,6 +95,7 @@ "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-18.0.0.tgz", "integrity": "sha512-XSynPSXHq5+nrh7J2snfrcbvm6YGwUGQRzr7OuO3wURJ6CHOD9C+xEAmvEUWW8c1YjEslVNG7aLtCGz7LA4ymw==", "dev": true, + "license": "MIT", "dependencies": { "@angular-builders/common": "2.0.0", "@angular-devkit/architect": ">=0.1800.0 < 0.1900.0", @@ -113,6 +116,7 @@ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1801.3.tgz", "integrity": "sha512-4yba7x315GKim7OuBgv89ZtG50hE3hw64KuRLSGuW+RvwcwLV24VanmdWmFiLC4RKYNSH13E0wZqDNJkrMQepw==", "dev": true, + "license": "MIT", "dependencies": { "@angular-devkit/core": "18.1.3", "rxjs": "7.8.1" @@ -128,6 +132,7 @@ "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.1.3.tgz", "integrity": "sha512-1avnneitUEfC2A9HX24X6a7Ag8sHkxomVEBsggITFNQoGnZAZHCOBRzm3b9QiqTi1c1eH3p8teW8EAufEjFPKQ==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", "@angular-devkit/architect": "0.1801.3", @@ -252,289 +257,12 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/@angular/build": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.1.3.tgz", - "integrity": "sha512-jmTQC7lecJ6c2mJobb5nY2CN6jvdeFFHXN/jif0RkNI8dP60uV1QdMKJtTGbxEtAKXdMgOTReYICVYl6m9Q56Q==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1801.3", - "@babel/core": "7.24.7", - "@babel/helper-annotate-as-pure": "7.24.7", - "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-syntax-import-attributes": "7.24.7", - "@inquirer/confirm": "3.1.11", - "@vitejs/plugin-basic-ssl": "1.1.0", - "ansi-colors": "4.1.3", - "browserslist": "^4.23.0", - "critters": "0.0.24", - "esbuild": "0.21.5", - "fast-glob": "3.3.2", - "https-proxy-agent": "7.0.5", - "lmdb": "3.0.12", - "magic-string": "0.30.10", - "mrmime": "2.0.0", - "ora": "5.4.1", - "parse5-html-rewriting-stream": "7.0.0", - "picomatch": "4.0.2", - "piscina": "4.6.1", - "rollup": "4.18.0", - "sass": "1.77.6", - "semver": "7.6.2", - "undici": "6.19.2", - "vite": "5.3.2", - "watchpack": "2.4.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "@angular/compiler-cli": "^18.0.0", - "@angular/localize": "^18.0.0", - "@angular/platform-server": "^18.0.0", - "@angular/service-worker": "^18.0.0", - "less": "^4.2.0", - "postcss": "^8.4.0", - "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.4 <5.6" - }, - "peerDependenciesMeta": { - "@angular/localize": { - "optional": true - }, - "@angular/platform-server": { - "optional": true - }, - "@angular/service-worker": { - "optional": true - }, - "less": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tailwindcss": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", - "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", - "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", - "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", - "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", - "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", - "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", - "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", - "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", - "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", - "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", - "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", - "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", - "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", - "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", - "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", - "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@angular-devkit/build-angular/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -551,6 +279,7 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, + "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } @@ -560,6 +289,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -573,6 +303,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -581,54 +312,22 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@angular-devkit/build-angular/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/rollup": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", - "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", "dev": true, - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.0", - "@rollup/rollup-android-arm64": "4.18.0", - "@rollup/rollup-darwin-arm64": "4.18.0", - "@rollup/rollup-darwin-x64": "4.18.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", - "@rollup/rollup-linux-arm-musleabihf": "4.18.0", - "@rollup/rollup-linux-arm64-gnu": "4.18.0", - "@rollup/rollup-linux-arm64-musl": "4.18.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", - "@rollup/rollup-linux-riscv64-gnu": "4.18.0", - "@rollup/rollup-linux-s390x-gnu": "4.18.0", - "@rollup/rollup-linux-x64-gnu": "4.18.0", - "@rollup/rollup-linux-x64-musl": "4.18.0", - "@rollup/rollup-win32-arm64-msvc": "4.18.0", - "@rollup/rollup-win32-ia32-msvc": "4.18.0", - "@rollup/rollup-win32-x64-msvc": "4.18.0", - "fsevents": "~2.3.2" - } + "license": "MIT" }, "node_modules/@angular-devkit/build-angular/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -647,6 +346,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz", "integrity": "sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==", "dev": true, + "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", @@ -694,6 +394,7 @@ "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1801.3.tgz", "integrity": "sha512-JezRR72P4QAc4mnkT60/+kVANCYNKcr2sZyX0/9aBHJsR7lIqgOKz5Dft3FgWHwAJcQFtsZ7OLGVOW3P1LpFkw==", "dev": true, + "license": "MIT", "dependencies": { "@angular-devkit/architect": "0.1801.3", "rxjs": "7.8.1" @@ -713,6 +414,7 @@ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.1.3.tgz", "integrity": "sha512-S0UzNNVLbHPaiSVXHjCd2wX+eERj/YR7jJCc40PHs1gINA7Gtd2q3VDm3bUEWe4P6fP6GNp43qSXmWJFQD0+Yg==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "8.16.0", "ajv-formats": "3.0.1", @@ -740,6 +442,7 @@ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.1.3.tgz", "integrity": "sha512-ElzCfiYW9P3xPRNRbPRSrOTGm+G7X8ta1ce3srqi00yPX39Y0WSM95SACqqF8j9dxL6BqazBMyAgNQUaVSbWjw==", "dev": true, + "license": "MIT", "dependencies": { "@angular-devkit/core": "18.1.3", "jsonc-parser": "3.3.1", @@ -757,6 +460,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.1.3.tgz", "integrity": "sha512-jF4jGHZxV/REnymB11wg5q/DMXewJ0byihmvNQ3OPLHGkWnvE9MdrX44vUzI7RkzqO0suaAg8shxJlkY3OHjeA==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -767,10 +471,82 @@ "@angular/core": "18.1.3" } }, + "node_modules/@angular/build": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.1.3.tgz", + "integrity": "sha512-jmTQC7lecJ6c2mJobb5nY2CN6jvdeFFHXN/jif0RkNI8dP60uV1QdMKJtTGbxEtAKXdMgOTReYICVYl6m9Q56Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "2.3.0", + "@angular-devkit/architect": "0.1801.3", + "@babel/core": "7.24.7", + "@babel/helper-annotate-as-pure": "7.24.7", + "@babel/helper-split-export-declaration": "7.24.7", + "@babel/plugin-syntax-import-attributes": "7.24.7", + "@inquirer/confirm": "3.1.11", + "@vitejs/plugin-basic-ssl": "1.1.0", + "ansi-colors": "4.1.3", + "browserslist": "^4.23.0", + "critters": "0.0.24", + "esbuild": "0.21.5", + "fast-glob": "3.3.2", + "https-proxy-agent": "7.0.5", + "lmdb": "3.0.12", + "magic-string": "0.30.10", + "mrmime": "2.0.0", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "picomatch": "4.0.2", + "piscina": "4.6.1", + "rollup": "4.18.0", + "sass": "1.77.6", + "semver": "7.6.2", + "undici": "6.19.2", + "vite": "5.3.2", + "watchpack": "2.4.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^18.0.0", + "@angular/localize": "^18.0.0", + "@angular/platform-server": "^18.0.0", + "@angular/service-worker": "^18.0.0", + "less": "^4.2.0", + "postcss": "^8.4.0", + "tailwindcss": "^2.0.0 || ^3.0.0", + "typescript": ">=5.4 <5.6" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/platform-server": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "less": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tailwindcss": { + "optional": true + } + } + }, "node_modules/@angular/cdk": { "version": "18.1.3", "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.1.3.tgz", "integrity": "sha512-u14xbuXQz+36nBeHSwRcwRoS64WNhOdK97H47nI1WaIZZaGGvKHR1Wwk2XletDRtIHv2622sJm8h+dbaBNeTGQ==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -788,6 +564,7 @@ "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.1.3.tgz", "integrity": "sha512-vsEc3cGDUYcc+adfvBHSqKdI8uiaa86Y9pLWGHfqaD+N0q/k17d/47AFvXTDKLmKucMZrto/4088Y1y+yM9eOg==", "dev": true, + "license": "MIT", "dependencies": { "@angular-devkit/architect": "0.1801.3", "@angular-devkit/core": "18.1.3", @@ -820,6 +597,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.1.3.tgz", "integrity": "sha512-TC71jVph4L+QaXlyJTrW27nbqis4sWwr9hD/RDSNkfY9XCvYDb2MjYjKrpbN03FWiv7lmcKT9zgse1fYENFsKQ==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -835,6 +613,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.1.3.tgz", "integrity": "sha512-Mrcd+YGsz02GVnVlVbzYp7EJIVoPOIHMvhll1OiylhjQElNVeJCLPIvjVYdylzOUDctXNlchkGf/LbA7BYMbXg==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -855,6 +634,7 @@ "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.1.3.tgz", "integrity": "sha512-e9t5v/L1KqPLUQL+WU+d70MBBFcSRuwqbkluZgdDjdW5VelYjzlVzXdrzV6jFElP48T3kQCxJN1dAJkAvKjdOg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "7.24.9", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -883,6 +663,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", @@ -912,13 +693,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -928,6 +711,7 @@ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.25.0", "@jridgewell/gen-mapping": "^0.3.5", @@ -942,6 +726,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.1.3.tgz", "integrity": "sha512-1tFTyGLwio5oYAP2sMVDiOvy5wl/v0a4om7RTCpP2Bjro0ynuYe8FK7ilcmdyPXR1DF7GVdo/0R/eCIQJZ2PwA==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -957,6 +742,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.1.3.tgz", "integrity": "sha512-4kic/9hpS0HkbTORIkrdox7K40EcVT9VIbBruPoxX7jbfiW5jFaJ/05hLRvRt9RF8Sd9G+g5Uohmkcq/5hmsng==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -975,6 +761,7 @@ "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.1.3.tgz", "integrity": "sha512-1s1VQHJ6Gh84lCqgSEU6pNuPBpvee1mhfIZEE2lqxFu/tLe5gqvtTescFaTFLWY6I4e2RGAOU8WtRnFgFNxzGg==", "dev": true, + "license": "MIT", "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0" } @@ -983,6 +770,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.1.3.tgz", "integrity": "sha512-/k5Xt/WjOk6OlRqb1Wd0ZUQ3NjSbafQyDC9Icy0Mb8qJtiXZjA4VCMkZIiQD7cBxO0F/BsAiYnYNjWrIkCZICA==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -1004,6 +792,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.1.3.tgz", "integrity": "sha512-VhYfyPcdKrsLrkd5Lq7W+pqE49DZBpUeCqM/Q+s9rhTSiCCKe9Ikktq8yPZ9iHDpFr203P+T1EMHmILnLvf+gQ==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -1021,6 +810,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.1.3.tgz", "integrity": "sha512-6fXiTgdUnaGGF32Un4+7LttG1N9rziansigvLBzFG//qYU0Ihk49phqDdWxz11iaJ+uK1YVafkjSFvV7z9cgDA==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -1039,6 +829,7 @@ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" @@ -1048,10 +839,11 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", - "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", + "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1061,6 +853,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", @@ -1090,13 +883,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -1106,6 +901,7 @@ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7", "@jridgewell/gen-mapping": "^0.3.5", @@ -1121,6 +917,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7" }, @@ -1133,6 +930,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -1142,12 +940,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", - "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.24.8", + "@babel/compat-data": "^7.25.2", "@babel/helper-validator-option": "^7.24.8", "browserslist": "^4.23.1", "lru-cache": "^5.1.1", @@ -1162,6 +961,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -1171,6 +971,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz", "integrity": "sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-member-expression-to-functions": "^7.24.8", @@ -1192,6 +993,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -1201,6 +1003,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", @@ -1218,6 +1021,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -1227,6 +1031,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -1243,6 +1048,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7" }, @@ -1255,6 +1061,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/traverse": "^7.24.8", "@babel/types": "^7.24.8" @@ -1268,6 +1075,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -1281,6 +1089,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", @@ -1299,6 +1108,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7" }, @@ -1311,6 +1121,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1320,6 +1131,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-wrap-function": "^7.25.0", @@ -1337,6 +1149,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-member-expression-to-functions": "^7.24.8", "@babel/helper-optimise-call-expression": "^7.24.7", @@ -1354,6 +1167,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -1367,6 +1181,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -1380,6 +1195,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7" }, @@ -1392,6 +1208,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1401,6 +1218,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1410,6 +1228,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1419,6 +1238,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.0", @@ -1429,13 +1249,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", - "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", + "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.8" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -1446,6 +1267,7 @@ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", @@ -1461,6 +1283,7 @@ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.25.2" }, @@ -1476,6 +1299,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/traverse": "^7.25.3" @@ -1492,6 +1316,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1507,6 +1332,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -1524,6 +1350,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/traverse": "^7.25.0" @@ -1540,6 +1367,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" }, @@ -1552,6 +1380,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1564,6 +1393,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -1576,6 +1406,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1591,6 +1422,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1603,6 +1435,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -1615,6 +1448,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1630,6 +1464,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1645,6 +1480,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1657,6 +1493,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1669,6 +1506,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1681,6 +1519,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1693,6 +1532,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1705,6 +1545,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1717,6 +1558,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1729,6 +1571,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1741,6 +1584,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1756,6 +1600,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1771,6 +1616,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1787,6 +1633,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1802,6 +1649,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1820,6 +1668,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1837,6 +1686,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1852,6 +1702,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1867,6 +1718,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1883,6 +1735,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1900,6 +1753,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz", "integrity": "sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-compilation-targets": "^7.24.8", @@ -1920,6 +1774,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/template": "^7.24.7" @@ -1936,6 +1791,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1951,6 +1807,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1967,6 +1824,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1982,6 +1840,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -1998,6 +1857,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -2014,6 +1874,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -2030,6 +1891,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -2046,6 +1908,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8", @@ -2063,6 +1926,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -2079,6 +1943,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -2094,6 +1959,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -2110,6 +1976,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2125,6 +1992,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -2141,6 +2009,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8", @@ -2158,6 +2027,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.0", "@babel/helper-plugin-utils": "^7.24.8", @@ -2176,6 +2046,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -2192,6 +2063,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -2208,6 +2080,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2223,6 +2096,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -2239,6 +2113,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" @@ -2255,6 +2130,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -2273,6 +2149,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-replace-supers": "^7.24.7" @@ -2289,6 +2166,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -2305,6 +2183,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -2322,6 +2201,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2337,6 +2217,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -2353,6 +2234,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-create-class-features-plugin": "^7.24.7", @@ -2371,6 +2253,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2386,6 +2269,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "regenerator-transform": "^0.15.2" @@ -2402,6 +2286,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2417,6 +2302,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -2437,6 +2323,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -2446,6 +2333,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2461,6 +2349,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -2477,6 +2366,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2492,6 +2382,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2507,6 +2398,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -2522,6 +2414,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2537,6 +2430,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -2553,6 +2447,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -2569,6 +2464,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -2585,6 +2481,7 @@ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.7.tgz", "integrity": "sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.24.7", "@babel/helper-compilation-targets": "^7.24.7", @@ -2680,6 +2577,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -2689,6 +2587,7 @@ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -2702,13 +2601,15 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/runtime": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", "dev": true, + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2721,6 +2622,7 @@ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/parser": "^7.25.0", @@ -2735,6 +2637,7 @@ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.0", @@ -2753,6 +2656,7 @@ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.25.0", "@jridgewell/gen-mapping": "^0.3.5", @@ -2768,6 +2672,7 @@ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", @@ -2781,6 +2686,7 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/@cfcs/core/-/core-0.0.6.tgz", "integrity": "sha512-FxfJMwoLB8MEMConeXUCqtMGqxdtePQxRBOiGip9ULcYYam3WfCgoY6xdnMaSkYvRvmosp5iuG+TiPofm65+Pw==", + "license": "MIT", "dependencies": { "@egjs/component": "^3.0.2" } @@ -2790,6 +2696,7 @@ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -2802,6 +2709,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -2810,13 +2718,15 @@ "node_modules/@daybrush/utils": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/@daybrush/utils/-/utils-1.13.0.tgz", - "integrity": "sha512-ALK12C6SQNNHw1enXK+UO8bdyQ+jaWNQ1Af7Z3FNxeAwjYhQT7do+TRE4RASAJ3ObaS2+TJ7TXR3oz2Gzbw0PQ==" + "integrity": "sha512-ALK12C6SQNNHw1enXK+UO8bdyQ+jaWNQ1Af7Z3FNxeAwjYhQT7do+TRE4RASAJ3ObaS2+TJ7TXR3oz2Gzbw0PQ==", + "license": "MIT" }, "node_modules/@develar/schema-utils": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.0", "ajv-keywords": "^3.4.1" @@ -2834,6 +2744,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2850,6 +2761,7 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, + "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } @@ -2858,13 +2770,15 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -2872,12 +2786,14 @@ "node_modules/@egjs/agent": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/@egjs/agent/-/agent-2.4.3.tgz", - "integrity": "sha512-XvksSENe8wPeFlEVouvrOhKdx8HMniJ3by7sro2uPF3M6QqWwjzVcmvwoPtdjiX8O1lfRoLhQMp1a7NGlVTdIA==" + "integrity": "sha512-XvksSENe8wPeFlEVouvrOhKdx8HMniJ3by7sro2uPF3M6QqWwjzVcmvwoPtdjiX8O1lfRoLhQMp1a7NGlVTdIA==", + "license": "MIT" }, "node_modules/@egjs/children-differ": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@egjs/children-differ/-/children-differ-1.0.1.tgz", "integrity": "sha512-DRvyqMf+CPCOzAopQKHtW+X8iN6Hy6SFol+/7zCUiE5y4P/OB8JP8FtU4NxtZwtafvSL4faD5KoQYPj3JHzPFQ==", + "license": "MIT", "dependencies": { "@egjs/list-differ": "^1.0.0" } @@ -2885,18 +2801,21 @@ "node_modules/@egjs/component": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@egjs/component/-/component-3.0.5.tgz", - "integrity": "sha512-cLcGizTrrUNA2EYE3MBmEDt2tQv1joVP1Q3oDisZ5nw0MZDx2kcgEXM+/kZpfa/PAkFvYVhRUZwytIQWoN3V/w==" + "integrity": "sha512-cLcGizTrrUNA2EYE3MBmEDt2tQv1joVP1Q3oDisZ5nw0MZDx2kcgEXM+/kZpfa/PAkFvYVhRUZwytIQWoN3V/w==", + "license": "MIT" }, "node_modules/@egjs/list-differ": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@egjs/list-differ/-/list-differ-1.0.1.tgz", - "integrity": "sha512-OTFTDQcWS+1ZREOdCWuk5hCBgYO4OsD30lXcOCyVOAjXMhgL5rBRDnt/otb6Nz8CzU0L/igdcaQBDLWc4t9gvg==" + "integrity": "sha512-OTFTDQcWS+1ZREOdCWuk5hCBgYO4OsD30lXcOCyVOAjXMhgL5rBRDnt/otb6Nz8CzU0L/igdcaQBDLWc4t9gvg==", + "license": "MIT" }, "node_modules/@electron/asar": { "version": "3.2.10", "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.10.tgz", "integrity": "sha512-mvBSwIBUeiRscrCeJE1LwctAriBj65eUDm0Pc11iE5gRwzkmsdbS7FnZ1XUWjpSeQWL1L5g12Fc/SchPM9DUOw==", "dev": true, + "license": "MIT", "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", @@ -2914,6 +2833,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2924,6 +2844,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2936,6 +2857,7 @@ "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", @@ -2957,6 +2879,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -2966,6 +2889,7 @@ "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.1", @@ -2980,6 +2904,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -2995,6 +2920,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -3007,6 +2933,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -3016,6 +2943,7 @@ "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", @@ -3037,6 +2965,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -3051,6 +2980,7 @@ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8.0.0" }, @@ -3063,6 +2993,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -3075,6 +3006,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -3084,6 +3016,7 @@ "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", "dev": true, + "license": "MIT", "dependencies": { "@electron/asar": "^3.2.1", "@malept/cross-spawn-promise": "^1.1.0", @@ -3102,6 +3035,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3112,6 +3046,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -3127,6 +3062,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -3139,6 +3075,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3151,6 +3088,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -3163,6 +3101,7 @@ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" @@ -3179,6 +3118,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -3195,6 +3135,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -3211,6 +3152,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -3227,6 +3169,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -3243,6 +3186,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -3259,6 +3203,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -3275,6 +3220,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -3291,6 +3237,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -3307,6 +3254,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -3323,6 +3271,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -3339,6 +3288,7 @@ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -3355,6 +3305,7 @@ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -3371,6 +3322,7 @@ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -3387,6 +3339,7 @@ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -3403,6 +3356,7 @@ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -3419,6 +3373,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -3435,6 +3390,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -3451,6 +3407,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -3467,6 +3424,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -3483,6 +3441,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -3499,6 +3458,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -3515,6 +3475,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -3528,6 +3489,7 @@ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -3538,11 +3500,25 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint-community/regexpp": { "version": "4.11.0", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -3552,6 +3528,7 @@ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.4", "debug": "^4.3.1", @@ -3566,6 +3543,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3576,6 +3554,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3588,6 +3567,7 @@ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -3611,6 +3591,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3627,6 +3608,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3637,6 +3619,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -3648,13 +3631,15 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3667,6 +3652,7 @@ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -3676,6 +3662,7 @@ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -3684,13 +3671,15 @@ "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@hapi/topo": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.0.0" } @@ -3700,6 +3689,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -3713,6 +3703,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -3722,14 +3713,15 @@ } }, "node_modules/@inquirer/checkbox": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.4.0.tgz", - "integrity": "sha512-XHOCmntitRBD8SJcrv+6X9YakxO1wfsvezOnU5MBIXeTlSBRCVk9DOIrx6Cgi9BS3qkcy7oQb+fUGEKrP6xecQ==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.4.5.tgz", + "integrity": "sha512-+YlCyS6JBWeZugIvReh/YL5HJcowlklz5RykQuYKQfgWQeCJh5Us0nWcRddvIVkjmYa0I/8bwWioSLu850J8sA==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/core": "^9.0.3", - "@inquirer/figures": "^1.0.4", - "@inquirer/type": "^1.5.0", + "@inquirer/core": "^9.0.8", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, @@ -3738,15 +3730,16 @@ } }, "node_modules/@inquirer/checkbox/node_modules/@inquirer/core": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.3.tgz", - "integrity": "sha512-p2BRZv/vMmpwlU4ZR966vKQzGVCi4VhLjVofwnFLziTQia541T7i1Ar8/LPh+LzjkXzocme+g5Io6MRtzlCcNA==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.8.tgz", + "integrity": "sha512-ttnI/BGlP9SxjbQnv1nssv7dPAwiR82KmjJZx2SxSZyi2mGbaEvh4jg0I4yU/4mVQf7QvCVGGr/hGuJFEYhwnw==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.4", - "@inquirer/type": "^1.5.0", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.14.11", + "@types/node": "^22.0.0", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "cli-spinners": "^2.9.2", @@ -3761,11 +3754,29 @@ "node": ">=18" } }, + "node_modules/@inquirer/checkbox/node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@inquirer/checkbox/node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true, + "license": "MIT" + }, "node_modules/@inquirer/confirm": { "version": "3.1.11", "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.11.tgz", "integrity": "sha512-3wWw10VPxQP279FO4bzWsf8YjIAq7NdwATJ4xS2h1uwsXZu/RmtOVV95rZ7yllS1h/dzu+uLewjMAzNDEj8h2w==", "dev": true, + "license": "MIT", "dependencies": { "@inquirer/core": "^8.2.4", "@inquirer/type": "^1.3.3" @@ -3779,6 +3790,7 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.4.tgz", "integrity": "sha512-7vsXSfxtrrbwMTirfaKwPcjqJy7pzeuF/bP62yo1NQrRJ5HjmMlrhZml/Ljm9ODc1RnbhJlTeSnCkjtFddKjwA==", "dev": true, + "license": "MIT", "dependencies": { "@inquirer/figures": "^1.0.3", "@inquirer/type": "^1.3.3", @@ -3799,13 +3811,14 @@ } }, "node_modules/@inquirer/editor": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.15.tgz", - "integrity": "sha512-UmtZnY36rGLS/4cCzvdRmk0xxsGgH2AsF0v1SSlBZ3C5JK/Bxm2gNW8fmUVzQ5vm8kpdWASXPapbUx4iV49ScA==", + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.20.tgz", + "integrity": "sha512-vtIN9NwXldX8SWbPt5biJhnTpHJCzF5nSymcv4hcOxiCrOpXmgOvFYGpAY729KODF+5e1OLqPbJ8ApiwPu/peQ==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/core": "^9.0.3", - "@inquirer/type": "^1.5.0", + "@inquirer/core": "^9.0.8", + "@inquirer/type": "^1.5.1", "external-editor": "^3.1.0" }, "engines": { @@ -3813,15 +3826,16 @@ } }, "node_modules/@inquirer/editor/node_modules/@inquirer/core": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.3.tgz", - "integrity": "sha512-p2BRZv/vMmpwlU4ZR966vKQzGVCi4VhLjVofwnFLziTQia541T7i1Ar8/LPh+LzjkXzocme+g5Io6MRtzlCcNA==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.8.tgz", + "integrity": "sha512-ttnI/BGlP9SxjbQnv1nssv7dPAwiR82KmjJZx2SxSZyi2mGbaEvh4jg0I4yU/4mVQf7QvCVGGr/hGuJFEYhwnw==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.4", - "@inquirer/type": "^1.5.0", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.14.11", + "@types/node": "^22.0.0", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "cli-spinners": "^2.9.2", @@ -3836,14 +3850,32 @@ "node": ">=18" } }, + "node_modules/@inquirer/editor/node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@inquirer/editor/node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true, + "license": "MIT" + }, "node_modules/@inquirer/expand": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.15.tgz", - "integrity": "sha512-aBnnrBw9vbFJROUlDCsbq8H/plX6JHfPwLmSphxaVqOR+b1hgLdw+oRhZkpcJhG2AZOlc8IKzGdZhji93gQg4w==", + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.20.tgz", + "integrity": "sha512-ruUTCUGKhe6TvDM3/gKjX9v7D5cWbiuawFE6aF/cFmNO79R/zMjrFFVoueDM8FRw8yXqnREb0jFkYF1LUxnDNA==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/core": "^9.0.3", - "@inquirer/type": "^1.5.0", + "@inquirer/core": "^9.0.8", + "@inquirer/type": "^1.5.1", "yoctocolors-cjs": "^2.1.2" }, "engines": { @@ -3851,15 +3883,16 @@ } }, "node_modules/@inquirer/expand/node_modules/@inquirer/core": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.3.tgz", - "integrity": "sha512-p2BRZv/vMmpwlU4ZR966vKQzGVCi4VhLjVofwnFLziTQia541T7i1Ar8/LPh+LzjkXzocme+g5Io6MRtzlCcNA==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.8.tgz", + "integrity": "sha512-ttnI/BGlP9SxjbQnv1nssv7dPAwiR82KmjJZx2SxSZyi2mGbaEvh4jg0I4yU/4mVQf7QvCVGGr/hGuJFEYhwnw==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.4", - "@inquirer/type": "^1.5.0", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.14.11", + "@types/node": "^22.0.0", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "cli-spinners": "^2.9.2", @@ -3874,38 +3907,58 @@ "node": ">=18" } }, + "node_modules/@inquirer/expand/node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@inquirer/expand/node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true, + "license": "MIT" + }, "node_modules/@inquirer/figures": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.4.tgz", - "integrity": "sha512-R7Gsg6elpuqdn55fBH2y9oYzrU/yKrSmIsDX4ROT51vohrECFzTf2zw9BfUbOW8xjfmM2QbVoVYdTwhrtEKWSQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz", + "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@inquirer/input": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.2.2.tgz", - "integrity": "sha512-VjkzYSVH0606nLi9HHiSb4QYs2idwRgneiMoFoTAIwQ1Qwx6OIDugOYLtLta3gP8AWZx7qUvgDtj+/SJuiiKuQ==", + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.2.7.tgz", + "integrity": "sha512-QFk31Gq4Wr+Ve9ilMiFGGrSjGZQBilV0cgTN1zubD98Bx65fsNrh8++Biy/9mjNKRaqHFbZBw5baAcQvOmW8OQ==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/core": "^9.0.3", - "@inquirer/type": "^1.5.0" + "@inquirer/core": "^9.0.8", + "@inquirer/type": "^1.5.1" }, "engines": { "node": ">=18" } }, "node_modules/@inquirer/input/node_modules/@inquirer/core": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.3.tgz", - "integrity": "sha512-p2BRZv/vMmpwlU4ZR966vKQzGVCi4VhLjVofwnFLziTQia541T7i1Ar8/LPh+LzjkXzocme+g5Io6MRtzlCcNA==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.8.tgz", + "integrity": "sha512-ttnI/BGlP9SxjbQnv1nssv7dPAwiR82KmjJZx2SxSZyi2mGbaEvh4jg0I4yU/4mVQf7QvCVGGr/hGuJFEYhwnw==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.4", - "@inquirer/type": "^1.5.0", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.14.11", + "@types/node": "^22.0.0", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "cli-spinners": "^2.9.2", @@ -3920,14 +3973,32 @@ "node": ">=18" } }, + "node_modules/@inquirer/input/node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@inquirer/input/node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true, + "license": "MIT" + }, "node_modules/@inquirer/password": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.15.tgz", - "integrity": "sha512-/JmiTtIcSYbZdPucEW5q2rhC71vGKPivm3LFqNDQEI6lJyffq7hlfKKFC+R1Qp19dMqkaG+O5L1XmcHpmlAUUQ==", + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.20.tgz", + "integrity": "sha512-il2TG7xDlfiLE3cnOCxfDfrwvsiSmXjVd26hvf4tdzHvdisgLiEjbN6mi51/TnlSQ+2Qc69+9jIq3ws93nhS2w==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/core": "^9.0.3", - "@inquirer/type": "^1.5.0", + "@inquirer/core": "^9.0.8", + "@inquirer/type": "^1.5.1", "ansi-escapes": "^4.3.2" }, "engines": { @@ -3935,15 +4006,16 @@ } }, "node_modules/@inquirer/password/node_modules/@inquirer/core": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.3.tgz", - "integrity": "sha512-p2BRZv/vMmpwlU4ZR966vKQzGVCi4VhLjVofwnFLziTQia541T7i1Ar8/LPh+LzjkXzocme+g5Io6MRtzlCcNA==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.8.tgz", + "integrity": "sha512-ttnI/BGlP9SxjbQnv1nssv7dPAwiR82KmjJZx2SxSZyi2mGbaEvh4jg0I4yU/4mVQf7QvCVGGr/hGuJFEYhwnw==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.4", - "@inquirer/type": "^1.5.0", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.14.11", + "@types/node": "^22.0.0", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "cli-spinners": "^2.9.2", @@ -3958,11 +4030,29 @@ "node": ">=18" } }, + "node_modules/@inquirer/password/node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@inquirer/password/node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true, + "license": "MIT" + }, "node_modules/@inquirer/prompts": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.0.7.tgz", "integrity": "sha512-GFcigCxJTKCH3aECzMIu4FhgLJWnFvMXzpI4CCSoELWFtkOOU2P+goYA61+OKpGrB8fPE7q6n8zAXBSlZRrHjQ==", "dev": true, + "license": "MIT", "dependencies": { "@inquirer/checkbox": "^2.3.7", "@inquirer/confirm": "^3.1.11", @@ -3978,13 +4068,14 @@ } }, "node_modules/@inquirer/rawlist": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.1.15.tgz", - "integrity": "sha512-zwU6aWDMyuQNiY5Z0iYXkxi7pliRFXqUmiS7vG6lAGxqcbOSptYgIxGJnd3AU4Y91N0Tbt57+koJL0S2p6vSkA==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.2.2.tgz", + "integrity": "sha512-U4OsvqjdLB6nmf5ZDshPYMq0b+qd6JWxTrvRTiMfwUY6cFxkR9YWKarLXFhndf7tawQ8f3DwU9P9wryDc2ESSA==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/core": "^9.0.3", - "@inquirer/type": "^1.5.0", + "@inquirer/core": "^9.0.8", + "@inquirer/type": "^1.5.1", "yoctocolors-cjs": "^2.1.2" }, "engines": { @@ -3992,15 +4083,16 @@ } }, "node_modules/@inquirer/rawlist/node_modules/@inquirer/core": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.3.tgz", - "integrity": "sha512-p2BRZv/vMmpwlU4ZR966vKQzGVCi4VhLjVofwnFLziTQia541T7i1Ar8/LPh+LzjkXzocme+g5Io6MRtzlCcNA==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.8.tgz", + "integrity": "sha512-ttnI/BGlP9SxjbQnv1nssv7dPAwiR82KmjJZx2SxSZyi2mGbaEvh4jg0I4yU/4mVQf7QvCVGGr/hGuJFEYhwnw==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.4", - "@inquirer/type": "^1.5.0", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.14.11", + "@types/node": "^22.0.0", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "cli-spinners": "^2.9.2", @@ -4015,15 +4107,33 @@ "node": ">=18" } }, + "node_modules/@inquirer/rawlist/node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@inquirer/rawlist/node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true, + "license": "MIT" + }, "node_modules/@inquirer/select": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.4.0.tgz", - "integrity": "sha512-iU1eRkHirVNs43zWk6anMIMKc7tCXlJ+I5DcpIV7JzMe+45TuPPOGGCgeGIkZ4xYJ3cXdFoh7GJpm84PNC8veg==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.4.5.tgz", + "integrity": "sha512-DbCthH3l7vrrK+Ewll3bgzxC3dzMle8xkWYta4if31p9NOmFNhZKhSfdYMjaOtGFBCUEwo4D5LMgN6sPKgUWIw==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/core": "^9.0.3", - "@inquirer/figures": "^1.0.4", - "@inquirer/type": "^1.5.0", + "@inquirer/core": "^9.0.8", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, @@ -4032,15 +4142,16 @@ } }, "node_modules/@inquirer/select/node_modules/@inquirer/core": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.3.tgz", - "integrity": "sha512-p2BRZv/vMmpwlU4ZR966vKQzGVCi4VhLjVofwnFLziTQia541T7i1Ar8/LPh+LzjkXzocme+g5Io6MRtzlCcNA==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.8.tgz", + "integrity": "sha512-ttnI/BGlP9SxjbQnv1nssv7dPAwiR82KmjJZx2SxSZyi2mGbaEvh4jg0I4yU/4mVQf7QvCVGGr/hGuJFEYhwnw==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.4", - "@inquirer/type": "^1.5.0", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.14.11", + "@types/node": "^22.0.0", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "cli-spinners": "^2.9.2", @@ -4055,11 +4166,29 @@ "node": ">=18" } }, + "node_modules/@inquirer/select/node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@inquirer/select/node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true, + "license": "MIT" + }, "node_modules/@inquirer/type": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.0.tgz", - "integrity": "sha512-L/UdayX9Z1lLN+itoTKqJ/X4DX5DaWu2Sruwt4XgZzMNv32x4qllbzMX4MbJlz0yxAQtU19UvABGOjmdq1u3qA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.1.tgz", + "integrity": "sha512-m3YgGQlKNS0BM+8AFiJkCsTqHEFCWn6s/Rqye3mYwvqY6LdfUv12eSwbsgNzrYyrLXiy7IrrjDLPysaSBwEfhw==", "dev": true, + "license": "MIT", "dependencies": { "mute-stream": "^1.0.0" }, @@ -4072,6 +4201,7 @@ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -4089,6 +4219,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4101,6 +4232,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4112,13 +4244,15 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -4136,6 +4270,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -4151,6 +4286,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -4168,6 +4304,7 @@ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4177,6 +4314,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -4191,6 +4329,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -4200,6 +4339,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -4209,6 +4349,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -4218,13 +4359,15 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "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, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -4235,6 +4378,7 @@ "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.0" }, @@ -4251,6 +4395,7 @@ "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/base64": "^1.1.1", "@jsonjoy.com/util": "^1.1.2", @@ -4273,6 +4418,7 @@ "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.0" }, @@ -4287,19 +4433,22 @@ "node_modules/@kurkle/color": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", - "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==", + "license": "MIT" }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@listr2/prompt-adapter-inquirer": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.13.tgz", "integrity": "sha512-nAl6teTt7EWSjttNavAnv3uFR3w3vPP3OTYmHyPNHzKhAj2NoBDHmbS3MGpvvO8KXXPASnHjEGrrKrdKTMKPnQ==", "dev": true, + "license": "MIT", "dependencies": { "@inquirer/type": "^1.3.3" }, @@ -4318,6 +4467,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -4331,6 +4481,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -4344,6 +4495,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -4357,6 +4509,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -4370,6 +4523,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -4383,6 +4537,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -4403,6 +4558,7 @@ "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" } ], + "license": "Apache-2.0", "dependencies": { "cross-spawn": "^7.0.1" }, @@ -4415,6 +4571,7 @@ "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.0", @@ -4430,6 +4587,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -4445,6 +4603,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -4457,6 +4616,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -4464,7 +4624,8 @@ "node_modules/@mdi/font": { "version": "7.4.47", "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", - "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==" + "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==", + "license": "Apache-2.0" }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { "version": "3.0.3", @@ -4474,6 +4635,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -4487,6 +4649,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -4500,6 +4663,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -4513,6 +4677,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -4526,6 +4691,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -4539,6 +4705,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -4549,6 +4716,7 @@ "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.1.3.tgz", "integrity": "sha512-VmqOO8CcXKL06anNYlL0OkrqIuBNZQu5n0YVP4z8oneJhDBqwK2++dK0WpcNyIFcg3HsQ7w3BuqUWJ4iPiWxEQ==", "dev": true, + "license": "MIT", "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", @@ -4565,6 +4733,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -4578,6 +4747,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -4587,6 +4757,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -4600,6 +4771,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", "dev": true, + "license": "ISC", "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", @@ -4616,6 +4788,7 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4" }, @@ -4628,6 +4801,7 @@ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -4640,13 +4814,15 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@npmcli/fs": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", "dev": true, + "license": "ISC", "dependencies": { "semver": "^7.3.5" }, @@ -4659,6 +4835,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.8.tgz", "integrity": "sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/promise-spawn": "^7.0.0", "ini": "^4.1.3", @@ -4679,6 +4856,7 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=16" } @@ -4687,13 +4865,15 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@npmcli/git/node_modules/which": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -4709,6 +4889,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz", "integrity": "sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==", "dev": true, + "license": "ISC", "dependencies": { "npm-bundled": "^3.0.0", "npm-normalize-package-bin": "^3.0.0" @@ -4725,6 +4906,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -4734,6 +4916,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.2.0.tgz", "integrity": "sha512-qe/kiqqkW0AGtvBjL8TJKZk/eBBSpnJkUWvHdQ9jM2lKHXRYYJuyNpJPlJw3c8QjC2ow6NZYiLExhUaeJelbxQ==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/git": "^5.0.0", "glob": "^10.2.2", @@ -4752,6 +4935,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -4772,6 +4956,7 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^10.0.1" }, @@ -4783,13 +4968,15 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@npmcli/package-json/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -4805,6 +4992,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", "dev": true, + "license": "ISC", "dependencies": { "which": "^4.0.0" }, @@ -4817,6 +5005,7 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=16" } @@ -4826,6 +5015,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -4841,6 +5031,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-2.0.1.tgz", "integrity": "sha512-YgsR5jCQZhVmTJvjduTOIHph0L73pK8xwMVaDY0PatySqVM9AZj93jpoXYSJqfHFxFkN9dmqTw6OiqExsS3LPw==", "dev": true, + "license": "ISC", "engines": { "node": "^16.14.0 || >=18.0.0" } @@ -4850,6 +5041,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-8.1.0.tgz", "integrity": "sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/node-gyp": "^3.0.0", "@npmcli/package-json": "^5.0.0", @@ -4867,6 +5059,7 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=16" } @@ -4876,6 +5069,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -4891,214 +5085,231 @@ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=14" } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.2.tgz", - "integrity": "sha512-OHflWINKtoCFSpm/WmuQaWW4jeX+3Qt3XQDepkkiFTsoxFc5BpF3Z5aDxFZgBqRjO6ATP5+b1iilp4kGIZVWlA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.2.tgz", - "integrity": "sha512-k0OC/b14rNzMLDOE6QMBCjDRm3fQOHAL8Ldc9bxEWvMo4Ty9RY6rWmGetNTWhPo+/+FNd1lsQYRd0/1OSix36A==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.2.tgz", - "integrity": "sha512-IIARRgWCNWMTeQH+kr/gFTHJccKzwEaI0YSvtqkEBPj7AshElFq89TyreKNFAGh5frLfDCbodnq+Ye3dqGKPBw==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.2.tgz", - "integrity": "sha512-52udDMFDv54BTAdnw+KXNF45QCvcJOcYGl3vQkp4vARyrcdI/cXH8VXTEv/8QWfd6Fru8QQuw1b2uNersXOL0g==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.2.tgz", - "integrity": "sha512-r+SI2t8srMPYZeoa1w0o/AfoVt9akI1ihgazGYPQGRilVAkuzMGiTtexNZkrPkQsyFrvqq/ni8f3zOnHw4hUbA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.2.tgz", - "integrity": "sha512-+tYiL4QVjtI3KliKBGtUU7yhw0GMcJJuB9mLTCEauHEsqfk49gtUBXGtGP3h1LW8MbaTY6rSFIQV1XOBps1gBA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.2.tgz", - "integrity": "sha512-OR5DcvZiYN75mXDNQQxlQPTv4D+uNCUsmSCSY2FolLf9W5I4DSoJyg7z9Ea3TjKfhPSGgMJiey1aWvlWuBzMtg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.2.tgz", - "integrity": "sha512-Hw3jSfWdUSauEYFBSFIte6I8m6jOj+3vifLg8EU3lreWulAUpch4JBjDMtlKosrBzkr0kwKgL9iCfjA8L3geoA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.2.tgz", - "integrity": "sha512-rhjvoPBhBwVnJRq/+hi2Q3EMiVF538/o9dBuj9TVLclo9DuONqt5xfWSaE6MYiFKpo/lFPJ/iSI72rYWw5Hc7w==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.2.tgz", - "integrity": "sha512-EAz6vjPwHHs2qOCnpQkw4xs14XJq84I81sDRGPEjKPFVPBw7fwvtwhVjcZR6SLydCv8zNK8YGFblKWd/vRmP8g==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.2.tgz", - "integrity": "sha512-IJSUX1xb8k/zN9j2I7B5Re6B0NNJDJ1+soezjNojhT8DEVeDNptq2jgycCOpRhyGj0+xBn7Cq+PK7Q+nd2hxLA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.2.tgz", - "integrity": "sha512-OgaToJ8jSxTpgGkZSkwKE+JQGihdcaqnyHEFOSAU45utQ+yLruE1dkonB2SDI8t375wOKgNn8pQvaWY9kPzxDQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.2.tgz", - "integrity": "sha512-5V3mPpWkB066XZZBgSd1lwozBk7tmOkKtquyCJ6T4LN3mzKENXyBwWNQn8d0Ci81hvlBw5RoFgleVpL6aScLYg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.2.tgz", - "integrity": "sha512-ayVstadfLeeXI9zUPiKRVT8qF55hm7hKa+0N1V6Vj+OTNFfKSoUxyZvzVvgtBxqSb5URQ8sK6fhwxr9/MLmxdA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.2.tgz", - "integrity": "sha512-Mda7iG4fOLHNsPqjWSjANvNZYoW034yxgrndof0DwCy0D3FvTjeNo+HGE6oGWgvcLZNLlcp0hLEFcRs+UGsMLg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.2.tgz", - "integrity": "sha512-DPi0ubYhSow/00YqmG1jWm3qt1F8aXziHc/UNy8bo9cpCacqhuWu+iSq/fp2SyEQK7iYTZ60fBU9cat3MXTjIQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -5108,6 +5319,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/@scena/dragscroll/-/dragscroll-1.4.0.tgz", "integrity": "sha512-3O8daaZD9VXA9CP3dra6xcgt/qrm0mg0xJCwiX6druCteQ9FFsXffkF8PrqxY4Z4VJ58fFKEa0RlKqbsi/XnRA==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.6.0", "@scena/event-emitter": "^1.0.2" @@ -5117,6 +5329,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@scena/event-emitter/-/event-emitter-1.0.5.tgz", "integrity": "sha512-AzY4OTb0+7ynefmWFQ6hxDdk0CySAq/D4efljfhtRHCOP7MBF9zUfhKG3TJiroVjASqVgkRJFdenS8ArZo6Olg==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.1.1" } @@ -5125,6 +5338,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@scena/matrix/-/matrix-1.1.1.tgz", "integrity": "sha512-JVKBhN0tm2Srl+Yt+Ywqu0oLgLcdemDQlD1OxmN9jaCTwaFPZ7tY8n6dhVgMEaR9qcR7r+kAlMXnSfNyYdE+Vg==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.4.0" } @@ -5134,6 +5348,7 @@ "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.1.3.tgz", "integrity": "sha512-VyoL7O+3eL+BazmoWzexFpVy9k0MoOAmff3XqKLhP3/V7eXPc9s7znIDpPp28QF0V/Y2xMaGDWhqTx2CFcz4Qg==", "dev": true, + "license": "MIT", "dependencies": { "@angular-devkit/core": "18.1.3", "@angular-devkit/schematics": "18.1.3", @@ -5150,6 +5365,7 @@ "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.0.0" } @@ -5158,19 +5374,22 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@sideway/pinpoint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@sigstore/bundle": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.3.2.tgz", "integrity": "sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.3.2" }, @@ -5183,6 +5402,7 @@ "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.1.0.tgz", "integrity": "sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^16.14.0 || >=18.0.0" } @@ -5192,6 +5412,7 @@ "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.2.tgz", "integrity": "sha512-c6B0ehIWxMI8wiS/bj6rHMPqeFvngFV7cDU/MY+B16P9Z3Mp9k8L93eYZ7BYzSickzuqAQqAq0V956b3Ju6mLw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^16.14.0 || >=18.0.0" } @@ -5201,6 +5422,7 @@ "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.3.2.tgz", "integrity": "sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^2.3.2", "@sigstore/core": "^1.0.0", @@ -5218,6 +5440,7 @@ "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.4.tgz", "integrity": "sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.3.2", "tuf-js": "^2.2.1" @@ -5231,6 +5454,7 @@ "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.2.1.tgz", "integrity": "sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^2.3.2", "@sigstore/core": "^1.1.0", @@ -5245,6 +5469,7 @@ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -5257,6 +5482,7 @@ "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -5269,6 +5495,7 @@ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "dev": true, + "license": "MIT", "dependencies": { "defer-to-connect": "^2.0.0" }, @@ -5281,6 +5508,7 @@ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } @@ -5289,31 +5517,36 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tufjs/canonical-json": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", "dev": true, + "license": "MIT", "engines": { "node": "^16.14.0 || >=18.0.0" } @@ -5323,6 +5556,7 @@ "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.1.tgz", "integrity": "sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==", "dev": true, + "license": "MIT", "dependencies": { "@tufjs/canonical-json": "2.0.0", "minimatch": "^9.0.4" @@ -5336,6 +5570,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5351,6 +5586,7 @@ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "dev": true, + "license": "MIT", "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -5361,6 +5597,7 @@ "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5370,6 +5607,7 @@ "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", "dev": true, + "license": "MIT", "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", @@ -5382,6 +5620,7 @@ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5391,6 +5630,7 @@ "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", "dev": true, + "license": "MIT", "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" @@ -5401,15 +5641,17 @@ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/ms": "*" } }, "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -5420,6 +5662,7 @@ "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz", "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==", "dev": true, + "license": "MIT", "dependencies": { "@types/eslint": "*" } @@ -5429,6 +5672,7 @@ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, + "license": "MIT", "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -5438,13 +5682,15 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -5457,6 +5703,7 @@ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -5469,6 +5716,7 @@ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5477,25 +5725,29 @@ "version": "7946.0.14", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/http-cache-semantics": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/http-proxy": { "version": "1.17.14", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5504,13 +5756,15 @@ "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 + "dev": true, + "license": "MIT" }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5520,6 +5774,7 @@ "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz", "integrity": "sha512-BK7XS+NyRI291HIo0HCfE18Lp8oA30H1gpi1tf0mF3TgiCEzanQjOqNZ4x126SXzzi2oNSZhZ5axJp1k0iM6jg==", "dev": true, + "license": "MIT", "dependencies": { "@types/geojson": "*" } @@ -5528,19 +5783,22 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/ms": { "version": "0.7.34", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/mute-stream": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5550,6 +5808,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", "dev": true, + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } @@ -5559,6 +5818,7 @@ "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5568,6 +5828,7 @@ "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "@types/node": "*", @@ -5578,19 +5839,22 @@ "version": "6.9.15", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/responselike": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5599,13 +5863,15 @@ "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dev": true, + "license": "MIT", "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -5616,6 +5882,7 @@ "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", "dev": true, + "license": "MIT", "dependencies": { "@types/express": "*" } @@ -5625,6 +5892,7 @@ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "dev": true, + "license": "MIT", "dependencies": { "@types/http-errors": "*", "@types/node": "*", @@ -5636,6 +5904,7 @@ "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5645,19 +5914,22 @@ "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.10.tgz", "integrity": "sha512-l4MM0Jppn18hb9xmM6wwD1uTdShpf9Pn80aXTStnK1C94gtPvJcV2FrDmbOQUAQfJ1cKZHktkQUDwEqaAKXMMg==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/@types/wrap-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/ws": { "version": "8.5.12", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5667,6 +5939,7 @@ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "@types/node": "*" @@ -5677,6 +5950,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0.tgz", "integrity": "sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.0.0", @@ -5710,6 +5984,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.0.tgz", "integrity": "sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "8.0.0", "@typescript-eslint/types": "8.0.0", @@ -5738,6 +6013,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0.tgz", "integrity": "sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "8.0.0", "@typescript-eslint/visitor-keys": "8.0.0" @@ -5755,6 +6031,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.0.tgz", "integrity": "sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/typescript-estree": "8.0.0", "@typescript-eslint/utils": "8.0.0", @@ -5779,6 +6056,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0.tgz", "integrity": "sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -5792,6 +6070,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0.tgz", "integrity": "sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "8.0.0", "@typescript-eslint/visitor-keys": "8.0.0", @@ -5820,6 +6099,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -5840,6 +6120,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5855,6 +6136,7 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5864,6 +6146,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0.tgz", "integrity": "sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.0.0", @@ -5886,6 +6169,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0.tgz", "integrity": "sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "8.0.0", "eslint-visitor-keys": "^3.4.3" @@ -5898,11 +6182,25 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@vitejs/plugin-basic-ssl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", "integrity": "sha512-wO4Dk/rm8u7RNhOf95ZzcEmC9rYOncYgvq4z3duaJrCgjN8BxAnDVyndanfcJZ0O6XZzHz6Q0hTimxTg8Y9g/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.6.0" }, @@ -5915,6 +6213,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -5924,25 +6223,29 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -5953,13 +6256,15 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -5972,6 +6277,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -5981,6 +6287,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } @@ -5989,13 +6296,15 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -6012,6 +6321,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -6025,6 +6335,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -6037,6 +6348,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", @@ -6051,6 +6363,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" @@ -6061,6 +6374,7 @@ "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -6069,31 +6383,36 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/7zip-bin": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/abbrev": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -6103,6 +6422,7 @@ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "dev": true, + "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" }, @@ -6115,6 +6435,7 @@ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -6128,6 +6449,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -6140,6 +6462,7 @@ "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^8" } @@ -6149,6 +6472,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -6158,6 +6482,7 @@ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", "dev": true, + "license": "MIT", "dependencies": { "acorn": "^8.11.0" }, @@ -6170,6 +6495,7 @@ "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", "dev": true, + "license": "MIT", "dependencies": { "loader-utils": "^2.0.0", "regex-parser": "^2.2.11" @@ -6183,6 +6509,7 @@ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, + "license": "MIT", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -6197,6 +6524,7 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, + "license": "MIT", "dependencies": { "debug": "4" }, @@ -6209,6 +6537,7 @@ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, + "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -6222,6 +6551,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", @@ -6238,6 +6568,7 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -6255,6 +6586,7 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -6266,6 +6598,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/amator/-/amator-1.1.0.tgz", "integrity": "sha512-V5+aH8pe+Z3u/UG3L3pG3BaFQGXAyXHVQDroRwjPHdh08bcUEchAVsU1MCuJSCaU5o60wTK6KaE6te5memzgYw==", + "license": "MIT", "dependencies": { "bezier-easing": "^2.0.3" } @@ -6275,6 +6608,7 @@ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -6284,6 +6618,7 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -6302,6 +6637,7 @@ "engines": [ "node >= 0.8.0" ], + "license": "Apache-2.0", "bin": { "ansi-html": "bin/ansi-html" } @@ -6311,6 +6647,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6320,6 +6657,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -6332,6 +6670,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -6345,6 +6684,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -6356,13 +6696,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/app-builder-lib": { "version": "24.13.3", "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", "dev": true, + "license": "MIT", "dependencies": { "@develar/schema-utils": "~2.6.5", "@electron/notarize": "2.2.1", @@ -6405,6 +6747,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -6419,6 +6762,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -6431,6 +6775,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -6440,6 +6785,7 @@ "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -6459,6 +6805,7 @@ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "glob": "^7.1.4", @@ -6481,6 +6828,7 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/archiver-utils/node_modules/readable-stream": { @@ -6488,6 +6836,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "core-util-is": "~1.0.0", @@ -6504,6 +6853,7 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/archiver-utils/node_modules/string_decoder": { @@ -6511,6 +6861,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "safe-buffer": "~5.1.0" @@ -6520,19 +6871,22 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -6548,13 +6902,15 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6564,6 +6920,7 @@ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -6586,6 +6943,7 @@ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dev": true, + "license": "MIT", "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", @@ -6596,13 +6954,15 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/assert": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "is-nan": "^1.3.2", @@ -6616,6 +6976,7 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.8" @@ -6626,6 +6987,7 @@ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=8" @@ -6635,13 +6997,15 @@ "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/async-exit-hook": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -6650,13 +7014,15 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 4.0.0" } @@ -6680,6 +7046,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "browserslist": "^4.23.0", "caniuse-lite": "^1.0.30001599", @@ -6703,6 +7070,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, + "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -6718,6 +7086,7 @@ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", "dev": true, + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -6729,6 +7098,7 @@ "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", "dev": true, + "license": "MIT", "dependencies": { "find-cache-dir": "^4.0.0", "schema-utils": "^4.0.0" @@ -6746,6 +7116,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.2", @@ -6760,6 +7131,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -6769,6 +7141,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.1", "core-js-compat": "^3.36.1" @@ -6782,6 +7155,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2" }, @@ -6793,7 +7167,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", @@ -6813,24 +7188,28 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/bezier-easing": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz", - "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig==" + "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig==", + "license": "MIT" }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -6840,6 +7219,7 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -6852,6 +7232,7 @@ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -6862,13 +7243,15 @@ "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/bluebird-lst": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", "dev": true, + "license": "MIT", "dependencies": { "bluebird": "^3.5.5" } @@ -6877,13 +7260,15 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dev": true, + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -6908,6 +7293,7 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -6917,6 +7303,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -6926,6 +7313,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -6937,13 +7325,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/body-parser/node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" }, @@ -6959,6 +7349,7 @@ "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" @@ -6968,13 +7359,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/brace-expansion": { @@ -6982,6 +7375,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -6991,6 +7385,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -7002,13 +7397,15 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, + "license": "MIT", "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -7023,6 +7420,7 @@ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", "dev": true, + "license": "MIT", "dependencies": { "browserify-aes": "^1.0.4", "browserify-des": "^1.0.0", @@ -7034,6 +7432,7 @@ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", "dev": true, + "license": "MIT", "dependencies": { "cipher-base": "^1.0.1", "des.js": "^1.0.0", @@ -7046,6 +7445,7 @@ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", "dev": true, + "license": "MIT", "dependencies": { "bn.js": "^5.0.0", "randombytes": "^2.0.1" @@ -7056,6 +7456,7 @@ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", "dev": true, + "license": "ISC", "dependencies": { "bn.js": "^5.2.1", "browserify-rsa": "^4.1.0", @@ -7076,13 +7477,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/browserify-sign/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -7097,13 +7500,15 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/browserify-sign/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -7112,21 +7517,23 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dev": true, + "license": "MIT", "dependencies": { "pako": "~1.0.5" } }, "node_modules/browserslist": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", - "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "dev": true, "funding": [ { @@ -7142,10 +7549,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { @@ -7174,6 +7582,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -7184,6 +7593,7 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -7193,6 +7603,7 @@ "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4" }, @@ -7204,19 +7615,22 @@ "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 + "dev": true, + "license": "MIT" }, "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/builder-util": { "version": "24.13.1", "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", "dev": true, + "license": "MIT", "dependencies": { "@types/debug": "^4.1.6", "7zip-bin": "~5.2.0", @@ -7241,6 +7655,7 @@ "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" @@ -7254,6 +7669,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -7269,6 +7685,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -7285,6 +7702,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -7296,13 +7714,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/builder-util/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -7317,6 +7737,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -7326,6 +7747,7 @@ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -7339,6 +7761,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -7351,6 +7774,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -7363,6 +7787,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -7371,13 +7796,15 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/bundle-name": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, + "license": "MIT", "dependencies": { "run-applescript": "^7.0.0" }, @@ -7393,6 +7820,7 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -7402,6 +7830,7 @@ "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", @@ -7425,6 +7854,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -7444,13 +7874,15 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/cacache/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -7466,6 +7898,7 @@ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.6.0" } @@ -7475,6 +7908,7 @@ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", "dev": true, + "license": "MIT", "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", @@ -7493,6 +7927,7 @@ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -7512,14 +7947,15 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001642", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", - "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "version": "1.0.30001646", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001646.tgz", + "integrity": "sha512-dRg00gudiBDDTmUhClSdv3hqRfpbOnU28IpI1T6PBTLWa+kOj0681C8uML3PifYfREuBrVjDGhL3adYpBT6spw==", "dev": true, "funding": [ { @@ -7534,13 +7970,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "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, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -7554,12 +7992,14 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/chart.js": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.3.tgz", "integrity": "sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==", + "license": "MIT", "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -7571,6 +8011,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/chartjs-plugin-zoom/-/chartjs-plugin-zoom-2.0.1.tgz", "integrity": "sha512-ogOmLu6e+Q7E1XWOCOz9YwybMslz9qNfGV2a+qjfmqJYpsw5ZMoRHZBUyW+NGhkpQ5PwwPA/+rikHpBZb7PZuA==", + "license": "MIT", "dependencies": { "hammerjs": "^2.0.8" }, @@ -7583,6 +8024,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -7607,6 +8049,7 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -7616,6 +8059,7 @@ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0" } @@ -7624,7 +8068,8 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ci-info": { "version": "3.9.0", @@ -7637,6 +8082,7 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } @@ -7646,6 +8092,7 @@ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -7656,20 +8103,22 @@ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, + "license": "MIT", "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7680,6 +8129,7 @@ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -7692,6 +8142,7 @@ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "slice-ansi": "^3.0.0", @@ -7709,6 +8160,7 @@ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", "dev": true, + "license": "ISC", "engines": { "node": ">= 12" } @@ -7718,6 +8170,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -7732,6 +8185,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -7747,6 +8201,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -7758,13 +8213,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -7782,6 +8239,7 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8" } @@ -7791,6 +8249,7 @@ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -7805,6 +8264,7 @@ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", "dev": true, + "license": "MIT", "dependencies": { "mimic-response": "^1.0.0" }, @@ -7817,6 +8277,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -7825,19 +8286,22 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -7850,6 +8314,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -7858,13 +8323,15 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/compare-version": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7874,6 +8341,7 @@ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "buffer-crc32": "^0.2.13", @@ -7890,6 +8358,7 @@ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": ">= 1.43.0 < 2" }, @@ -7902,6 +8371,7 @@ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.5", "bytes": "3.0.0", @@ -7920,6 +8390,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -7928,25 +8399,29 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/compression/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/config-file-ts": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", "dev": true, + "license": "MIT", "dependencies": { "glob": "^10.3.10", "typescript": "^5.3.3" @@ -7957,6 +8432,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -7977,6 +8453,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -7992,6 +8469,7 @@ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8" } @@ -8006,13 +8484,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -8025,6 +8505,7 @@ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8033,13 +8514,15 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8048,13 +8531,15 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/copy-anything": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", "dev": true, + "license": "MIT", "dependencies": { "is-what": "^3.14.1" }, @@ -8067,6 +8552,7 @@ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz", "integrity": "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==", "dev": true, + "license": "MIT", "dependencies": { "fast-glob": "^3.3.2", "glob-parent": "^6.0.1", @@ -8091,6 +8577,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -8103,6 +8590,7 @@ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", "dev": true, + "license": "MIT", "dependencies": { "browserslist": "^4.23.0" }, @@ -8115,13 +8603,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cosmiconfig": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, + "license": "MIT", "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", @@ -8148,6 +8638,7 @@ "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "buffer": "^5.1.0" @@ -8158,6 +8649,7 @@ "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", "dev": true, + "license": "Apache-2.0", "peer": true, "bin": { "crc32": "bin/crc32.njs" @@ -8171,6 +8663,7 @@ "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "crc-32": "^1.2.0", @@ -8185,6 +8678,7 @@ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", "dev": true, + "license": "MIT", "dependencies": { "bn.js": "^4.1.0", "elliptic": "^6.5.3" @@ -8194,13 +8688,15 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, + "license": "MIT", "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -8214,6 +8710,7 @@ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, + "license": "MIT", "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -8227,13 +8724,15 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/critters": { "version": "0.0.24", "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.24.tgz", "integrity": "sha512-Oyqew0FGM0wYUSNqR0L6AteO5MpMoUU0rhKRieXeiKs+PmRTxiJMyaunYB2KF6fQ3dzChXKCpbFOEJx3OQ1v/Q==", "dev": true, + "license": "Apache-2.0", "dependencies": { "chalk": "^4.1.0", "css-select": "^5.1.0", @@ -8249,6 +8748,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -8264,6 +8764,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -8280,6 +8781,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -8291,13 +8793,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/critters/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8307,6 +8811,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -8318,6 +8823,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/croact/-/croact-1.0.4.tgz", "integrity": "sha512-9GhvyzTY/IVUrMQ2iz/mzgZ8+NcjczmIo/t4FkC1CU0CEcau6v6VsEih4jkTa4ZmRgYTF0qXEZLObCzdDFplpw==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.13.0", "@egjs/list-differ": "^1.0.0" @@ -8327,6 +8833,7 @@ "version": "1.1.9", "resolved": "https://registry.npmjs.org/croact-css-styled/-/croact-css-styled-1.1.9.tgz", "integrity": "sha512-G7yvRiVJ3Eoj0ov2h2xR4312hpOzATay2dGS9clK8yJQothjH1sBXIyvOeRP5wBKD9mPcKcoUXPCPsl0tQog4w==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.13.0", "css-styled": "~1.0.8", @@ -8337,6 +8844,7 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/croact-moveable/-/croact-moveable-0.9.0.tgz", "integrity": "sha512-fc3bieV6CdqqZFtzsSLi9KmvUMFW3oakUfhPCls1BxKjOfUfn8rktteGED2341A/Qghy8tI3Hm6SdocIc68IKg==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.13.0", "@egjs/agent": "^2.2.1", @@ -8362,6 +8870,7 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -8376,6 +8885,7 @@ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, + "license": "MIT", "dependencies": { "browserify-cipher": "^1.0.0", "browserify-sign": "^4.0.0", @@ -8398,6 +8908,7 @@ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", "dev": true, + "license": "MIT", "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.33", @@ -8433,6 +8944,7 @@ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", @@ -8448,6 +8960,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/css-styled/-/css-styled-1.0.8.tgz", "integrity": "sha512-tCpP7kLRI8dI95rCh3Syl7I+v7PP+2JYOzWkl0bUEoSbJM+u8ITbutjlQVf0NC2/g4ULROJPi16sfwDIO8/84g==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.13.0" } @@ -8456,6 +8969,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/css-to-mat/-/css-to-mat-1.1.1.tgz", "integrity": "sha512-kvpxFYZb27jRd2vium35G7q5XZ2WJ9rWjDUMNT36M3Hc41qCrLXFM5iEKMGXcrPsKfXEN+8l/riB4QzwwwiEyQ==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.13.0", "@scena/matrix": "^1.0.0" @@ -8466,6 +8980,7 @@ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">= 6" }, @@ -8478,6 +8993,7 @@ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, + "license": "MIT", "bin": { "cssesc": "bin/cssesc" }, @@ -8490,6 +9006,7 @@ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -8507,6 +9024,7 @@ "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, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -8524,6 +9042,7 @@ "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, + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -8537,10 +9056,11 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -8558,6 +9078,7 @@ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" }, @@ -8573,6 +9094,7 @@ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -8584,13 +9106,15 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/default-browser": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, + "license": "MIT", "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" @@ -8607,6 +9131,7 @@ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -8619,6 +9144,7 @@ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "execa": "^5.0.0" }, @@ -8631,6 +9157,7 @@ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, + "license": "MIT", "dependencies": { "clone": "^1.0.2" }, @@ -8643,6 +9170,7 @@ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -8652,6 +9180,7 @@ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -8669,6 +9198,7 @@ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -8681,6 +9211,7 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -8698,6 +9229,7 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -8707,6 +9239,7 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -8716,6 +9249,7 @@ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" @@ -8726,6 +9260,7 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -8736,6 +9271,7 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=8" } @@ -8744,13 +9280,15 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -8760,6 +9298,7 @@ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, + "license": "MIT", "dependencies": { "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", @@ -8770,13 +9309,15 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/dir-compare": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", "dev": true, + "license": "MIT", "dependencies": { "buffer-equal": "^1.0.0", "minimatch": "^3.0.4" @@ -8787,6 +9328,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8797,6 +9339,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -8809,6 +9352,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -8821,6 +9365,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8830,6 +9375,7 @@ "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", "dev": true, + "license": "MIT", "dependencies": { "app-builder-lib": "24.13.3", "builder-util": "24.13.1", @@ -8847,6 +9393,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -8861,6 +9408,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -8873,6 +9421,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -8882,6 +9431,7 @@ "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -8908,6 +9458,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -8925,6 +9476,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/dns-packet": { @@ -8932,6 +9484,7 @@ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", "dev": true, + "license": "MIT", "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" }, @@ -8944,6 +9497,7 @@ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, + "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -8958,6 +9512,7 @@ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-5.7.0.tgz", "integrity": "sha512-edTFu0M/7wO1pXY6GDxVNVW086uqwWYIHP98txhcPyV995X21JIH2DtYp33sQJOupYoXKe9RwTw2Ya2vWaquTQ==", "dev": true, + "license": "Artistic-2.0", "engines": { "node": ">=4" }, @@ -8975,13 +9530,15 @@ "type": "github", "url": "https://github.com/sponsors/fb55" } - ] + ], + "license": "BSD-2-Clause" }, "node_modules/domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.3.0" }, @@ -8997,6 +9554,7 @@ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -9011,6 +9569,7 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=10" } @@ -9019,25 +9578,29 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "jake": "^10.8.5" }, @@ -9054,6 +9617,7 @@ "integrity": "sha512-9fiuWlRhBfygtcT+auRd/WdBK/f8LZZcrpx0RjpXhH2DPTP/PfnkC4JB1PW55qCbGbh4wAgkYbf4ExIag8oGCA==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^20.9.0", @@ -9071,6 +9635,7 @@ "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", "dev": true, + "license": "MIT", "dependencies": { "app-builder-lib": "24.13.3", "builder-util": "24.13.1", @@ -9097,6 +9662,7 @@ "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz", "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "app-builder-lib": "24.13.3", @@ -9110,6 +9676,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -9125,6 +9692,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "universalify": "^2.0.0" @@ -9138,6 +9706,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 10.0.0" @@ -9148,6 +9717,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -9163,6 +9733,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -9179,6 +9750,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -9190,13 +9762,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/electron-builder/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -9211,6 +9785,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9220,6 +9795,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -9232,6 +9808,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -9244,6 +9821,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -9253,6 +9831,7 @@ "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", "dev": true, + "license": "MIT", "dependencies": { "@types/fs-extra": "^9.0.11", "builder-util": "24.13.1", @@ -9268,6 +9847,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -9283,6 +9863,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -9299,6 +9880,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -9310,13 +9892,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/electron-publish/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -9331,6 +9915,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9340,6 +9925,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -9352,6 +9938,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -9364,21 +9951,24 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, "node_modules/electron-to-chromium": { - "version": "1.4.830", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.830.tgz", - "integrity": "sha512-TrPKKH20HeN0J1LHzsYLs2qwXrp8TF4nHdu4sq61ozGbzMpWhI7iIOPYPPkxeq1azMT9PZ8enPFcftbs/Npcjg==", - "dev": true + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", + "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==", + "dev": true, + "license": "ISC" }, "node_modules/elliptic": { "version": "6.5.6", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.6.tgz", "integrity": "sha512-mpzdtpeCLuS3BmE3pO3Cpp5bbjlOPY2Q0PgoF+Od1XZrHLYI28Xe3ossCmYCQt11FQKEYd9+PF8jymTvtWJSHQ==", "dev": true, + "license": "MIT", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -9393,19 +9983,22 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -9415,6 +10008,7 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -9424,6 +10018,7 @@ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "iconv-lite": "^0.6.2" @@ -9434,15 +10029,17 @@ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, + "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -9456,6 +10053,7 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "devOptional": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -9468,21 +10066,37 @@ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/err-code": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "prr": "~1.0.1" @@ -9496,6 +10110,7 @@ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } @@ -9505,6 +10120,7 @@ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -9565,6 +10181,7 @@ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -9577,6 +10194,7 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -9585,13 +10203,15 @@ "version": "1.5.4", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true + "dev": true, + "license": "MIT" }, "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, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -9604,6 +10224,7 @@ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -9618,6 +10239,7 @@ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -9635,6 +10257,7 @@ "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/esbuild": { @@ -9643,6 +10266,7 @@ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -9680,6 +10304,7 @@ "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.21.5.tgz", "integrity": "sha512-L/FlOPMMFtw+6qPAbuPvJXdrOYOp9yx/PEwSrIZW0qghY4vgV003evdYDwqQ/9ENMQI0B6RMod9xT4FHtto6OQ==", "dev": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -9692,6 +10317,7 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -9700,13 +10326,15 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true + "dev": true, + "license": "MIT" }, "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, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -9716,6 +10344,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", @@ -9767,6 +10396,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -9779,12 +10409,13 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -9795,6 +10426,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -9811,6 +10443,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -9826,6 +10459,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -9836,6 +10470,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -9852,6 +10487,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -9863,13 +10499,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -9877,23 +10515,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -9906,6 +10533,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9914,13 +10542,15 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -9933,6 +10563,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -9945,6 +10576,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", @@ -9957,23 +10589,12 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -9986,6 +10607,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -9998,6 +10620,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -10007,6 +10630,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -10016,6 +10640,7 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10025,6 +10650,7 @@ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -10033,13 +10659,15 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.x" } @@ -10049,6 +10677,7 @@ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, + "license": "MIT", "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -10059,6 +10688,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -10082,6 +10712,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -10089,23 +10720,42 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/execa/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, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/execa/node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/exponential-backoff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/express": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -10148,6 +10798,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -10156,13 +10807,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/express/node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" }, @@ -10178,6 +10831,7 @@ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, + "license": "MIT", "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -10192,6 +10846,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -10204,6 +10859,7 @@ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -10227,19 +10883,22 @@ "engines": [ "node >=0.6.0" ], + "license": "MIT", "optional": true }, "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 + "dev": true, + "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -10255,19 +10914,22 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -10277,6 +10939,7 @@ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "dev": true, + "license": "Apache-2.0", "dependencies": { "websocket-driver": ">=0.5.1" }, @@ -10289,6 +10952,7 @@ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, + "license": "MIT", "dependencies": { "pend": "~1.2.0" } @@ -10298,6 +10962,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -10310,6 +10975,7 @@ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, + "license": "Apache-2.0", "dependencies": { "minimatch": "^5.0.1" } @@ -10319,6 +10985,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -10331,6 +10998,7 @@ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dev": true, + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -10349,6 +11017,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -10357,13 +11026,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/find-cache-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", "dev": true, + "license": "MIT", "dependencies": { "common-path-prefix": "^3.0.0", "pkg-dir": "^7.0.0" @@ -10380,6 +11051,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -10396,6 +11068,7 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } @@ -10405,6 +11078,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -10417,7 +11091,8 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/follow-redirects": { "version": "1.15.6", @@ -10430,6 +11105,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -10444,6 +11120,7 @@ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.1.3" } @@ -10453,6 +11130,7 @@ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -10469,6 +11147,7 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -10483,6 +11162,7 @@ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10492,6 +11172,7 @@ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, + "license": "MIT", "engines": { "node": "*" }, @@ -10503,13 +11184,15 @@ "node_modules/framework-utils": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/framework-utils/-/framework-utils-1.1.0.tgz", - "integrity": "sha512-KAfqli5PwpFJ8o3psRNs8svpMGyCSAe8nmGcjQ0zZBWN2H6dZDnq+ABp3N3hdUmFeMrLtjOCTXD4yplUJIWceg==" + "integrity": "sha512-KAfqli5PwpFJ8o3psRNs8svpMGyCSAe8nmGcjQ0zZBWN2H6dZDnq+ABp3N3hdUmFeMrLtjOCTXD4yplUJIWceg==", + "license": "MIT" }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10519,6 +11202,7 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/fs-extra": { @@ -10526,6 +11210,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -10540,6 +11225,7 @@ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -10551,7 +11237,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -10559,6 +11246,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -10572,6 +11260,7 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10581,6 +11270,7 @@ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -10599,6 +11289,7 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10608,6 +11299,7 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -10616,6 +11308,7 @@ "version": "1.19.4", "resolved": "https://registry.npmjs.org/gesto/-/gesto-1.19.4.tgz", "integrity": "sha512-hfr/0dWwh0Bnbb88s3QVJd1ZRJeOWcgHPPwmiH6NnafDYvhTsxg+SLYu+q/oPNh9JS3V+nlr6fNs8kvPAtcRDQ==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.13.0", "@scena/event-emitter": "^1.0.2" @@ -10626,6 +11319,7 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -10635,6 +11329,7 @@ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -10647,6 +11342,7 @@ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -10666,6 +11362,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, + "license": "MIT", "dependencies": { "pump": "^3.0.0" }, @@ -10681,6 +11378,7 @@ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -10699,6 +11397,7 @@ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -10719,6 +11418,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -10730,13 +11430,15 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/glob/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -10747,6 +11449,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -10759,6 +11462,7 @@ "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "dependencies": { "boolean": "^3.0.1", @@ -10777,6 +11481,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -10786,6 +11491,7 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -10802,6 +11508,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", "dev": true, + "license": "MIT", "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", "fast-glob": "^3.3.2", @@ -10822,6 +11529,7 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -10834,6 +11542,7 @@ "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "dev": true, + "license": "MIT", "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", @@ -10858,18 +11567,21 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/hammerjs": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", "integrity": "sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==", + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -10878,13 +11590,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10894,6 +11608,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -10903,6 +11618,7 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -10915,6 +11631,7 @@ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10927,6 +11644,7 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10939,6 +11657,7 @@ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -10954,6 +11673,7 @@ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -10967,6 +11687,7 @@ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -10977,6 +11698,7 @@ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -10989,6 +11711,7 @@ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", "dev": true, + "license": "MIT", "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -11000,6 +11723,7 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -11012,6 +11736,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -11023,12 +11748,14 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/hotkeys-js": { "version": "3.13.7", "resolved": "https://registry.npmjs.org/hotkeys-js/-/hotkeys-js-3.13.7.tgz", "integrity": "sha512-ygFIdTqqwG4fFP7kkiYlvayZppeIQX2aPpirsngkv1xM1lP0piDY5QEh68nQnIKvz64hfocxhBaD/uK3sSK1yQ==", + "license": "MIT", "funding": { "url": "https://jaywcjlove.github.io/#/sponsor" } @@ -11038,6 +11765,7 @@ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -11049,13 +11777,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/hpack.js/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -11070,13 +11800,15 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/hpack.js/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -11095,7 +11827,8 @@ "type": "patreon", "url": "https://patreon.com/mdevils" } - ] + ], + "license": "MIT" }, "node_modules/htmlparser2": { "version": "8.0.2", @@ -11109,6 +11842,7 @@ "url": "https://github.com/sponsors/fb55" } ], + "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", @@ -11120,19 +11854,22 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -11148,13 +11885,15 @@ "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, + "license": "MIT", "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -11169,6 +11908,7 @@ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, + "license": "MIT", "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -11183,6 +11923,7 @@ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.0.tgz", "integrity": "sha512-36AV1fIaI2cWRzHo+rbcxhe3M3jUDCNzc4D5zRl57sEWRAxdXYtw7FSQKYY6PDKssiAKjLYypbssHk+xs/kMXw==", "dev": true, + "license": "MIT", "dependencies": { "@types/http-proxy": "^1.17.10", "debug": "^4.3.4", @@ -11200,6 +11941,7 @@ "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", "dev": true, + "license": "MIT", "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" @@ -11212,13 +11954,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/https-proxy-agent": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -11232,6 +11976,7 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4" }, @@ -11244,6 +11989,7 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } @@ -11253,6 +11999,7 @@ "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.18" } @@ -11262,6 +12009,7 @@ "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -11279,6 +12027,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -11291,6 +12040,7 @@ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "dev": true, + "license": "ISC", "engines": { "node": "^10 || ^12 || >= 14" }, @@ -11316,13 +12066,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -11332,6 +12084,7 @@ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", "integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==", "dev": true, + "license": "ISC", "dependencies": { "minimatch": "^9.0.0" }, @@ -11344,6 +12097,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -11359,6 +12113,7 @@ "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", "dev": true, + "license": "MIT", "optional": true, "bin": { "image-size": "bin/image-size.js" @@ -11371,13 +12126,15 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -11394,6 +12151,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -11403,6 +12161,7 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11413,6 +12172,7 @@ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -11422,13 +12182,15 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ini": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -11438,6 +12200,7 @@ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -11452,6 +12215,7 @@ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", "dev": true, + "license": "MIT", "dependencies": { "jsbn": "1.1.0", "sprintf-js": "^1.1.3" @@ -11465,6 +12229,7 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } @@ -11474,6 +12239,7 @@ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -11490,6 +12256,7 @@ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -11505,13 +12272,15 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, + "license": "MIT", "dependencies": { "has-bigints": "^1.0.1" }, @@ -11524,6 +12293,7 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -11536,6 +12306,7 @@ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -11552,6 +12323,7 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11564,6 +12336,7 @@ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dev": true, + "license": "MIT", "dependencies": { "ci-info": "^3.2.0" }, @@ -11576,6 +12349,7 @@ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", "dev": true, + "license": "MIT", "dependencies": { "hasown": "^2.0.2" }, @@ -11591,6 +12365,7 @@ "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, + "license": "MIT", "dependencies": { "is-typed-array": "^1.1.13" }, @@ -11606,6 +12381,7 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -11621,6 +12397,7 @@ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, + "license": "MIT", "bin": { "is-docker": "cli.js" }, @@ -11636,6 +12413,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11645,6 +12423,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11654,6 +12433,7 @@ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -11669,6 +12449,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -11681,6 +12462,7 @@ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, + "license": "MIT", "dependencies": { "is-docker": "^3.0.0" }, @@ -11699,6 +12481,7 @@ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11707,13 +12490,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-nan": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" @@ -11730,6 +12515,7 @@ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11742,6 +12528,7 @@ "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -11754,6 +12541,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -11763,6 +12551,7 @@ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -11778,6 +12567,7 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11787,6 +12577,7 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -11799,6 +12590,7 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, + "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, @@ -11811,6 +12603,7 @@ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -11827,6 +12620,7 @@ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7" }, @@ -11842,6 +12636,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -11854,6 +12649,7 @@ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -11869,6 +12665,7 @@ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" }, @@ -11884,6 +12681,7 @@ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, + "license": "MIT", "dependencies": { "which-typed-array": "^1.1.14" }, @@ -11899,6 +12697,7 @@ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -11911,6 +12710,7 @@ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -11922,13 +12722,15 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-wsl": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, + "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" }, @@ -11943,13 +12745,15 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isbinaryfile": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.2.tgz", "integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18.0.0" }, @@ -11961,13 +12765,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11977,6 +12783,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } @@ -11986,6 +12793,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.23.9", "@babel/parser": "^7.23.9", @@ -12002,6 +12810,7 @@ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -12017,6 +12826,7 @@ "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "async": "^3.2.3", "chalk": "^4.0.2", @@ -12035,6 +12845,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -12050,6 +12861,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -12060,6 +12872,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -12076,6 +12889,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -12087,13 +12901,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jake/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -12103,6 +12919,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -12115,6 +12932,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -12127,6 +12945,7 @@ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -12141,6 +12960,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -12150,6 +12970,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -12165,6 +12986,7 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "dev": true, + "license": "MIT", "bin": { "jiti": "bin/jiti.js" } @@ -12174,6 +12996,7 @@ "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", @@ -12186,13 +13009,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -12204,13 +13029,15 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -12222,19 +13049,22 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "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, + "license": "MIT", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -12243,19 +13073,22 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true, + "license": "ISC", "optional": true }, "node_modules/json5": { @@ -12263,6 +13096,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -12274,13 +13108,15 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, + "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -12292,13 +13128,15 @@ "dev": true, "engines": [ "node >= 0.2.0" - ] + ], + "license": "MIT" }, "node_modules/karma-source-map-support": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", "dev": true, + "license": "MIT", "dependencies": { "source-map-support": "^0.5.5" } @@ -12306,12 +13144,14 @@ "node_modules/keycode": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz", - "integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==" + "integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==", + "license": "MIT" }, "node_modules/keycon": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/keycon/-/keycon-1.4.0.tgz", "integrity": "sha512-p1NAIxiRMH3jYfTeXRs2uWbVJ1WpEjpi8ktzUyBJsX7/wn2qu2VRXktneBLNtKNxJmlUYxRi9gOJt1DuthXR7A==", + "license": "MIT", "dependencies": { "@cfcs/core": "^0.0.6", "@daybrush/utils": "^1.7.1", @@ -12324,6 +13164,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -12333,6 +13174,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12342,6 +13184,7 @@ "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==", "dev": true, + "license": "MIT", "dependencies": { "picocolors": "^1.0.0", "shell-quote": "^1.8.1" @@ -12351,13 +13194,15 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lazystream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "readable-stream": "^2.0.5" @@ -12371,6 +13216,7 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lazystream/node_modules/readable-stream": { @@ -12378,6 +13224,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "core-util-is": "~1.0.0", @@ -12394,6 +13241,7 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lazystream/node_modules/string_decoder": { @@ -12401,6 +13249,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "safe-buffer": "~5.1.0" @@ -12409,13 +13258,15 @@ "node_modules/leaflet": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", - "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "license": "BSD-2-Clause" }, "node_modules/less": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "copy-anything": "^2.0.1", "parse-node-version": "^1.0.1", @@ -12442,6 +13293,7 @@ "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-12.2.0.tgz", "integrity": "sha512-MYUxjSQSBUQmowc0l5nPieOYwMzGPUaTzB6inNW/bdPEG9zOL3eAAD1Qw5ZxSPk7we5dMojHwNODYMV1hq4EVg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18.12.0" }, @@ -12468,6 +13320,7 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, + "license": "MIT", "optional": true, "bin": { "mime": "cli.js" @@ -12481,6 +13334,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "engines": { "node": ">=0.10.0" @@ -12491,6 +13345,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -12504,6 +13359,7 @@ "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", "dev": true, + "license": "ISC", "dependencies": { "webpack-sources": "^3.0.0" }, @@ -12520,13 +13376,15 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/listr2": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.3.tgz", "integrity": "sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==", "dev": true, + "license": "MIT", "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", @@ -12544,6 +13402,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -12556,6 +13415,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -12568,6 +13428,7 @@ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, + "license": "MIT", "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" @@ -12583,19 +13444,22 @@ "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/listr2/node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/listr2/node_modules/is-fullwidth-code-point": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -12608,6 +13472,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" @@ -12624,6 +13489,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -12641,6 +13507,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -12656,6 +13523,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -12674,6 +13542,7 @@ "integrity": "sha512-JnoEulTgveoC64vlYJ9sufGLuNkk6TcxSYpKxSC9aM42I61jIv3pQH0fgb6qW7HV0+FNqA3g1WCQQYfhfawGoQ==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "msgpackr": "^1.10.2", "node-addon-api": "^6.1.0", @@ -12697,13 +13566,15 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^4.0.0", @@ -12719,6 +13590,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, + "license": "MIT", "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" @@ -12732,6 +13604,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -12741,6 +13614,7 @@ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.11.5" } @@ -12750,6 +13624,7 @@ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12.13.0" } @@ -12759,6 +13634,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -12773,19 +13649,22 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lodash.difference": { @@ -12793,6 +13672,7 @@ "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lodash.flatten": { @@ -12800,6 +13680,7 @@ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lodash.isplainobject": { @@ -12807,19 +13688,22 @@ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.union": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/log-symbols": { @@ -12827,6 +13711,7 @@ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -12843,6 +13728,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -12858,6 +13744,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -12874,6 +13761,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -12885,13 +13773,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-symbols/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -12901,6 +13791,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -12909,14 +13800,15 @@ } }, "node_modules/log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, @@ -12928,12 +13820,16 @@ } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -12944,6 +13840,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -12956,6 +13853,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -12967,13 +13865,15 @@ "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-update/node_modules/is-fullwidth-code-point": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, + "license": "MIT", "dependencies": { "get-east-asian-width": "^1.0.0" }, @@ -12989,6 +13889,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" @@ -13005,6 +13906,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -13022,6 +13924,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -13037,6 +13940,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -13054,6 +13958,7 @@ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -13063,6 +13968,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -13072,6 +13978,7 @@ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } @@ -13081,6 +13988,7 @@ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "pify": "^4.0.1", @@ -13095,6 +14003,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "optional": true, "bin": { "semver": "bin/semver" @@ -13104,13 +14013,15 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/make-fetch-happen": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", @@ -13134,6 +14045,7 @@ "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "escape-string-regexp": "^4.0.0" @@ -13147,6 +14059,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=10" @@ -13160,6 +14073,7 @@ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, + "license": "MIT", "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -13171,6 +14085,7 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -13180,6 +14095,7 @@ "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", "@jsonjoy.com/util": "^1.3.0", @@ -13207,19 +14123,22 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -13229,6 +14148,7 @@ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -13238,6 +14158,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -13251,6 +14172,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -13263,6 +14185,7 @@ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, + "license": "MIT", "dependencies": { "bn.js": "^4.0.0", "brorand": "^1.0.1" @@ -13275,13 +14198,15 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -13294,6 +14219,7 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -13303,6 +14229,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -13315,15 +14242,30 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -13333,6 +14275,7 @@ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", "integrity": "sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==", "dev": true, + "license": "MIT", "dependencies": { "schema-utils": "^4.0.0", "tapable": "^2.2.1" @@ -13352,19 +14295,22 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -13377,6 +14323,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13386,6 +14333,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } @@ -13395,6 +14343,7 @@ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -13407,6 +14356,7 @@ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", "dev": true, + "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", @@ -13424,6 +14374,7 @@ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -13436,6 +14387,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -13447,13 +14399,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -13466,6 +14420,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -13477,13 +14432,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -13496,6 +14453,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -13507,13 +14465,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, + "license": "MIT", "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -13527,6 +14487,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -13538,13 +14499,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -13556,6 +14519,7 @@ "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", "engines": { "node": "*" } @@ -13564,6 +14528,7 @@ "version": "0.53.0", "resolved": "https://registry.npmjs.org/moveable/-/moveable-0.53.0.tgz", "integrity": "sha512-71jS9zIoQzMhnNvduhg4tUEdm23+fO/40FN7muVMbZvVwbTku2MIxxLhnU4qFvxI4oVxn75l79SbtgjuA+s7Pw==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.13.0", "@scena/event-emitter": "^1.0.5", @@ -13577,6 +14542,7 @@ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -13585,13 +14551,15 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/msgpackr": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.0.tgz", "integrity": "sha512-I8qXuuALqJe5laEBYoFykChhSXLikZmUhccjGsPuSJ/7uPip2TJ7lwdIQwWSAi0jGZDXv4WOP8Qg65QZRuXxXw==", "dev": true, + "license": "MIT", "optionalDependencies": { "msgpackr-extract": "^3.0.2" } @@ -13602,6 +14570,7 @@ "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "node-gyp-build-optional-packages": "5.2.2" @@ -13623,6 +14592,7 @@ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dev": true, + "license": "MIT", "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" @@ -13636,6 +14606,7 @@ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -13651,6 +14622,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -13662,13 +14634,15 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/needle": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "iconv-lite": "^0.6.3", @@ -13686,6 +14660,7 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -13694,17 +14669,20 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ngraph.events": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.2.2.tgz", - "integrity": "sha512-JsUbEOzANskax+WSYiAPETemLWYXmixuPAlmZmhIbIj6FH/WDgEGCGnRwUQBK0GjOnVm8Ui+e5IJ+5VZ4e32eQ==" + "integrity": "sha512-JsUbEOzANskax+WSYiAPETemLWYXmixuPAlmZmhIbIj6FH/WDgEGCGnRwUQBK0GjOnVm8Ui+e5IJ+5VZ4e32eQ==", + "license": "BSD-3-Clause" }, "node_modules/ngx-moveable": { "version": "0.50.0", "resolved": "https://registry.npmjs.org/ngx-moveable/-/ngx-moveable-0.50.0.tgz", "integrity": "sha512-P70Jk9tgZQtCkNHKXasDu0+3kyRqMaxNnhcjzzT1fovgtkClCAd1eyxUrQmTHtAVMAUbtqUjEET9A9+NjOobIw==", + "license": "MIT", "dependencies": { "framework-utils": "^1.1.0", "moveable": "~0.53.0", @@ -13721,6 +14699,7 @@ "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "!win32" @@ -13735,19 +14714,22 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-addon-api": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/node-forge": { @@ -13755,6 +14737,7 @@ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", "dev": true, + "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } @@ -13764,6 +14747,7 @@ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", "dev": true, + "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", @@ -13788,6 +14772,7 @@ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", "dev": true, + "license": "MIT", "optional": true, "bin": { "node-gyp-build": "bin.js", @@ -13800,6 +14785,7 @@ "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", "dev": true, + "license": "MIT", "dependencies": { "detect-libc": "^2.0.1" }, @@ -13814,6 +14800,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -13834,6 +14821,7 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=16" } @@ -13843,6 +14831,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -13858,6 +14847,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -13873,6 +14863,7 @@ "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-4.0.0.tgz", "integrity": "sha512-WLk77vLpbcpmTekRj6s6vYxk30XoyaY5MDZ4+9g8OaKoG3Ij+TjOqhpQjVUlfDZBPBgpNATDltaQkzuXSnnkwg==", "dev": true, + "license": "MIT", "dependencies": { "assert": "^2.1.0", "browserify-zlib": "^0.2.0", @@ -13925,6 +14916,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -13935,6 +14927,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dev": true, + "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", @@ -13947,10 +14940,11 @@ } }, "node_modules/node-polyfill-webpack-plugin/node_modules/type-fest": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.22.1.tgz", - "integrity": "sha512-9tHNEa0Ov81YOopiVkcCJVz5TM6AEQ+CHHjFIktqPnE3NV0AHIkx+gh9tiCl58m/66wWxkOC9eltpa75J4lQPA==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.23.0.tgz", + "integrity": "sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=16" }, @@ -13959,16 +14953,18 @@ } }, "node_modules/node-releases": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz", - "integrity": "sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==", - "dev": true + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true, + "license": "MIT" }, "node_modules/nopt": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", "dev": true, + "license": "ISC", "dependencies": { "abbrev": "^2.0.0" }, @@ -13984,6 +14980,7 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^7.0.0", "semver": "^7.3.5", @@ -13998,6 +14995,7 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^10.0.1" }, @@ -14009,13 +15007,15 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -14025,6 +15025,7 @@ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -14034,6 +15035,7 @@ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -14046,6 +15048,7 @@ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", "integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==", "dev": true, + "license": "ISC", "dependencies": { "npm-normalize-package-bin": "^3.0.0" }, @@ -14058,6 +15061,7 @@ "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" }, @@ -14070,6 +15074,7 @@ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -14079,6 +15084,7 @@ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.2.tgz", "integrity": "sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^7.0.0", "proc-log": "^4.0.0", @@ -14094,6 +15100,7 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^10.0.1" }, @@ -14105,13 +15112,15 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/npm-packlist": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", "dev": true, + "license": "ISC", "dependencies": { "ignore-walk": "^6.0.4" }, @@ -14124,6 +15133,7 @@ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.1.tgz", "integrity": "sha512-Udm1f0l2nXb3wxDpKjfohwgdFUSV50UVwzEIpDXVsbDMXVIEF81a/i0UhuQbhrPMMmdiq3+YMFLFIRVLs3hxQw==", "dev": true, + "license": "ISC", "dependencies": { "npm-install-checks": "^6.0.0", "npm-normalize-package-bin": "^3.0.0", @@ -14139,6 +15149,7 @@ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-17.1.0.tgz", "integrity": "sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/redact": "^2.0.0", "jsonparse": "^1.3.1", @@ -14158,6 +15169,7 @@ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "chalk": "^2.4.1", @@ -14183,6 +15195,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -14193,6 +15206,7 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, + "license": "MIT", "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -14209,6 +15223,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -14221,6 +15236,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -14230,6 +15246,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -14239,6 +15256,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^1.0.0" }, @@ -14251,6 +15269,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -14260,6 +15279,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -14272,6 +15292,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -14284,6 +15305,7 @@ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0" }, @@ -14295,6 +15317,7 @@ "version": "2.0.1-2", "resolved": "https://registry.npmjs.org/nuid/-/nuid-2.0.1-2.tgz", "integrity": "sha512-zL7Z5+CivaZyUdBn76Ih8rffXABBSe3hzazHBk7qXsF4/o5DPDsblXjs5KQRlgjkeLa6XSCd5/GJaShArI2WMQ==", + "license": "Apache-2.0", "engines": { "node": ">= 18.x" } @@ -14304,6 +15327,7 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -14316,6 +15340,7 @@ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1" @@ -14332,6 +15357,7 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -14341,6 +15367,7 @@ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -14358,13 +15385,15 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -14377,6 +15406,7 @@ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -14386,20 +15416,22 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "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==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, + "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -14410,6 +15442,7 @@ "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", "dev": true, + "license": "MIT", "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", @@ -14428,6 +15461,7 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -14445,6 +15479,7 @@ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, + "license": "MIT", "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -14468,6 +15503,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -14483,6 +15519,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14499,6 +15536,7 @@ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, + "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" }, @@ -14511,6 +15549,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -14522,22 +15561,41 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ora/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/ora/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, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ora/node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, + "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -14550,13 +15608,15 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ora/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -14568,19 +15628,22 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.1.tgz", "integrity": "sha512-5VyHfHY3cd0iza71JepYG50My+YUbrFtGoUz2ooEydPyPM7Aai/JW098juLr+RG6+rDJuzNNTsEQu2DZa1A41A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -14589,6 +15652,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/overlap-area/-/overlap-area-1.1.0.tgz", "integrity": "sha512-3dlJgJCaVeXH0/eZjYVJvQiLVVrPO4U1ZGqlATtx6QGO3b5eNM6+JgUKa7oStBTdYuGTk7gVoABCW6Tp+dhRdw==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.7.1" } @@ -14598,6 +15662,7 @@ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -14607,6 +15672,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -14622,6 +15688,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -14637,6 +15704,7 @@ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, + "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -14652,6 +15720,7 @@ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", "dev": true, + "license": "MIT", "dependencies": { "@types/retry": "0.12.2", "is-network-error": "^1.0.0", @@ -14669,6 +15738,7 @@ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -14677,13 +15747,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true + "dev": true, + "license": "BlueOak-1.0.0" }, "node_modules/pacote": { "version": "18.0.6", "resolved": "https://registry.npmjs.org/pacote/-/pacote-18.0.6.tgz", "integrity": "sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/git": "^5.0.0", "@npmcli/installed-package-contents": "^2.0.1", @@ -14714,12 +15786,14 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true + "dev": true, + "license": "(MIT AND Zlib)" }, "node_modules/panzoom": { "version": "9.4.3", "resolved": "https://registry.npmjs.org/panzoom/-/panzoom-9.4.3.tgz", "integrity": "sha512-xaxCpElcRbQsUtIdwlrZA90P90+BHip4Vda2BC8MEb4tkI05PmR6cKECdqUCZ85ZvBHjpI9htJrZBxV5Gp/q/w==", + "license": "MIT", "dependencies": { "amator": "^1.1.0", "ngraph.events": "^1.2.2", @@ -14731,6 +15805,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -14743,6 +15818,7 @@ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", "dev": true, + "license": "ISC", "dependencies": { "asn1.js": "^4.10.1", "browserify-aes": "^1.2.0", @@ -14760,6 +15836,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -14777,13 +15854,15 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -14793,6 +15872,7 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "devOptional": true, + "license": "MIT", "dependencies": { "entities": "^4.4.0" }, @@ -14805,6 +15885,7 @@ "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", "dev": true, + "license": "MIT", "dependencies": { "entities": "^4.3.0", "parse5": "^7.0.0", @@ -14819,6 +15900,7 @@ "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", "dev": true, + "license": "MIT", "dependencies": { "parse5": "^7.0.0" }, @@ -14831,6 +15913,7 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -14839,13 +15922,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -14855,6 +15940,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -14864,6 +15950,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -14872,13 +15959,15 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -14894,19 +15983,22 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-type": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -14919,6 +16011,7 @@ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", "dev": true, + "license": "MIT", "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -14934,19 +16027,22 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -14959,6 +16055,7 @@ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true, + "license": "MIT", "bin": { "pidtree": "bin/pidtree.js" }, @@ -14971,6 +16068,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=6" @@ -14981,6 +16079,7 @@ "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.6.1.tgz", "integrity": "sha512-z30AwWGtQE+Apr+2WBZensP2lIvwoaMcOPkQlIEmSGMJNUvaYACylPYrQM6wSdUNJlnDVMSpLv7xTMJqlVshOA==", "dev": true, + "license": "MIT", "optionalDependencies": { "nice-napi": "^1.0.2" } @@ -14990,6 +16089,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^6.3.0" }, @@ -15005,6 +16105,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^7.1.0", "path-exists": "^5.0.0" @@ -15021,6 +16122,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^6.0.0" }, @@ -15036,6 +16138,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^1.0.0" }, @@ -15051,6 +16154,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^4.0.0" }, @@ -15066,6 +16170,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -15075,6 +16180,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.20" }, @@ -15087,6 +16193,7 @@ "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dev": true, + "license": "MIT", "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", @@ -15101,6 +16208,7 @@ "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, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -15124,6 +16232,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", @@ -15138,6 +16247,7 @@ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", "dev": true, + "license": "MIT", "dependencies": { "cosmiconfig": "^9.0.0", "jiti": "^1.20.0", @@ -15168,13 +16278,15 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/postcss-modules-extract-imports": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", "dev": true, + "license": "ISC", "engines": { "node": "^10 || ^12 || >= 14" }, @@ -15187,6 +16299,7 @@ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", "dev": true, + "license": "MIT", "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^6.0.2", @@ -15204,6 +16317,7 @@ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", "dev": true, + "license": "ISC", "dependencies": { "postcss-selector-parser": "^6.0.4" }, @@ -15219,6 +16333,7 @@ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, + "license": "ISC", "dependencies": { "icss-utils": "^5.0.0" }, @@ -15234,6 +16349,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -15246,13 +16362,15 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -15262,6 +16380,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -15275,17 +16394,20 @@ "node_modules/primeflex": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/primeflex/-/primeflex-3.3.1.tgz", - "integrity": "sha512-zaOq3YvcOYytbAmKv3zYc+0VNS9Wg5d37dfxZnveKBFPr7vEIwfV5ydrpiouTft8MVW6qNjfkaQphHSnvgQbpQ==" + "integrity": "sha512-zaOq3YvcOYytbAmKv3zYc+0VNS9Wg5d37dfxZnveKBFPr7vEIwfV5ydrpiouTft8MVW6qNjfkaQphHSnvgQbpQ==", + "license": "MIT" }, "node_modules/primeicons": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-7.0.0.tgz", - "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==" + "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==", + "license": "MIT" }, "node_modules/primeng": { "version": "17.18.7", "resolved": "https://registry.npmjs.org/primeng/-/primeng-17.18.7.tgz", "integrity": "sha512-RKbUL69uTzDrVLOKxC8Qn7tyzoAUXetBsMOnNJJaomXTirC001vNTw/wzcuLxkTQpNXAOztxcKMpMTmZQMhe5Q==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -15299,13 +16421,15 @@ }, "node_modules/primeng-sass-theme": { "version": "17.18.3", - "resolved": "git+ssh://git@github.com/primefaces/primeng-sass-theme.git#2f7b1705c8783a098381c078345eb5dbe45c4008" + "resolved": "git+ssh://git@github.com/primefaces/primeng-sass-theme.git#2f7b1705c8783a098381c078345eb5dbe45c4008", + "license": "MIT" }, "node_modules/proc-log": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -15315,6 +16439,7 @@ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -15323,13 +16448,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -15338,13 +16465,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, + "license": "MIT", "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -15358,6 +16487,7 @@ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -15371,6 +16501,7 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -15379,13 +16510,15 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/public-encrypt": { @@ -15393,6 +16526,7 @@ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dev": true, + "license": "MIT", "dependencies": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", @@ -15406,13 +16540,15 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -15423,15 +16559,17 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/qs": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", - "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.6" }, @@ -15469,13 +16607,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -15488,6 +16628,7 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -15497,6 +16638,7 @@ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, + "license": "MIT", "dependencies": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" @@ -15507,6 +16649,7 @@ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -15516,6 +16659,7 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -15531,6 +16675,7 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -15540,6 +16685,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -15551,6 +16697,7 @@ "version": "1.1.9", "resolved": "https://registry.npmjs.org/react-css-styled/-/react-css-styled-1.1.9.tgz", "integrity": "sha512-M7fJZ3IWFaIHcZEkoFOnkjdiUFmwd8d+gTh2bpqMOcnxy/0Gsykw4dsL4QBiKsxcGow6tETUa4NAUcmJF+/nfw==", + "license": "MIT", "dependencies": { "css-styled": "~1.0.8", "framework-utils": "^1.1.0" @@ -15560,6 +16707,7 @@ "version": "0.56.0", "resolved": "https://registry.npmjs.org/react-moveable/-/react-moveable-0.56.0.tgz", "integrity": "sha512-FmJNmIOsOA36mdxbrc/huiE4wuXSRlmon/o+/OrfNhSiYYYL0AV5oObtPluEhb2Yr/7EfYWBHTxF5aWAvjg1SA==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.13.0", "@egjs/agent": "^2.2.1", @@ -15580,6 +16728,7 @@ "version": "1.26.3", "resolved": "https://registry.npmjs.org/react-selecto/-/react-selecto-1.26.3.tgz", "integrity": "sha512-Ubik7kWSnZyQEBNro+1k38hZaI1tJarE+5aD/qsqCOA1uUBSjgKVBy3EWRzGIbdmVex7DcxznFZLec/6KZNvwQ==", + "license": "MIT", "dependencies": { "selecto": "~1.26.3" } @@ -15589,6 +16738,7 @@ "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", "dev": true, + "license": "MIT", "dependencies": { "config-file-ts": "^0.2.4", "dotenv": "^9.0.2", @@ -15606,6 +16756,7 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, + "license": "MIT", "dependencies": { "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", @@ -15619,13 +16770,15 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/read-pkg/node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -15638,6 +16791,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, + "license": "MIT", "dependencies": { "pify": "^3.0.0" }, @@ -15650,6 +16804,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -15659,6 +16814,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -15668,6 +16824,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -15682,6 +16839,7 @@ "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", "dev": true, + "license": "Apache-2.0", "peer": true, "dependencies": { "minimatch": "^5.1.0" @@ -15692,6 +16850,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -15704,6 +16863,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -15715,19 +16875,22 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/regenerate-unicode-properties": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", "dev": true, + "license": "MIT", "dependencies": { "regenerate": "^1.4.2" }, @@ -15739,13 +16902,15 @@ "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/regenerator-transform": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.4" } @@ -15754,13 +16919,15 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/regexp.prototype.flags": { "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, + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "define-properties": "^1.2.1", @@ -15779,6 +16946,7 @@ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", @@ -15796,6 +16964,7 @@ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "jsesc": "~0.5.0" }, @@ -15817,6 +16986,7 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -15826,6 +16996,7 @@ "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, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -15834,13 +17005,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -15857,13 +17030,15 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -15873,6 +17048,7 @@ "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", "dev": true, + "license": "MIT", "dependencies": { "adjust-sourcemap-loader": "^4.0.0", "convert-source-map": "^1.7.0", @@ -15889,6 +17065,7 @@ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, + "license": "MIT", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -15903,6 +17080,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -15912,6 +17090,7 @@ "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", "dev": true, + "license": "MIT", "dependencies": { "lowercase-keys": "^2.0.0" }, @@ -15920,32 +17099,28 @@ } }, "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, + "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -15955,6 +17130,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -15964,13 +17140,68 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, + "license": "MIT", "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -15981,6 +17212,7 @@ "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "dependencies": { "boolean": "^3.0.1", @@ -15995,10 +17227,11 @@ } }, "node_modules/rollup": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.19.2.tgz", - "integrity": "sha512-6/jgnN1svF9PjNYJ4ya3l+cqutg49vOZ4rVgsDKxdl+5gpGPnByFXWGyfH9YGx9i3nfBwSu1Iyu6vGwFFA0BdQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "1.0.5" }, @@ -16010,22 +17243,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.19.2", - "@rollup/rollup-android-arm64": "4.19.2", - "@rollup/rollup-darwin-arm64": "4.19.2", - "@rollup/rollup-darwin-x64": "4.19.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.19.2", - "@rollup/rollup-linux-arm-musleabihf": "4.19.2", - "@rollup/rollup-linux-arm64-gnu": "4.19.2", - "@rollup/rollup-linux-arm64-musl": "4.19.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.19.2", - "@rollup/rollup-linux-riscv64-gnu": "4.19.2", - "@rollup/rollup-linux-s390x-gnu": "4.19.2", - "@rollup/rollup-linux-x64-gnu": "4.19.2", - "@rollup/rollup-linux-x64-musl": "4.19.2", - "@rollup/rollup-win32-arm64-msvc": "4.19.2", - "@rollup/rollup-win32-ia32-msvc": "4.19.2", - "@rollup/rollup-win32-x64-msvc": "4.19.2", + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", "fsevents": "~2.3.2" } }, @@ -16034,6 +17267,7 @@ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -16060,6 +17294,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -16068,6 +17303,7 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" } @@ -16077,6 +17313,7 @@ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", @@ -16108,13 +17345,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -16131,13 +17370,15 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/sanitize-filename": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", "dev": true, + "license": "WTFPL OR ISC", "dependencies": { "truncate-utf8-bytes": "^1.0.0" } @@ -16147,6 +17388,7 @@ "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz", "integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==", "dev": true, + "license": "MIT", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -16164,6 +17406,7 @@ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-14.2.1.tgz", "integrity": "sha512-G0VcnMYU18a4N7VoNDegg2OuMjYtxnqzQWARVWCIVSZwJeiL9kg8QMsuIZOplsJgTzZLF6jGxI3AClj8I9nRdQ==", "dev": true, + "license": "MIT", "dependencies": { "neo-async": "^2.6.2" }, @@ -16203,13 +17446,15 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -16229,6 +17474,7 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -16245,12 +17491,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/selecto": { "version": "1.26.3", "resolved": "https://registry.npmjs.org/selecto/-/selecto-1.26.3.tgz", "integrity": "sha512-gZHgqMy5uyB6/2YDjv3Qqaf7bd2hTDOpPdxXlrez4R3/L0GiEWDCFaUfrflomgqdb3SxHF2IXY0Jw0EamZi7cw==", + "license": "MIT", "dependencies": { "@daybrush/utils": "^1.13.0", "@egjs/children-differ": "^1.0.1", @@ -16269,6 +17517,7 @@ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/node-forge": "^1.3.0", "node-forge": "^1" @@ -16282,6 +17531,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -16294,6 +17544,7 @@ "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/send": { @@ -16301,6 +17552,7 @@ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dev": true, + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -16325,6 +17577,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -16333,13 +17586,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -16351,13 +17606,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/serialize-error": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "type-fest": "^0.13.1" @@ -16374,6 +17631,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "optional": true, "engines": { "node": ">=10" @@ -16387,6 +17645,7 @@ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -16396,6 +17655,7 @@ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", @@ -16414,6 +17674,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -16423,6 +17684,7 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -16432,6 +17694,7 @@ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", "dev": true, + "license": "MIT", "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -16446,25 +17709,29 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/serve-index/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/serve-index/node_modules/setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/serve-index/node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -16474,6 +17741,7 @@ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dev": true, + "license": "MIT", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -16489,6 +17757,7 @@ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -16506,6 +17775,7 @@ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -16520,19 +17790,22 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, + "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -16546,6 +17819,7 @@ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, + "license": "MIT", "dependencies": { "kind-of": "^6.0.2" }, @@ -16558,6 +17832,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -16570,6 +17845,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -16579,6 +17855,7 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -16588,6 +17865,7 @@ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -16606,6 +17884,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -16618,6 +17897,7 @@ "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.3.1.tgz", "integrity": "sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^2.3.2", "@sigstore/core": "^1.0.0", @@ -16635,6 +17915,7 @@ "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -16647,6 +17928,7 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -16659,6 +17941,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "ansi-styles": "^4.0.0", @@ -16674,6 +17957,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "color-convert": "^2.0.1" @@ -16690,6 +17974,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "color-name": "~1.1.4" @@ -16703,6 +17988,7 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/smart-buffer": { @@ -16710,6 +17996,7 @@ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -16720,6 +18007,7 @@ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, + "license": "MIT", "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", @@ -16731,6 +18019,7 @@ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dev": true, + "license": "MIT", "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" @@ -16745,6 +18034,7 @@ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^7.1.1", "debug": "^4.3.4", @@ -16759,6 +18049,7 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4" }, @@ -16771,6 +18062,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">= 8" } @@ -16780,6 +18072,7 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -16789,6 +18082,7 @@ "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-5.0.0.tgz", "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", "dev": true, + "license": "MIT", "dependencies": { "iconv-lite": "^0.6.3", "source-map-js": "^1.0.2" @@ -16809,6 +18103,7 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -16819,6 +18114,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -16828,6 +18124,7 @@ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -16837,13 +18134,15 @@ "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 + "dev": true, + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -16853,13 +18152,15 @@ "version": "3.0.18", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", - "dev": true + "dev": true, + "license": "CC0-1.0" }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", @@ -16876,6 +18177,7 @@ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -16889,13 +18191,15 @@ "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 + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/ssri": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -16908,6 +18212,7 @@ "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -16917,6 +18222,7 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -16926,6 +18232,7 @@ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "~2.0.4", "readable-stream": "^3.5.0" @@ -16936,6 +18243,7 @@ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", "dev": true, + "license": "MIT", "dependencies": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.4", @@ -16948,6 +18256,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -16957,6 +18266,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -16972,6 +18282,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -16986,6 +18297,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -17004,6 +18316,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -17022,6 +18335,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -17036,6 +18350,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -17053,6 +18368,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -17066,6 +18382,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -17078,6 +18395,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -17087,6 +18405,7 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -17096,6 +18415,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -17108,6 +18428,7 @@ "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "debug": "^4.1.0" }, @@ -17120,6 +18441,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -17132,6 +18454,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -17144,6 +18467,7 @@ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10" } @@ -17153,6 +18477,7 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -17162,6 +18487,7 @@ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -17179,6 +18505,7 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "bl": "^4.0.3", @@ -17196,6 +18523,7 @@ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -17208,6 +18536,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -17220,6 +18549,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=8" } @@ -17228,13 +18558,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/temp-file": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", "dev": true, + "license": "MIT", "dependencies": { "async-exit-hook": "^2.0.1", "fs-extra": "^10.0.0" @@ -17245,6 +18577,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -17259,6 +18592,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -17271,6 +18605,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -17280,6 +18615,7 @@ "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz", "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -17298,6 +18634,7 @@ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", @@ -17332,6 +18669,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -17348,6 +18686,7 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, + "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } @@ -17356,13 +18695,15 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -17380,19 +18721,22 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/thingies": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", "dev": true, + "license": "Unlicense", "engines": { "node": ">=10.18" }, @@ -17404,13 +18748,15 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/timers-browserify": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", "dev": true, + "license": "MIT", "dependencies": { "setimmediate": "^1.0.4" }, @@ -17423,6 +18769,7 @@ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, + "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -17435,6 +18782,7 @@ "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", "dev": true, + "license": "MIT", "dependencies": { "tmp": "^0.2.0" } @@ -17444,6 +18792,7 @@ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.14" } @@ -17453,6 +18802,7 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -17462,6 +18812,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -17474,6 +18825,7 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.6" } @@ -17483,6 +18835,7 @@ "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.0" }, @@ -17499,6 +18852,7 @@ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, + "license": "MIT", "bin": { "tree-kill": "cli.js" } @@ -17508,6 +18862,7 @@ "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", "dev": true, + "license": "WTFPL", "dependencies": { "utf8-byte-length": "^1.0.1" } @@ -17517,6 +18872,7 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -17529,6 +18885,7 @@ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -17572,6 +18929,7 @@ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, + "license": "MIT", "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", @@ -17584,19 +18942,22 @@ "node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "license": "0BSD" }, "node_modules/tty-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tuf-js": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz", "integrity": "sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==", "dev": true, + "license": "MIT", "dependencies": { "@tufjs/models": "2.0.1", "debug": "^4.3.4", @@ -17611,6 +18972,7 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -17623,6 +18985,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -17635,6 +18998,7 @@ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -17648,6 +19012,7 @@ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -17662,6 +19027,7 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -17681,6 +19047,7 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -17701,6 +19068,7 @@ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -17720,13 +19088,15 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -17740,6 +19110,7 @@ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.0.tgz", "integrity": "sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/eslint-plugin": "8.0.0", "@typescript-eslint/parser": "8.0.0", @@ -17763,6 +19134,7 @@ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -17778,6 +19150,7 @@ "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.2.tgz", "integrity": "sha512-JfjKqIauur3Q6biAtHJ564e3bWa8VvT+7cSiOJHFbX4Erv6CLGDpg8z+Fmg/1OI/47RA+GI2QZaF48SSaLvyBA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18.17" } @@ -17786,13 +19159,15 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -17802,6 +19177,7 @@ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, + "license": "MIT", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -17815,6 +19191,7 @@ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -17824,6 +19201,7 @@ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -17833,6 +19211,7 @@ "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -17845,6 +19224,7 @@ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", "dev": true, + "license": "ISC", "dependencies": { "unique-slug": "^4.0.0" }, @@ -17857,6 +19237,7 @@ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, @@ -17869,6 +19250,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.0.0" } @@ -17878,6 +19260,7 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -17901,6 +19284,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" @@ -17917,37 +19301,45 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", "dev": true, + "license": "MIT", "dependencies": { "punycode": "^1.4.1", - "qs": "^6.11.2" + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/url/node_modules/punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/utf8-byte-length": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", - "dev": true + "dev": true, + "license": "(WTFPL OR MIT)" }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", @@ -17960,13 +19352,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -17976,6 +19370,7 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -17984,13 +19379,15 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -18001,6 +19398,7 @@ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -18010,6 +19408,7 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -18019,6 +19418,7 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "assert-plus": "^1.0.0", @@ -18034,6 +19434,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.2.tgz", "integrity": "sha512-6lA7OBHBlXUxiJxbO5aAY2fsHHzDr1q7DvXYnyZycRs2Dz+dXBWuhpWHvmljTRTpQC2uvGmUFFkSHF2vGo90MA==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.38", @@ -18088,13 +19489,15 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wait-on": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", "dev": true, + "license": "MIT", "dependencies": { "axios": "^1.6.1", "joi": "^17.11.0", @@ -18114,6 +19517,7 @@ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", "dev": true, + "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -18127,6 +19531,7 @@ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, + "license": "MIT", "dependencies": { "minimalistic-assert": "^1.0.0" } @@ -18136,6 +19541,7 @@ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, + "license": "MIT", "dependencies": { "defaults": "^1.0.3" } @@ -18144,13 +19550,15 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/webpack": { "version": "5.93.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -18199,6 +19607,7 @@ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.2.1.tgz", "integrity": "sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA==", "dev": true, + "license": "MIT", "dependencies": { "colorette": "^2.0.10", "memfs": "^4.6.0", @@ -18228,6 +19637,7 @@ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", "dev": true, + "license": "MIT", "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", @@ -18282,31 +19692,12 @@ } } }, - "node_modules/webpack-dev-server/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", "dev": true, + "license": "MIT", "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -18326,41 +19717,12 @@ } } }, - "node_modules/webpack-dev-server/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/webpack-dev-server/node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dev": true, + "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", @@ -18375,6 +19737,7 @@ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.13.0" } @@ -18384,6 +19747,7 @@ "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", "dev": true, + "license": "MIT", "dependencies": { "typed-assert": "^1.0.8" }, @@ -18405,6 +19769,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -18422,6 +19787,7 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, + "license": "MIT", "peer": true, "peerDependencies": { "ajv": "^6.9.1" @@ -18432,6 +19798,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "dependencies": { "esrecurse": "^4.3.0", @@ -18446,6 +19813,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=4.0" @@ -18456,6 +19824,7 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/webpack/node_modules/json-schema-traverse": { @@ -18463,6 +19832,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/webpack/node_modules/schema-utils": { @@ -18470,6 +19840,7 @@ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@types/json-schema": "^7.0.8", @@ -18489,6 +19860,7 @@ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", @@ -18503,6 +19875,7 @@ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=0.8.0" } @@ -18510,13 +19883,15 @@ "node_modules/wheel": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wheel/-/wheel-1.0.0.tgz", - "integrity": "sha512-XiCMHibOiqalCQ+BaNSwRoZ9FDTAvOsXxGHXChBugewDj7HC8VBIER71dEOiRH1fSdLbRCQzngKTSiZ06ZQzeA==" + "integrity": "sha512-XiCMHibOiqalCQ+BaNSwRoZ9FDTAvOsXxGHXChBugewDj7HC8VBIER71dEOiRH1fSdLbRCQzngKTSiZ06ZQzeA==", + "license": "MIT" }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -18532,6 +19907,7 @@ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, + "license": "MIT", "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -18548,6 +19924,7 @@ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -18566,13 +19943,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true + "dev": true, + "license": "MIT" }, "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, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -18582,6 +19961,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -18597,6 +19977,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -18614,6 +19995,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -18629,6 +20011,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -18640,13 +20023,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -18662,6 +20047,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -18673,19 +20059,22 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -18707,6 +20096,7 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0" } @@ -18716,6 +20106,7 @@ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4" } @@ -18725,6 +20116,7 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -18733,13 +20125,15 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -18758,6 +20152,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } @@ -18767,6 +20162,7 @@ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, + "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -18777,6 +20173,7 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -18786,6 +20183,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -18798,6 +20196,7 @@ "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -18810,6 +20209,7 @@ "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "archiver-utils": "^3.0.4", @@ -18825,6 +20225,7 @@ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "glob": "^7.2.3", @@ -18845,7 +20246,8 @@ "node_modules/zone.js": { "version": "0.14.8", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.8.tgz", - "integrity": "sha512-48uh7MnVp4/OQDuCHeFdXw5d8xwPqFTvlHgPJ1LBFb5GaustLSZV+YUH0to5ygNyGpqTsjpbpt141U/j3pCfqQ==" + "integrity": "sha512-48uh7MnVp4/OQDuCHeFdXw5d8xwPqFTvlHgPJ1LBFb5GaustLSZV+YUH0to5ygNyGpqTsjpbpt141U/j3pCfqQ==", + "license": "MIT" } } } From a773eee674473fd642d3591dba50f4aaca1a59bd Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 3 Aug 2024 11:10:10 -0300 Subject: [PATCH 089/104] [desktop]: Generate application info on build and use it on About --- desktop/app/main.ts | 2 +- desktop/eslint.config.mjs | 4 ++ desktop/package.json | 8 ++-- desktop/scripts/nebulosa.mjs | 47 +++++++++++++++++++ desktop/src/app/about/about.component.html | 12 +++-- desktop/src/app/about/about.component.ts | 21 ++++----- desktop/src/app/home/home.component.ts | 5 +- desktop/src/assets/data/.gitignore | 1 + desktop/src/shared/pipes/skyObject.pipe.ts | 6 +-- .../src/shared/services/electron.service.ts | 6 +-- .../shared/services/remote-storage.service.ts | 30 ------------ 11 files changed, 82 insertions(+), 60 deletions(-) create mode 100644 desktop/scripts/nebulosa.mjs create mode 100644 desktop/src/assets/data/.gitignore delete mode 100644 desktop/src/shared/services/remote-storage.service.ts diff --git a/desktop/app/main.ts b/desktop/app/main.ts index 59c2ea254..4f3c7b2ad 100644 --- a/desktop/app/main.ts +++ b/desktop/app/main.ts @@ -69,7 +69,7 @@ async function startApp() { if (text) { const regex = /server is started at port: (\d+)/i - const match = text.match(regex) + const match = regex.exec(text) if (match) { const port = parseInt(match[1]) diff --git a/desktop/eslint.config.mjs b/desktop/eslint.config.mjs index 6176d33fc..32b27756c 100644 --- a/desktop/eslint.config.mjs +++ b/desktop/eslint.config.mjs @@ -2,6 +2,9 @@ import eslint from '@eslint/js' import tseslint from 'typescript-eslint' export default tseslint.config( + { + ignores: ['**/*.mjs'], + }, { files: ['**/*.ts'], ...eslint.configs.recommended, @@ -33,6 +36,7 @@ export default tseslint.config( rules: { 'no-unused-vars': 'off', 'no-loss-of-precision': 'off', + 'no-extra-semi': 'warn', '@typescript-eslint/no-unused-vars': 'warn', '@typescript-eslint/no-loss-of-precision': 'off', '@typescript-eslint/restrict-template-expressions': 'off', diff --git a/desktop/package.json b/desktop/package.json index bf67d2c86..e6e43e6e4 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -12,11 +12,12 @@ "main": "app/main.js", "private": true, "scripts": { - "postinstall": "electron-builder install-app-deps", + "postinstall": "electron-builder install-app-deps && npm run scripts", "ng": "ng", + "scripts": "node --no-warnings scripts/nebulosa.mjs", "start": "npm-run-all -p electron:serve ng:serve", "ng:serve": "ng serve -c web --hmr", - "build": "npm run electron:serve-tsc && ng build --base-href ./", + "build": "npm run scripts && npm run electron:serve-tsc && ng build --base-href ./", "build:dev": "npm run build -- -c dev", "build:prod": "npm run build -- -c production", "web:build": "npm run build -- -c web-production", @@ -31,8 +32,7 @@ "lint": "npx eslint .", "prettier:ts": "npx prettier '**/*.ts' --write", "prettier:html": "npx prettier '**/*.html' --write", - "prettier:scss": "npx prettier '**/*.scss' --write", - "prettier:json": "npx prettier '**/*.json' --write" + "prettier:scss": "npx prettier '**/*.scss' --write" }, "dependencies": { "@angular/animations": "18.1.3", diff --git a/desktop/scripts/nebulosa.mjs b/desktop/scripts/nebulosa.mjs new file mode 100644 index 000000000..b8951e41b --- /dev/null +++ b/desktop/scripts/nebulosa.mjs @@ -0,0 +1,47 @@ +import { execSync } from 'child_process' +import fs from 'fs' +import mainPackageJson from '../app/package.json' with { type: 'json' } +import rendererPackageJson from '../package.json' with { type: 'json' } + +const dependencies = [] + +if (rendererPackageJson.dependencies) { + for (const [name, version] of Object.entries(rendererPackageJson.dependencies).filter((e) => !e[1].includes('#'))) { + dependencies.push({ name, version }) + } +} + +if (mainPackageJson.dependencies) { + for (const [name, version] of Object.entries(mainPackageJson.dependencies).filter((e) => !e[1].includes('#'))) { + dependencies.push({ name, version }) + } +} + +if (rendererPackageJson.devDependencies) { + for (const [name, version] of Object.entries(rendererPackageJson.devDependencies).filter((e) => !e[1].includes('#'))) { + dependencies.push({ name, version }) + } +} + +if (mainPackageJson.devDependencies) { + for (const [name, version] of Object.entries(mainPackageJson.devDependencies).filter((e) => !e[1].includes('#'))) { + dependencies.push({ name, version }) + } +} + +dependencies.sort((a, b) => a.name.localeCompare(b.name)) + +const data = { + name: rendererPackageJson.name, + codename: rendererPackageJson.codename, + version: rendererPackageJson.version, + description: rendererPackageJson.description, + author: rendererPackageJson.author, + build: { + commit: execSync('git rev-parse HEAD').toString().trim(), + date: new Date().toISOString(), + }, + dependencies, +} + +fs.writeFileSync('src/assets/data/nebulosa.json', JSON.stringify(data)) diff --git a/desktop/src/app/about/about.component.html b/desktop/src/app/about/about.component.html index f63d817d8..7c59df1fe 100644 --- a/desktop/src/app/about/about.component.html +++ b/desktop/src/app/about/about.component.html @@ -38,11 +38,17 @@
-

This software is WIP, comes with absolutely no warranty and the copyright holder is not liable or responsible for anything.

+

This software is WIP, comes with absolutely no warranty and the copyright holder is not liable or responsible for anything.

+
+ +
+ COMMIT: {{ commit }} + DATE: {{ date }} +
@for (icon of icons; track $index) {
@for (dep of dependencies; track $index) { (type: K) { + private async openDevice(type: keyof MappedDevice) { this.deviceModel.length = 0 const devices: Device[] = @@ -362,8 +362,7 @@ export class HomeComponent implements AfterContentInit { : type === 'MOUNT' ? this.mounts : type === 'FOCUSER' ? this.focusers : type === 'WHEEL' ? this.wheels - : type === 'ROTATOR' ? this.rotators - : [] + : this.rotators if (devices.length === 0) return diff --git a/desktop/src/assets/data/.gitignore b/desktop/src/assets/data/.gitignore new file mode 100644 index 000000000..7850aa44f --- /dev/null +++ b/desktop/src/assets/data/.gitignore @@ -0,0 +1 @@ +nebulosa.json diff --git a/desktop/src/shared/pipes/skyObject.pipe.ts b/desktop/src/shared/pipes/skyObject.pipe.ts index a73df5489..c8b414f03 100644 --- a/desktop/src/shared/pipes/skyObject.pipe.ts +++ b/desktop/src/shared/pipes/skyObject.pipe.ts @@ -2,9 +2,7 @@ import { Pipe, PipeTransform } from '@angular/core' import { AstronomicalObject } from '../types/atlas.types' import { Undefinable } from '../utils/types' -const SKY_OBJECT_PARTS = ['name', 'firstName'] as const - -export type SkyObjectPart = (typeof SKY_OBJECT_PARTS)[number] +export type SkyObjectPart = 'name' | 'firstName' @Pipe({ name: 'skyObject' }) export class SkyObjectPipe implements PipeTransform { @@ -13,7 +11,7 @@ export class SkyObjectPipe implements PipeTransform { case 'name': return value?.name.replaceAll('|', ' ยท ') case 'firstName': - return value?.name.split(/\[([^\]]+)\]/g).filter(Boolean)[0] + return value?.name.split(/\[([^\]]+)\]/g).find(Boolean) default: return `${value}` } diff --git a/desktop/src/shared/services/electron.service.ts b/desktop/src/shared/services/electron.service.ts index 1e275d470..9609f6eeb 100644 --- a/desktop/src/shared/services/electron.service.ts +++ b/desktop/src/shared/services/electron.service.ts @@ -4,9 +4,9 @@ import { Injectable } from '@angular/core' // other than as TypeScript types, the resulting javascript file will // look as if you never imported the module at all. -import * as childProcess from 'child_process' -import { ipcRenderer, webFrame } from 'electron' -import * as fs from 'fs' +import type * as childProcess from 'child_process' +import type { ipcRenderer, webFrame } from 'electron' +import type * as fs from 'fs' import { DARVEvent, TPPAEvent } from '../types/alignment.types' import { DeviceMessageEvent } from '../types/api.types' import { CloseWindow, ConfirmationEvent, FullscreenWindow, JsonFile, NotificationEvent, OpenDirectory, OpenFile, ResizeWindow, SaveJson, WindowCommand } from '../types/app.types' diff --git a/desktop/src/shared/services/remote-storage.service.ts b/desktop/src/shared/services/remote-storage.service.ts deleted file mode 100644 index ade4eba8f..000000000 --- a/desktop/src/shared/services/remote-storage.service.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Injectable } from '@angular/core' -import { Undefinable } from '../utils/types' -import { ApiService } from './api.service' -import { StorageService } from './storage.service' - -@Injectable({ providedIn: 'root' }) -export class RemoteStorageService implements StorageService { - constructor(private readonly api: ApiService) {} - - clear() { - return this.api.clearPreferences() - } - - delete(key: string) { - return this.api.deletePreference(key) - } - - async get(key: string, defaultValue: T) { - return (await this.api.getPreference>(key)) ?? defaultValue - } - - has(key: string) { - return this.api.hasPreference(key) - } - - set(key: string, value: unknown) { - if (value === null || value === undefined) return this.delete(key) - else return this.api.setPreference(key, value) - } -} From f9367abc8a2d89f9004e95ac0ee7e55ddf2874bb Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sat, 3 Aug 2024 12:00:58 -0300 Subject: [PATCH 090/104] [desktop]: Move the buttons that open Camera's Image --- desktop/eslint.config.mjs | 7 + desktop/src/app/home/home.component.html | 8 +- desktop/src/app/home/home.component.ts | 293 ++++++++++++----------- desktop/src/shared/types/wheel.types.ts | 2 +- 4 files changed, 169 insertions(+), 141 deletions(-) diff --git a/desktop/eslint.config.mjs b/desktop/eslint.config.mjs index 32b27756c..900b0beff 100644 --- a/desktop/eslint.config.mjs +++ b/desktop/eslint.config.mjs @@ -58,6 +58,13 @@ export default tseslint.config( ignorePrimitives: true, }, ], + '@typescript-eslint/no-unused-expressions': [ + 'error', + { + allowShortCircuit: true, + allowTernary: true, + }, + ], }, }, ) diff --git a/desktop/src/app/home/home.component.html b/desktop/src/app/home/home.component.html index f2de2bf52..6dbb5e008 100644 --- a/desktop/src/app/home/home.component.html +++ b/desktop/src/app/home/home.component.html @@ -359,9 +359,5 @@ #deviceMenu [disableIfDeviceIsNotConnected]="false" (deviceConnect)="deviceConnected($event)" - (deviceDisconnect)="deviceDisconnected($event)" /> - + (deviceDisconnect)="deviceDisconnected($event)" + [toolbarBuilder]="deviceMenuToolbarBuilder" /> diff --git a/desktop/src/app/home/home.component.ts b/desktop/src/app/home/home.component.ts index cb49b7d6e..24ad324c9 100644 --- a/desktop/src/app/home/home.component.ts +++ b/desktop/src/app/home/home.component.ts @@ -8,23 +8,15 @@ import { BrowserWindowService } from '../../shared/services/browser-window.servi import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' import { PrimeService } from '../../shared/services/prime.service' -import { Camera } from '../../shared/types/camera.types' -import { Device } from '../../shared/types/device.types' -import { Focuser } from '../../shared/types/focuser.types' +import { Camera, isCamera } from '../../shared/types/camera.types' +import { Device, DeviceType } from '../../shared/types/device.types' +import { Focuser, isFocuser } from '../../shared/types/focuser.types' import { ConnectionDetails, DEFAULT_CONNECTION_DETAILS, DEFAULT_HOME_CONNECTION_DIALOG, DEFAULT_HOME_PREFERENCE, HomeWindowType } from '../../shared/types/home.types' -import { Mount } from '../../shared/types/mount.types' -import { Rotator } from '../../shared/types/rotator.types' -import { Wheel } from '../../shared/types/wheel.types' +import { isMount, Mount } from '../../shared/types/mount.types' +import { isRotator, Rotator } from '../../shared/types/rotator.types' +import { isWheel, Wheel } from '../../shared/types/wheel.types' import { AppComponent } from '../app.component' -interface MappedDevice { - CAMERA: Camera - MOUNT: Mount - FOCUSER: Focuser - WHEEL: Wheel - ROTATOR: Rotator -} - function scrollPageOf(element: Element) { return parseInt(element.getAttribute('scroll-page') ?? '0') } @@ -58,7 +50,7 @@ export class HomeComponent implements AfterContentInit { label: 'Open new image', slideMenu: [], command: () => { - return this.openImage(true) + return this.openImage() }, }, ] @@ -66,9 +58,6 @@ export class HomeComponent implements AfterContentInit { @ViewChild('deviceMenu') private readonly deviceMenu!: DeviceListMenuComponent - @ViewChild('imageMenu') - private readonly imageMenu!: DeviceListMenuComponent - get connected() { return !!this.connection && this.connection.connected } @@ -133,6 +122,22 @@ export class HomeComponent implements AfterContentInit { return this.connection?.type === 'ALPACA' && this.hasDevices } + protected readonly deviceMenuToolbarBuilder = (device: Device): MenuItem[] => { + if (isCamera(device)) { + return [ + { + icon: 'mdi mdi-image', + label: 'View Image', + command: () => { + return this.browserWindowService.openCameraImage(device) + }, + }, + ] + } else { + return [] + } + } + constructor( app: AppComponent, private readonly electronService: ElectronService, @@ -140,94 +145,89 @@ export class HomeComponent implements AfterContentInit { private readonly api: ApiService, private readonly primeService: PrimeService, private readonly preferenceService: PreferenceService, - private readonly ngZone: NgZone, + ngZone: NgZone, ) { app.title = 'Nebulosa' - this.startListening( - 'CAMERA', - (device) => { - return this.cameras.push(device) - }, - (device) => { - const found = this.cameras.findIndex((e) => e.id === device.id) - this.cameras.splice(found, 1) - return this.cameras.length - }, - (device) => { - const found = this.cameras.find((e) => e.id === device.id) - if (!found) return - Object.assign(found, device) - }, - ) + electronService.on('CAMERA.ATTACHED', (event) => { + ngZone.run(() => { + this.deviceAdded(event.device) + }) + }) + electronService.on(`CAMERA.DETACHED`, (event) => { + ngZone.run(() => { + this.deviceRemoved(event.device) + }) + }) + electronService.on(`CAMERA.UPDATED`, (event) => { + ngZone.run(() => { + this.deviceUpdated(event.device) + }) + }) - this.startListening( - 'MOUNT', - (device) => { - return this.mounts.push(device) - }, - (device) => { - const found = this.mounts.findIndex((e) => e.id === device.id) - this.mounts.splice(found, 1) - return this.mounts.length - }, - (device) => { - const found = this.mounts.find((e) => e.id === device.id) - if (!found) return - Object.assign(found, device) - }, - ) + electronService.on('MOUNT.ATTACHED', (event) => { + ngZone.run(() => { + this.deviceAdded(event.device) + }) + }) + electronService.on(`MOUNT.DETACHED`, (event) => { + ngZone.run(() => { + this.deviceRemoved(event.device) + }) + }) + electronService.on(`MOUNT.UPDATED`, (event) => { + ngZone.run(() => { + this.deviceUpdated(event.device) + }) + }) - this.startListening( - 'FOCUSER', - (device) => { - return this.focusers.push(device) - }, - (device) => { - const found = this.focusers.findIndex((e) => e.id === device.id) - this.focusers.splice(found, 1) - return this.focusers.length - }, - (device) => { - const found = this.focusers.find((e) => e.id === device.id) - if (!found) return - Object.assign(found, device) - }, - ) + electronService.on('FOCUSER.ATTACHED', (event) => { + ngZone.run(() => { + this.deviceAdded(event.device) + }) + }) + electronService.on(`FOCUSER.DETACHED`, (event) => { + ngZone.run(() => { + this.deviceRemoved(event.device) + }) + }) + electronService.on(`FOCUSER.UPDATED`, (event) => { + ngZone.run(() => { + this.deviceUpdated(event.device) + }) + }) - this.startListening( - 'WHEEL', - (device) => { - return this.wheels.push(device) - }, - (device) => { - const found = this.wheels.findIndex((e) => e.id === device.id) - this.wheels.splice(found, 1) - return this.wheels.length - }, - (device) => { - const found = this.wheels.find((e) => e.id === device.id) - if (!found) return - Object.assign(found, device) - }, - ) + electronService.on('WHEEL.ATTACHED', (event) => { + ngZone.run(() => { + this.deviceAdded(event.device) + }) + }) + electronService.on(`WHEEL.DETACHED`, (event) => { + ngZone.run(() => { + this.deviceRemoved(event.device) + }) + }) + electronService.on(`WHEEL.UPDATED`, (event) => { + ngZone.run(() => { + this.deviceUpdated(event.device) + }) + }) - this.startListening( - 'ROTATOR', - (device) => { - return this.rotators.push(device) - }, - (device) => { - const found = this.rotators.findIndex((e) => e.id === device.id) - this.rotators.splice(found, 1) - return this.rotators.length - }, - (device) => { - const found = this.rotators.find((e) => e.id === device.id) - if (!found) return - Object.assign(found, device) - }, - ) + electronService.on('ROTATOR.ATTACHED', (event) => { + ngZone.run(() => { + this.deviceAdded(event.device) + }) + }) + electronService.on(`ROTATOR.DETACHED`, (event) => { + ngZone.run(() => { + this.deviceRemoved(event.device) + }) + }) + electronService.on(`ROTATOR.UPDATED`, (event) => { + ngZone.run(() => { + this.deviceUpdated(event.device) + }) + }) electronService.on('CONNECTION.CLOSED', async (event) => { if (this.connection?.id === event.id) { @@ -252,24 +252,56 @@ export class HomeComponent implements AfterContentInit { } } - private startListening(type: K, onAdd: (device: MappedDevice[K]) => number, onRemove: (device: MappedDevice[K]) => number, onUpdate: (device: MappedDevice[K]) => void) { - this.electronService.on(`${type}.ATTACHED`, (event) => { - this.ngZone.run(() => { - onAdd(event.device as never) - }) - }) + private deviceAdded(device: Device) { + if (isCamera(device)) { + this.cameras.push(device) + } else if (isMount(device)) { + this.mounts.push(device) + } else if (isFocuser(device)) { + this.focusers.push(device) + } else if (isWheel(device)) { + this.wheels.push(device) + } else if (isRotator(device)) { + this.rotators.push(device) + } + } - this.electronService.on(`${type}.DETACHED`, (event) => { - this.ngZone.run(() => { - onRemove(event.device as never) - }) - }) + private deviceRemoved(device: Device) { + if (isCamera(device)) { + const found = this.cameras.findIndex((e) => e.id === device.id) + this.cameras.splice(found, 1) + } else if (isMount(device)) { + const found = this.mounts.findIndex((e) => e.id === device.id) + this.mounts.splice(found, 1) + } else if (isFocuser(device)) { + const found = this.focusers.findIndex((e) => e.id === device.id) + this.focusers.splice(found, 1) + } else if (isWheel(device)) { + const found = this.wheels.findIndex((e) => e.id === device.id) + this.wheels.splice(found, 1) + } else if (isRotator(device)) { + const found = this.rotators.findIndex((e) => e.id === device.id) + this.rotators.splice(found, 1) + } + } - this.electronService.on(`${type}.UPDATED`, (event) => { - this.ngZone.run(() => { - onUpdate(event.device as never) - }) - }) + private deviceUpdated(device: Device) { + if (isCamera(device)) { + const found = this.cameras.find((e) => e.id === device.id) + found && Object.assign(found, device) + } else if (isMount(device)) { + const found = this.mounts.find((e) => e.id === device.id) + found && Object.assign(found, device) + } else if (isFocuser(device)) { + const found = this.focusers.find((e) => e.id === device.id) + found && Object.assign(found, device) + } else if (isWheel(device)) { + const found = this.wheels.find((e) => e.id === device.id) + found && Object.assign(found, device) + } else if (isRotator(device)) { + const found = this.rotators.find((e) => e.id === device.id) + found && Object.assign(found, device) + } } protected addConnection() { @@ -354,7 +386,7 @@ export class HomeComponent implements AfterContentInit { return DeviceChooserComponent.handleDisconnectDevice(this.api, event.device, event.item) } - private async openDevice(type: keyof MappedDevice) { + private async openDevice(type: DeviceType) { this.deviceModel.length = 0 const devices: Device[] = @@ -362,19 +394,20 @@ export class HomeComponent implements AfterContentInit { : type === 'MOUNT' ? this.mounts : type === 'FOCUSER' ? this.focusers : type === 'WHEEL' ? this.wheels - : this.rotators + : type === 'ROTATOR' ? this.rotators + : [] if (devices.length === 0) return const device = await this.deviceMenu.show(devices, undefined, type) if (device && device !== 'NONE') { - await this.openDeviceWindow(type, device as never) + await this.openDeviceWindow(device) } } - private async openDeviceWindow(type: K, device: MappedDevice[K]) { - switch (type) { + private async openDeviceWindow(device: Device) { + switch (device.type) { case 'MOUNT': await this.browserWindowService.openMount(device as Mount, { bringToFront: true }) break @@ -393,22 +426,14 @@ export class HomeComponent implements AfterContentInit { } } - private async openImage(force: boolean = false) { - if (force || this.cameras.length === 0) { - const path = await this.electronService.openImage({ defaultPath: this.preference.imagePath }) - - if (path) { - this.preference.imagePath = dirname(path) - this.savePreference() + private async openImage() { + const path = await this.electronService.openImage({ defaultPath: this.preference.imagePath }) - await this.browserWindowService.openImage({ path, source: 'PATH' }) - } - } else { - const camera = await this.imageMenu.show(this.cameras) + if (path) { + this.preference.imagePath = dirname(path) + this.savePreference() - if (camera && camera !== 'NONE') { - await this.browserWindowService.openCameraImage(camera) - } + await this.browserWindowService.openImage({ path, source: 'PATH' }) } } diff --git a/desktop/src/shared/types/wheel.types.ts b/desktop/src/shared/types/wheel.types.ts index 5287170a7..2ebb46491 100644 --- a/desktop/src/shared/types/wheel.types.ts +++ b/desktop/src/shared/types/wheel.types.ts @@ -71,7 +71,7 @@ export const DEFAULT_WHEEL_PREFERENCE: WheelPreference = { shutterPosition: 0, } -export function isFilterWheel(device?: Device): device is Wheel { +export function isWheel(device?: Device): device is Wheel { return !!device && device.type === 'WHEEL' } From 955a670a2fb46516998c49ee6230e3b8b344d9a2 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Sun, 4 Aug 2024 15:29:53 -0300 Subject: [PATCH 091/104] [api][desktop]: Refactor Image --- .../api/image/AnnotateImageRequest.kt | 9 + ...mageAnnotation.kt => ImageAnnotatation.kt} | 2 +- .../nebulosa/api/image/ImageController.kt | 11 +- .../kotlin/nebulosa/api/image/ImageInfo.kt | 4 +- .../kotlin/nebulosa/api/image/ImageService.kt | 53 +- .../nebulosa/api/image/ImageTransformation.kt | 7 +- .../api/platesolver/PlateSolverController.kt | 12 +- .../api/platesolver/PlateSolverRequest.kt | 9 + .../api/platesolver/PlateSolverService.kt | 17 +- desktop/app/window.manager.ts | 1 - desktop/src/app/app.module.ts | 4 +- .../app/calibration/calibration.component.ts | 1 - desktop/src/app/camera/camera.component.ts | 3 +- .../src/app/camera/exposure-time.component.ts | 40 +- .../app/filterwheel/filterwheel.component.ts | 2 - desktop/src/app/image/crosshair.component.ts | 53 ++ desktop/src/app/image/image.component.html | 301 ++++--- desktop/src/app/image/image.component.scss | 52 +- desktop/src/app/image/image.component.ts | 783 ++++++++---------- .../menu-bar/menu-bar.component.html | 2 +- .../menu-item/menu-item.component.html | 2 +- .../interceptors/confirmation.interceptor.ts | 2 - .../src/shared/pipes/dropdown-options.pipe.ts | 5 +- .../src/shared/pipes/enum-dropdown.pipe.ts | 8 +- desktop/src/shared/pipes/enum.pipe.ts | 4 +- desktop/src/shared/services/api.service.ts | 16 +- .../shared/services/confirmation.service.ts | 1 - .../src/shared/services/electron.service.ts | 2 - .../src/shared/services/preference.service.ts | 5 +- desktop/src/shared/types/angular.types.ts | 4 + desktop/src/shared/types/camera.types.ts | 9 +- desktop/src/shared/types/image.types.ts | 457 +++++++--- desktop/src/shared/types/platesolver.types.ts | 16 +- desktop/tsconfig.serve.json | 3 +- .../main/kotlin/nebulosa/fits/FitsFormat.kt | 5 +- .../nebulosa/fits/SeekableSourceImageData.kt | 10 +- .../transformation/ScreenTransformFunction.kt | 8 +- .../test/kotlin/FitsTransformAlgorithmTest.kt | 734 ++++++++-------- .../nebulosa/platesolver/PlateSolution.kt | 2 +- 39 files changed, 1404 insertions(+), 1255 deletions(-) create mode 100644 api/src/main/kotlin/nebulosa/api/image/AnnotateImageRequest.kt rename api/src/main/kotlin/nebulosa/api/image/{ImageAnnotation.kt => ImageAnnotatation.kt} (98%) create mode 100644 desktop/src/app/image/crosshair.component.ts create mode 100644 desktop/src/shared/types/angular.types.ts diff --git a/api/src/main/kotlin/nebulosa/api/image/AnnotateImageRequest.kt b/api/src/main/kotlin/nebulosa/api/image/AnnotateImageRequest.kt new file mode 100644 index 000000000..cc56de4e9 --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/image/AnnotateImageRequest.kt @@ -0,0 +1,9 @@ +package nebulosa.api.image + +data class AnnotateImageRequest( + @JvmField val starsAndDSOs: Boolean = true, + @JvmField val minorPlanets: Boolean = false, + @JvmField val minorPlanetMagLimit: Double = 12.0, + @JvmField val includeMinorPlanetsWithoutMagnitude: Boolean = false, + @JvmField val useSimbad: Boolean = false, +) diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageAnnotation.kt b/api/src/main/kotlin/nebulosa/api/image/ImageAnnotatation.kt similarity index 98% rename from api/src/main/kotlin/nebulosa/api/image/ImageAnnotation.kt rename to api/src/main/kotlin/nebulosa/api/image/ImageAnnotatation.kt index 1db713fd5..e6365e937 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageAnnotation.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageAnnotatation.kt @@ -12,7 +12,7 @@ import nebulosa.skycatalog.DeepSkyObject import nebulosa.skycatalog.SkyObject import nebulosa.skycatalog.SkyObjectType -data class ImageAnnotation( +data class ImageAnnotatation( override val x: Double, override val y: Double, @JvmField val star: StarDSO? = null, diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageController.kt b/api/src/main/kotlin/nebulosa/api/image/ImageController.kt index 6c6d29312..33d886df0 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageController.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageController.kt @@ -38,17 +38,12 @@ class ImageController( imageService.saveImageAs(path, save, camera) } - @GetMapping("annotations") + @PutMapping("annotations") fun annotationsOfImage( @RequestParam path: Path, - @RequestParam(required = false, defaultValue = "true") starsAndDSOs: Boolean, - @RequestParam(required = false, defaultValue = "false") minorPlanets: Boolean, - @RequestParam(required = false, defaultValue = "12.0") minorPlanetMagLimit: Double, - @RequestParam(required = false, defaultValue = "false") includeMinorPlanetsWithoutMagnitude: Boolean, - @RequestParam(required = false, defaultValue = "false") useSimbad: Boolean, + @RequestBody request: AnnotateImageRequest, @LocationParam location: Location? = null, - ) = imageService - .annotations(path, starsAndDSOs, minorPlanets, minorPlanetMagLimit, includeMinorPlanetsWithoutMagnitude, useSimbad, location) + ) = imageService.annotations(path, request, location) @GetMapping("coordinate-interpolation") fun coordinateInterpolation(@RequestParam path: Path): CoordinateInterpolation? { diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageInfo.kt b/api/src/main/kotlin/nebulosa/api/image/ImageInfo.kt index 9c41c8d78..757f7174d 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageInfo.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageInfo.kt @@ -14,9 +14,7 @@ data class ImageInfo( @JvmField val width: Int, @JvmField val height: Int, @JvmField val mono: Boolean, - @JvmField val stretchShadow: Float = 0.0f, - @JvmField val stretchHighlight: Float = 1.0f, - @JvmField val stretchMidtone: Float = 0.5f, + @JvmField val stretch: ImageTransformation.Stretch, @field:JsonSerialize(using = RightAscensionSerializer::class) @JvmField val rightAscension: Double? = null, @field:JsonSerialize(using = DeclinationSerializer::class) @JvmField val declination: Double? = null, @JvmField val solved: ImageSolved? = null, diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageService.kt b/api/src/main/kotlin/nebulosa/api/image/ImageService.kt index 69a022f33..ea7704882 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageService.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageService.kt @@ -7,7 +7,7 @@ import nebulosa.api.atlas.SimbadEntityRepository import nebulosa.api.calibration.CalibrationFrameService import nebulosa.api.connection.ConnectionService import nebulosa.api.framing.FramingService -import nebulosa.api.image.ImageAnnotation.StarDSO +import nebulosa.api.image.ImageAnnotatation.StarDSO import nebulosa.fits.* import nebulosa.image.Image import nebulosa.image.algorithms.computation.Histogram @@ -43,6 +43,7 @@ import java.util.* import java.util.concurrent.CompletableFuture import javax.imageio.ImageIO import kotlin.io.path.outputStream +import kotlin.math.roundToInt @Service class ImageService( @@ -65,7 +66,7 @@ class ImageService( private data class TransformedImage( @JvmField val image: Image, @JvmField val statistics: Statistics.Data? = null, - @JvmField val strectchParams: ScreenTransformFunction.Parameters? = null, + @JvmField val stretchParameters: ScreenTransformFunction.Parameters? = null, @JvmField val instrument: Camera? = null, ) @@ -85,12 +86,16 @@ class ImageService( output: HttpServletResponse, ) { val (image, calibration) = imageBucket.open(path, transformation.debayer, force = transformation.force) - val (transformedImage, statistics, stretchParams, instrument) = image!!.transform(true, transformation, ImageOperation.OPEN, camera) + val (transformedImage, statistics, stretchParameters, instrument) = image!!.transform(true, transformation, ImageOperation.OPEN, camera) val info = ImageInfo( path, transformedImage.width, transformedImage.height, transformedImage.mono, - stretchParams!!.shadow, stretchParams.highlight, stretchParams.midtone, + transformation.stretch.copy( + shadow = (stretchParameters!!.shadow * 65536f).roundToInt(), + highlight = (stretchParameters.highlight * 65536f).roundToInt(), + midtone = (stretchParameters.midtone * 65536f).roundToInt(), + ), transformedImage.header.rightAscension.takeIf { it.isFinite() }, transformedImage.header.declination.takeIf { it.isFinite() }, calibration?.let(::ImageSolved), @@ -98,10 +103,12 @@ class ImageService( transformedImage.header.bitpix, instrument, statistics, ) + val format = if (transformation.useJPEG) "jpeg" else "png" + output.addHeader(IMAGE_INFO_HEADER, objectMapper.writeValueAsString(info)) - output.contentType = "image/png" + output.contentType = "image/$format" - ImageIO.write(transformedImage, "PNG", output.outputStream) + ImageIO.write(transformedImage, format, output.outputStream) } private fun Image.transform( @@ -112,7 +119,7 @@ class ImageService( val (autoStretch, shadow, highlight, midtone) = transformation.stretch val scnrEnabled = transformation.scnr.channel != null - val manualStretch = shadow != 0f || highlight != 1f || midtone != 0.5f + val manualStretch = shadow != 0 || highlight != 65536 || midtone != 32768 val shouldBeTransformed = enabled && (autoStretch || manualStretch || transformation.mirrorHorizontal || transformation.mirrorVertical || transformation.invert @@ -166,13 +173,7 @@ class ImageService( } @Synchronized - fun annotations( - path: Path, - starsAndDSOs: Boolean, minorPlanets: Boolean, - minorPlanetMagLimit: Double = 12.0, includeMinorPlanetsWithoutMagnitude: Boolean = false, - useSimbad: Boolean = false, - location: Location? = null, - ): List { + fun annotations(path: Path, request: AnnotateImageRequest, location: Location? = null): List { val (image, calibration) = imageBucket.open(path) if (image == null || calibration.isNullOrEmpty() || !calibration.solved) { @@ -182,16 +183,16 @@ class ImageService( val wcs = try { WCS(calibration) } catch (e: WCSException) { - LOG.error("unable to generate annotations for image. path={}", path) + LOG.error("unable to generate annotations for image. path={}", path, e) return emptyList() } - val annotations = Vector(64) + val annotations = Vector(64) val tasks = ArrayList>(2) val dateTime = image.header.observationDate ?: LocalDateTime.now() - if (minorPlanets) { + if (request.minorPlanets) { threadPoolTaskExecutor.submitCompletable { val latitude = image.header.latitude ?: location?.latitude?.deg ?: 0.0 val longitude = image.header.longitude ?: location?.longitude?.deg ?: 0.0 @@ -204,7 +205,7 @@ class ImageService( val identifiedBody = smallBodyDatabaseService.identify( dateTime, latitude, longitude, 0.0, calibration.rightAscension, calibration.declination, calibration.radius, - minorPlanetMagLimit, !includeMinorPlanetsWithoutMagnitude, + request.minorPlanetMagLimit, !request.includeMinorPlanetsWithoutMagnitude, ).execute().body() ?: return@submitCompletable val radiusInSeconds = calibration.radius.toArcsec @@ -218,8 +219,8 @@ class ImageService( val declination = it[2].deg.takeIf(Angle::isFinite) ?: return@forEach val (x, y) = wcs.skyToPix(rightAscension, declination) val magnitude = it[6].replace(INVALID_MAG_CHARS, "").toDoubleOrNull() ?: SkyObject.UNKNOWN_MAGNITUDE - val minorPlanet = ImageAnnotation.MinorPlanet(0L, it[0], rightAscension, declination, magnitude) - val annotation = ImageAnnotation(x, y, minorPlanet = minorPlanet) + val minorPlanet = ImageAnnotatation.MinorPlanet(0L, it[0], rightAscension, declination, magnitude) + val annotation = ImageAnnotatation(x, y, minorPlanet = minorPlanet) annotations.add(annotation) count++ } @@ -230,15 +231,15 @@ class ImageService( .also(tasks::add) } - if (starsAndDSOs) { + if (request.starsAndDSOs) { threadPoolTaskExecutor.submitCompletable { - LOG.info("finding star/DSO annotations. dateTime={}, useSimbad={}, calibration={}", dateTime, useSimbad, calibration) + LOG.info("finding star/DSO annotations. dateTime={}, useSimbad={}, calibration={}", dateTime, request.useSimbad, calibration) val rightAscension = calibration.rightAscension val declination = calibration.declination val radius = calibration.radius - val catalog = if (useSimbad) { + val catalog = if (request.useSimbad) { simbadService.search(SimbadSearch.Builder().region(rightAscension, declination, radius).build()) } else { simbadEntityRepository.search(null, null, rightAscension, declination, radius) @@ -253,8 +254,8 @@ class ImageService( val astrometric = barycentric.observe(entry).equatorial() val (x, y) = wcs.skyToPix(astrometric.longitude.normalized, astrometric.latitude) - val annotation = if (entry.type.classification == ClassificationType.STAR) ImageAnnotation(x, y, star = StarDSO(entry)) - else ImageAnnotation(x, y, dso = StarDSO(entry)) + val annotation = if (entry.type.classification == ClassificationType.STAR) ImageAnnotatation(x, y, star = StarDSO(entry)) + else ImageAnnotatation(x, y, dso = StarDSO(entry)) annotations.add(annotation) count++ } @@ -308,7 +309,7 @@ class ImageService( val wcs = try { WCS(calibration) } catch (e: WCSException) { - LOG.error("unable to generate annotations for image. path={}", path) + LOG.error("unable to generate annotations for image. path={}", path, e) return null } diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageTransformation.kt b/api/src/main/kotlin/nebulosa/api/image/ImageTransformation.kt index 42455df07..ed20ba5c6 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageTransformation.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageTransformation.kt @@ -12,6 +12,7 @@ data class ImageTransformation( @JvmField val mirrorVertical: Boolean = false, @JvmField val invert: Boolean = false, @JvmField val scnr: SCNR = SCNR.EMPTY, + @JvmField val useJPEG: Boolean = false, ) { data class SCNR( @@ -28,9 +29,9 @@ data class ImageTransformation( data class Stretch( @JvmField val auto: Boolean = false, - @JvmField val shadow: Float = 0f, - @JvmField val highlight: Float = 0.5f, - @JvmField val midtone: Float = 1f, + @JvmField val shadow: Int = 0, + @JvmField val highlight: Int = 32768, + @JvmField val midtone: Int = 65536, ) { companion object { diff --git a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverController.kt b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverController.kt index 2d4ed2456..5e44131bf 100644 --- a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverController.kt +++ b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverController.kt @@ -1,8 +1,6 @@ package nebulosa.api.platesolver import jakarta.validation.Valid -import nebulosa.api.beans.converters.angle.AngleParam -import nebulosa.math.Angle import org.springframework.web.bind.annotation.* import java.nio.file.Path @@ -13,17 +11,13 @@ class PlateSolverController( ) { @PutMapping("start") - fun startSolver( + fun start( @RequestParam path: Path, @RequestBody @Valid solver: PlateSolverRequest, - @RequestParam(required = false, defaultValue = "true") blind: Boolean, - @AngleParam(required = false, isHours = true, defaultValue = "0.0") centerRA: Angle, - @AngleParam(required = false, defaultValue = "0.0") centerDEC: Angle, - @AngleParam(required = false, defaultValue = "4.0") radius: Angle, - ) = plateSolverService.solveImage(solver, path, centerRA, centerDEC, if (blind) 0.0 else radius) + ) = plateSolverService.solveImage(solver, path) @PutMapping("stop") - fun stopSolver() { + fun stop() { plateSolverService.stopSolver() } } diff --git a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverRequest.kt b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverRequest.kt index 7dba84bbe..af3219921 100644 --- a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverRequest.kt @@ -1,9 +1,14 @@ package nebulosa.api.platesolver +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import nebulosa.api.beans.converters.angle.DeclinationDeserializer +import nebulosa.api.beans.converters.angle.DegreesDeserializer +import nebulosa.api.beans.converters.angle.RightAscensionDeserializer import nebulosa.astap.platesolver.AstapPlateSolver import nebulosa.astrometrynet.nova.NovaAstrometryNetService import nebulosa.astrometrynet.platesolver.LocalAstrometryNetPlateSolver import nebulosa.astrometrynet.platesolver.NovaAstrometryNetPlateSolver +import nebulosa.math.Angle import nebulosa.pixinsight.platesolver.PixInsightPlateSolver import nebulosa.pixinsight.script.startPixInsight import nebulosa.siril.platesolver.SirilPlateSolver @@ -26,6 +31,10 @@ data class PlateSolverRequest( @field:DurationMin(seconds = 0) @field:DurationMax(minutes = 5) @field:DurationUnit(ChronoUnit.SECONDS) @JvmField val timeout: Duration = Duration.ZERO, @JvmField val slot: Int = 1, + @JvmField val blind: Boolean = true, + @JsonDeserialize(using = RightAscensionDeserializer::class) @JvmField val centerRA: Angle = 0.0, + @JsonDeserialize(using = DeclinationDeserializer::class) @JvmField val centerDEC: Angle = 0.0, + @JsonDeserialize(using = DegreesDeserializer::class) @JvmField val radius: Angle = if (blind) 0.0 else 4.0, ) { fun get(httpClient: OkHttpClient? = null) = with(this) { diff --git a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverService.kt b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverService.kt index 890f40922..dfbe20d30 100644 --- a/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverService.kt +++ b/api/src/main/kotlin/nebulosa/api/platesolver/PlateSolverService.kt @@ -3,7 +3,6 @@ package nebulosa.api.platesolver import nebulosa.api.image.ImageBucket import nebulosa.api.image.ImageSolved import nebulosa.common.concurrency.cancel.CancellationToken -import nebulosa.math.Angle import okhttp3.OkHttpClient import org.springframework.stereotype.Service import java.nio.file.Path @@ -17,22 +16,18 @@ class PlateSolverService( private val cancellationToken = AtomicReference() - fun solveImage( - options: PlateSolverRequest, path: Path, - centerRA: Angle, centerDEC: Angle, radius: Angle, - ): ImageSolved { - val calibration = solve(options, path, centerRA, centerDEC, radius) + fun solveImage(request: PlateSolverRequest, path: Path): ImageSolved { + val calibration = solve(request, path) imageBucket.put(path, calibration) return ImageSolved(calibration) } @Synchronized - fun solve( - options: PlateSolverRequest, path: Path, - centerRA: Angle = 0.0, centerDEC: Angle = 0.0, radius: Angle = 0.0, - ) = CancellationToken().use { + fun solve(request: PlateSolverRequest, path: Path) = CancellationToken().use { cancellationToken.set(it) - options.get(httpClient).solve(path, null, centerRA, centerDEC, radius, options.downsampleFactor, options.timeout, it) + val solver = request.get(httpClient) + val radius = if (request.blind) 0.0 else request.radius + solver.solve(path, null, request.centerRA, request.centerDEC, radius, request.downsampleFactor, request.timeout, it) } fun stopSolver() { diff --git a/desktop/app/window.manager.ts b/desktop/app/window.manager.ts index 2e0b1d518..8e7770918 100644 --- a/desktop/app/window.manager.ts +++ b/desktop/app/window.manager.ts @@ -97,7 +97,6 @@ export class WindowManager { if (appWindow) { if (open.data) { - console.info('window data changed. id=%s, data=%s', open.id, open.data) appWindow.browserWindow.webContents.send('DATA.CHANGED', open.data) } diff --git a/desktop/src/app/app.module.ts b/desktop/src/app/app.module.ts index 3de22f9f2..46138ff7b 100644 --- a/desktop/src/app/app.module.ts +++ b/desktop/src/app/app.module.ts @@ -69,6 +69,7 @@ import { EnumDropdownPipe } from '../shared/pipes/enum-dropdown.pipe' import { EnumPipe } from '../shared/pipes/enum.pipe' import { EnvPipe } from '../shared/pipes/env.pipe' import { ExposureTimePipe } from '../shared/pipes/exposureTime.pipe' +import { PathPipe } from '../shared/pipes/path.pipe' import { SkyObjectPipe } from '../shared/pipes/skyObject.pipe' import { WinPipe } from '../shared/pipes/win.pipe' import { AboutComponent } from './about/about.component' @@ -88,6 +89,7 @@ import { FocuserComponent } from './focuser/focuser.component' import { FramingComponent } from './framing/framing.component' import { GuiderComponent } from './guider/guider.component' import { HomeComponent } from './home/home.component' +import { CrossHairComponent } from './image/crosshair.component' import { ImageComponent } from './image/image.component' import { INDIComponent } from './indi/indi.component' import { INDIPropertyComponent } from './indi/property/indi-property.component' @@ -96,7 +98,6 @@ import { RotatorComponent } from './rotator/rotator.component' import { SequencerComponent } from './sequencer/sequencer.component' import { SettingsComponent } from './settings/settings.component' import { StackerComponent } from './stacker/stacker.component' -import { PathPipe } from '../shared/pipes/path.pipe' @NgModule({ declarations: [ @@ -112,6 +113,7 @@ import { PathPipe } from '../shared/pipes/path.pipe' CameraInfoComponent, CameraExposureComponent, ConfirmDialog, + CrossHairComponent, DeviceChooserComponent, DeviceListMenuComponent, DialogMenuComponent, diff --git a/desktop/src/app/calibration/calibration.component.ts b/desktop/src/app/calibration/calibration.component.ts index 7fc78f33a..3a9ffa19c 100644 --- a/desktop/src/app/calibration/calibration.component.ts +++ b/desktop/src/app/calibration/calibration.component.ts @@ -270,7 +270,6 @@ export class CalibrationComponent implements AfterViewInit, OnDestroy { let index = this.selectedFrames.indexOf(frame) if (index >= 0) { - console.log('selected frame removed', frame) this.selectedFrames.splice(index, 1) this.frameSelected() } diff --git a/desktop/src/app/camera/camera.component.ts b/desktop/src/app/camera/camera.component.ts index 49077ab43..dd129a542 100644 --- a/desktop/src/app/camera/camera.component.ts +++ b/desktop/src/app/camera/camera.component.ts @@ -19,7 +19,6 @@ import { CameraStartCapture, DEFAULT_CAMERA, DEFAULT_CAMERA_PREFERENCE, - ExposureTimeUnit, FrameType, updateCameraStartCaptureFromCamera, } from '../../shared/types/camera.types' @@ -331,7 +330,7 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { this.preference.exposureMode = 'FIXED' this.request.exposureAmount = 1 } else if (mode === 'DARV') { - this.preference.exposureTimeUnit = ExposureTimeUnit.SECOND + this.preference.exposureTimeUnit = 'SECOND' } this.ditherMenuItem.visible = this.hasDither diff --git a/desktop/src/app/camera/exposure-time.component.ts b/desktop/src/app/camera/exposure-time.component.ts index 309d64741..5fc16707d 100644 --- a/desktop/src/app/camera/exposure-time.component.ts +++ b/desktop/src/app/camera/exposure-time.component.ts @@ -16,7 +16,7 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { readonly exposureTimeChange = new EventEmitter() @Input() - protected readonly unit: ExposureTimeUnit = ExposureTimeUnit.MICROSECOND + protected readonly unit: ExposureTimeUnit = 'MICROSECOND' @Output() readonly unitChange = new EventEmitter() @@ -52,25 +52,25 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { { label: 'Minute (m)', command: () => { - this.exposureTimeUnitChanged(ExposureTimeUnit.MINUTE) + this.exposureTimeUnitChanged('MINUTE') }, }, { label: 'Second (s)', command: () => { - this.exposureTimeUnitChanged(ExposureTimeUnit.SECOND) + this.exposureTimeUnitChanged('SECOND') }, }, { label: 'Millisecond (ms)', command: () => { - this.exposureTimeUnitChanged(ExposureTimeUnit.MILLISECOND) + this.exposureTimeUnitChanged('MILLISECOND') }, }, { label: 'Microsecond (ยตs)', command: () => { - this.exposureTimeUnitChanged(ExposureTimeUnit.MICROSECOND) + this.exposureTimeUnitChanged('MICROSECOND') }, }, ] @@ -86,7 +86,7 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { this.exposureTimeUnitChanged(change.currentValue) break case 'exposureTime': - this.exposureTimeChanged(change.currentValue, ExposureTimeUnit.MICROSECOND) + this.exposureTimeChanged(change.currentValue, 'MICROSECOND') break case 'min': case 'max': @@ -116,7 +116,7 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { protected exposureTimeUnitWheeled(event: WheelEvent) { if (event.deltaY) { - const units: ExposureTimeUnit[] = [ExposureTimeUnit.MINUTE, ExposureTimeUnit.SECOND, ExposureTimeUnit.MILLISECOND, ExposureTimeUnit.MICROSECOND] + const units: ExposureTimeUnit[] = ['MINUTE', 'SECOND', 'MILLISECOND', 'MICROSECOND'] const index = units.indexOf(this.unit) if (index >= 0) { @@ -157,10 +157,10 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { return false } - const factors = [ - { unit: ExposureTimeUnit.MINUTE, time: 60000000 }, - { unit: ExposureTimeUnit.SECOND, time: 1000000 }, - { unit: ExposureTimeUnit.MILLISECOND, time: 1000 }, + const factors: { unit: ExposureTimeUnit; time: number }[] = [ + { unit: 'MINUTE', time: 60000000 }, + { unit: 'SECOND', time: 1000000 }, + { unit: 'MILLISECOND', time: 1000 }, ] for (const { unit, time } of factors) { @@ -169,8 +169,7 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { // exposureTime is multiple of time. if (k === Math.floor(k)) { - console.log('exposure time normalized:', exposureTime, unit) - this.updateExposureTime(exposureTime, unit, ExposureTimeUnit.MICROSECOND) + this.updateExposureTime(exposureTime, unit, 'MICROSECOND') return true } } @@ -179,7 +178,7 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { return false } - static computeExposureTime(exposureTime: number, to: ExposureTimeUnit, from: ExposureTimeUnit = ExposureTimeUnit.MICROSECOND) { + static computeExposureTime(exposureTime: number, to: ExposureTimeUnit, from: ExposureTimeUnit = 'MICROSECOND') { if (to === from) { return exposureTime } @@ -192,13 +191,18 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { static exposureUnitFactor(unit: ExposureTimeUnit) { switch (unit) { - case ExposureTimeUnit.MINUTE: + case 'MINUTE': + case 'm' as ExposureTimeUnit: return 1 - case ExposureTimeUnit.SECOND: + case 'SECOND': + case 's' as ExposureTimeUnit: return 60 - case ExposureTimeUnit.MILLISECOND: + case 'MILLISECOND': + case 'ms' as ExposureTimeUnit: return 60000 - case ExposureTimeUnit.MICROSECOND: + case 'MICROSECOND': + case 'us' as ExposureTimeUnit: + case 'ยตs' as ExposureTimeUnit: return 60000000 default: return 0 diff --git a/desktop/src/app/filterwheel/filterwheel.component.ts b/desktop/src/app/filterwheel/filterwheel.component.ts index a7979cd71..fa98dfac6 100644 --- a/desktop/src/app/filterwheel/filterwheel.component.ts +++ b/desktop/src/app/filterwheel/filterwheel.component.ts @@ -248,8 +248,6 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab const offset = nextFocusOffset - currentFocusOffset if (this.focuser && offset !== 0) { - console.info('moving focuser %d steps', offset) - if (offset < 0) await this.api.focuserMoveIn(this.focuser, -offset) else await this.api.focuserMoveOut(this.focuser, offset) } diff --git a/desktop/src/app/image/crosshair.component.ts b/desktop/src/app/image/crosshair.component.ts new file mode 100644 index 000000000..22f9e44cf --- /dev/null +++ b/desktop/src/app/image/crosshair.component.ts @@ -0,0 +1,53 @@ +import { Component, ViewEncapsulation } from '@angular/core' + +@Component({ + selector: 'neb-crosshair', + template: ` + + + + + + + + `, + styles: ` + :host { + width: 100%; + height: 100%; + pointer-events: none; + } + `, + encapsulation: ViewEncapsulation.None, +}) +export class CrossHairComponent {} diff --git a/desktop/src/app/image/image.component.html b/desktop/src/app/image/image.component.html index 23710ccfd..db0c1780f 100644 --- a/desktop/src/app/image/image.component.html +++ b/desktop/src/app/image/image.component.html @@ -1,60 +1,25 @@ - {{ imageZoom.toFixed(1) }}x + {{ zoom.scale.toFixed(1) }}x
+ style="backface-visibility: hidden"> - - - - - - - + + (click)="drawDetectedStar(s)"> + [model]="contextMenuModel"> @@ -177,7 +142,9 @@
Stars & DSOs
@@ -185,8 +152,9 @@
@@ -208,7 +176,8 @@
Minor Planets
@@ -217,13 +186,14 @@
@@ -232,8 +202,10 @@
@@ -265,17 +237,17 @@
- +
@@ -285,7 +257,7 @@ @@ -295,55 +267,55 @@
+ *ngIf="astronomicalObject.info.constellation">
+ *ngIf="astronomicalObject.info.magnitude">
+ *ngIf="astronomicalObject.info.type">
+ *ngIf="astronomicalObject.info.distance"> @@ -351,10 +323,10 @@ @@ -362,32 +334,32 @@
+ [(ngModel)]="solver.request.blind" />
@@ -428,9 +400,9 @@ + [(ngModel)]="solver.request.centerRA" />
@@ -438,9 +410,9 @@ + [(ngModel)]="solver.request.centerDEC" />
@@ -449,17 +421,17 @@
- @if (solver.type === 'SIRIL' || solver.type === 'PIXINSIGHT') { + @if (solver.request.type === 'SIRIL' || solver.request.type === 'PIXINSIGHT') {
@@ -482,7 +454,7 @@ [step]="0.01" styleClass="p-inputtext-sm border-0 w-full" [showButtons]="true" - [(ngModel)]="solver.pixelSize" + [(ngModel)]="solver.request.pixelSize" [allowEmpty]="false" locale="en" spinnableNumber /> @@ -624,7 +596,7 @@ [max]="65536" [showButtons]="true" styleClass="p-inputtext-sm border-0 w-full" - [(ngModel)]="stretchShadow" + [(ngModel)]="stretch.transformation.shadow" locale="en" spinnableNumber /> @@ -635,7 +607,7 @@ [max]="65536" [showButtons]="true" styleClass="p-inputtext-sm border-0 w-full" - [(ngModel)]="stretchHighlight" + [(ngModel)]="stretch.transformation.highlight" locale="en" spinnableNumber /> @@ -646,8 +618,8 @@ class="mt-3 px-2" [min]="0" [max]="65536" - [ngModel]="stretchShadowAndHighlight()" - (ngModelChange)="stretchShadow.set($event[0]); stretchHighlight.set($event[1])" + [ngModel]="[stretch.transformation.shadow, stretch.transformation.highlight]" + (ngModelChange)="stretch.transformation.shadow = $event[0]; stretch.transformation.highlight = $event[1]" [range]="true" />
@@ -658,7 +630,7 @@ [max]="65536" [showButtons]="true" styleClass="p-inputtext-sm border-0 w-full" - [(ngModel)]="stretchMidtone" + [(ngModel)]="stretch.transformation.midtone" locale="en" spinnableNumber /> @@ -669,7 +641,7 @@ class="mt-3 px-2" [min]="0" [max]="65536" - [(ngModel)]="stretchMidtone" /> + [(ngModel)]="stretch.transformation.midtone" />
@@ -708,18 +680,19 @@
@@ -760,13 +733,13 @@
@@ -791,7 +764,7 @@ @@ -804,7 +777,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="imageInfo.statistics.count" /> + [value]="statistics.statistics.count" />
@@ -814,7 +787,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="(imageInfo.statistics.mean * statisticsBitLength.rangeMax).toFixed(8)" /> + [value]="(statistics.statistics.mean * statistics.bitOption.rangeMax).toFixed(8)" />
@@ -824,7 +797,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="(imageInfo.statistics.median * statisticsBitLength.rangeMax).toFixed(8)" /> + [value]="(statistics.statistics.median * statistics.bitOption.rangeMax).toFixed(8)" />
@@ -834,7 +807,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="(imageInfo.statistics.variance * statisticsBitLength.rangeMax * statisticsBitLength.rangeMax).toFixed(8)" /> + [value]="(statistics.statistics.variance * statistics.bitOption.rangeMax * statistics.bitOption.rangeMax).toFixed(8)" />
@@ -844,7 +817,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="(imageInfo.statistics.avgDev * statisticsBitLength.rangeMax).toFixed(8)" /> + [value]="(statistics.statistics.avgDev * statistics.bitOption.rangeMax).toFixed(8)" />
@@ -854,7 +827,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="(imageInfo.statistics.stdDev * statisticsBitLength.rangeMax).toFixed(8)" /> + [value]="(statistics.statistics.stdDev * statistics.bitOption.rangeMax).toFixed(8)" />
@@ -864,7 +837,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="(imageInfo.statistics.minimum * statisticsBitLength.rangeMax).toFixed(8)" /> + [value]="(statistics.statistics.minimum * statistics.bitOption.rangeMax).toFixed(8)" />
@@ -874,20 +847,20 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="(imageInfo.statistics.maximum * statisticsBitLength.rangeMax).toFixed(8)" /> + [value]="(statistics.statistics.maximum * statistics.bitOption.rangeMax).toFixed(8)" />
+ (ngModelChange)="savePreference()" />
@@ -903,7 +876,7 @@ @@ -912,7 +885,7 @@
+ *ngIf="starDetector.request.type !== 'SIRIL'"> @@ -941,7 +914,7 @@
+ *ngIf="starDetector.request.type === 'SIRIL'"> @@ -966,7 +939,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="starDetection.stars.length" /> + [value]="starDetector.stars.length" />
@@ -976,7 +949,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - value="{{ starDetection.computed.hfd.toFixed(2) }} | {{ starDetection.computed.stdDev.toFixed(4) }}" /> + value="{{ starDetector.computed.hfd.toFixed(2) }} | {{ starDetector.computed.stdDev.toFixed(4) }}" />
@@ -986,7 +959,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="starDetection.computed.snr.toFixed(1)" /> + [value]="starDetector.computed.snr.toFixed(1)" />
@@ -996,7 +969,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - value="{{ starDetection.computed.fluxMin.toFixed(0) }} | {{ starDetection.computed.fluxMax.toFixed(0) }}" /> + value="{{ starDetector.computed.fluxMin.toFixed(0) }} | {{ starDetector.computed.fluxMax.toFixed(0) }}" />
@@ -1016,7 +989,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - value="{{ starDetection.selected.x.toFixed(0) }} | {{ starDetection.selected.y.toFixed(0) }}" /> + value="{{ starDetector.selected.x.toFixed(0) }} | {{ starDetector.selected.y.toFixed(0) }}" />
@@ -1026,7 +999,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="starDetection.selected.flux.toFixed(0)" /> + [value]="starDetector.selected.flux.toFixed(0)" />
@@ -1036,7 +1009,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="starDetection.selected.hfd.toFixed(2)" /> + [value]="starDetector.selected.hfd.toFixed(2)" /> @@ -1046,7 +1019,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="starDetection.selected.snr.toFixed(1)" /> + [value]="starDetector.selected.snr.toFixed(1)" /> @@ -1055,7 +1028,7 @@
@@ -1082,14 +1055,14 @@ @@ -1099,7 +1072,7 @@ @@ -1109,7 +1082,7 @@ @@ -1121,7 +1094,7 @@ [showButtons]="true" [min]="1" [max]="9999" - [(ngModel)]="fov.cameraSize.width" + [(ngModel)]="fov.selected.cameraSize.width" spinnableNumber /> @@ -1133,7 +1106,7 @@ [showButtons]="true" [min]="1" [max]="9999" - [(ngModel)]="fov.cameraSize.height" + [(ngModel)]="fov.selected.cameraSize.height" spinnableNumber /> @@ -1148,7 +1121,7 @@ [step]="0.01" [minFractionDigits]="0" [maxFractionDigits]="2" - [(ngModel)]="fov.pixelSize.width" + [(ngModel)]="fov.selected.pixelSize.width" locale="en" spinnableNumber /> @@ -1164,7 +1137,7 @@ [step]="0.01" [minFractionDigits]="0" [maxFractionDigits]="2" - [(ngModel)]="fov.pixelSize.height" + [(ngModel)]="fov.selected.pixelSize.height" locale="en" spinnableNumber /> @@ -1180,7 +1153,7 @@ [step]="0.01" [minFractionDigits]="0" [maxFractionDigits]="2" - [(ngModel)]="fov.barlowReducer" + [(ngModel)]="fov.selected.barlowReducer" locale="en" spinnableNumber /> @@ -1193,7 +1166,7 @@ [showButtons]="true" [min]="1" [max]="5" - [(ngModel)]="fov.bin" + [(ngModel)]="fov.selected.bin" spinnableNumber /> @@ -1216,27 +1189,9 @@ -->
- - + +
+
+ + +
+
+
+
diff --git a/desktop/src/app/image/image.component.scss b/desktop/src/app/image/image.component.scss index 3f4411614..affaac825 100644 --- a/desktop/src/app/image/image.component.scss +++ b/desktop/src/app/image/image.component.scss @@ -15,33 +15,33 @@ image-rendering: pixelated; border-radius: 4px; } -} -.roi { - width: 128px; - height: 128px; - box-sizing: border-box; -} + .roi { + width: 128px; + height: 128px; + box-sizing: border-box; + } -.roi-coordinates { - background: rgba(0, 0, 0, 0.5); - padding: 4px 8px; - border-radius: 2px; - font-size: 12px !important; - min-width: 71px; - top: 46px; - left: 50%; - white-space: nowrap; - transform: translate(-50%, 0%); -} + .roi-coordinates { + background: rgba(0, 0, 0, 0.5); + padding: 4px 8px; + border-radius: 2px; + font-size: 12px !important; + min-width: 71px; + top: 46px; + left: 50%; + white-space: nowrap; + transform: translate(-50%, 0%); + } -.coordinates { - bottom: 8px; - left: 50%; - padding: 8px; - border-radius: 2px; - background: rgba(0, 0, 0, 0.65); - border: 1px solid rgba(255, 255, 255, 0.15); - width: 260px; - transform: translate(-50%, 0px); + .coordinates { + bottom: 8px; + left: 50%; + padding: 8px; + border-radius: 2px; + background: rgba(0, 0, 0, 0.65); + border: 1px solid rgba(255, 255, 255, 0.15); + width: 260px; + transform: translate(-50%, 0px); + } } diff --git a/desktop/src/app/image/image.component.ts b/desktop/src/app/image/image.component.ts index 0b72a763a..6e96e0ed0 100644 --- a/desktop/src/app/image/image.component.ts +++ b/desktop/src/app/image/image.component.ts @@ -1,8 +1,8 @@ -import { AfterViewInit, Component, ElementRef, HostListener, NgZone, OnDestroy, ViewChild, computed, model } from '@angular/core' +import { AfterViewInit, Component, ElementRef, HostListener, NgZone, OnDestroy, ViewChild } from '@angular/core' import { ActivatedRoute } from '@angular/router' import hotkeys from 'hotkeys-js' import { NgxLegacyMoveableComponent, OnDrag, OnResize, OnRotate } from 'ngx-moveable' -import createPanZoom, { PanZoom } from 'panzoom' +import createPanZoom from 'panzoom' import { basename, dirname, extname } from 'path' import { ContextMenu } from 'primeng/contextmenu' import { DeviceListMenuComponent } from '../../shared/components/device-list-menu/device-list-menu.component' @@ -14,39 +14,43 @@ import { BrowserWindowService } from '../../shared/services/browser-window.servi import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' import { PrimeService } from '../../shared/services/prime.service' -import { Angle, EquatorialCoordinateJ2000 } from '../../shared/types/atlas.types' +import { EquatorialCoordinateJ2000 } from '../../shared/types/atlas.types' import { Camera } from '../../shared/types/camera.types' import { - AnnotationInfoDialog, - DEFAULT_FOV, + AstronomicalObjectDialog, + DEFAULT_IMAGE_ANNOTATION_DIALOG, + DEFAULT_IMAGE_CALIBRATION, + DEFAULT_IMAGE_DATA, + DEFAULT_IMAGE_FOV_DIALOG, + DEFAULT_IMAGE_LIVE_STACKING, + DEFAULT_IMAGE_MOUSE_COORDINATES, + DEFAULT_IMAGE_MOUSE_POSITION, + DEFAULT_IMAGE_PREFERENCE, + DEFAULT_IMAGE_ROI, + DEFAULT_IMAGE_SAVE_DIALOG, + DEFAULT_IMAGE_SETTINGS_DIALOG, DEFAULT_IMAGE_SOLVED, + DEFAULT_IMAGE_SOLVER_DIALOG, + DEFAULT_IMAGE_STATISTICS_DIALOG, + DEFAULT_IMAGE_ZOOM, + DEFAULT_STAR_DETECTOR_DIALOG, DetectedStar, - FITSHeaderItem, FOV, - IMAGE_STATISTICS_BIT_OPTIONS, ImageAnnotation, - ImageAnnotationDialog, - ImageChannel, - ImageData, - ImageFITSHeadersDialog, - ImageFOVDialog, + imageFormatFromExtension, + ImageHeaderItem, + ImageHeadersDialog, ImageInfo, - ImageROI, ImageSCNRDialog, - ImageSaveDialog, ImageSolved, - ImageSolverDialog, - ImageStatisticsBitOption, ImageStretchDialog, - ImageTransformation, LiveStackingMode, OpenImage, - StarDetectionDialog, } from '../../shared/types/image.types' import { Mount } from '../../shared/types/mount.types' import { PlateSolverRequest } from '../../shared/types/platesolver.types' import { StarDetectionRequest } from '../../shared/types/stardetector.types' -import { CoordinateInterpolator, InterpolatedCoordinate } from '../../shared/utils/coordinate-interpolation' +import { CoordinateInterpolator } from '../../shared/utils/coordinate-interpolation' import { AppComponent } from '../app.component' @Component({ @@ -55,191 +59,60 @@ import { AppComponent } from '../app.component' styleUrls: ['./image.component.scss'], }) export class ImageComponent implements AfterViewInit, OnDestroy { - @ViewChild('image') - private readonly image!: ElementRef - - @ViewChild('roi') - private readonly roi!: ElementRef - - @ViewChild('menu') - private readonly menu!: ContextMenu - - @ViewChild('deviceMenu') - private readonly deviceMenu!: DeviceListMenuComponent - - @ViewChild('histogram') - private readonly histogram?: HistogramComponent - - @ViewChild('detectedStarCanvas') - private readonly detectedStarCanvas!: ElementRef - - @ViewChild('moveable') - private readonly moveable!: NgxLegacyMoveableComponent - - imageInfo?: ImageInfo - private imageURL!: string - imageData: ImageData = {} - liveStackingMode: LiveStackingMode = 'NONE' - imageZoom = 1 - - readonly scnrChannels: { name: string; value?: ImageChannel }[] = [ - { name: 'None', value: undefined }, - { name: 'Red', value: 'RED' }, - { name: 'Green', value: 'GREEN' }, - { name: 'Blue', value: 'BLUE' }, - ] - readonly scnr: ImageSCNRDialog = { - showDialog: false, - amount: 0.5, - method: 'AVERAGE_NEUTRAL', - } - - readonly stretch: ImageStretchDialog = { + protected readonly preference = structuredClone(DEFAULT_IMAGE_PREFERENCE) + protected readonly solver = structuredClone(DEFAULT_IMAGE_SOLVER_DIALOG) + protected readonly starDetector = structuredClone(DEFAULT_STAR_DETECTOR_DIALOG) + protected transformation = this.preference.transformation + protected readonly fov = structuredClone(DEFAULT_IMAGE_FOV_DIALOG) + protected readonly annotation = structuredClone(DEFAULT_IMAGE_ANNOTATION_DIALOG) + protected readonly imageROI = structuredClone(DEFAULT_IMAGE_ROI) + protected readonly saveAs = structuredClone(DEFAULT_IMAGE_SAVE_DIALOG) + protected readonly statistics = structuredClone(DEFAULT_IMAGE_STATISTICS_DIALOG) + protected readonly mouseCoordinate = structuredClone(DEFAULT_IMAGE_MOUSE_COORDINATES) + protected readonly liveStacking = structuredClone(DEFAULT_IMAGE_LIVE_STACKING) + protected readonly zoom = structuredClone(DEFAULT_IMAGE_ZOOM) + protected readonly settings = structuredClone(DEFAULT_IMAGE_SETTINGS_DIALOG) + private readonly calibration = structuredClone(DEFAULT_IMAGE_CALIBRATION) + private readonly mouseMountCoordinate = structuredClone(DEFAULT_IMAGE_MOUSE_POSITION) + private readonly imageData = structuredClone(DEFAULT_IMAGE_DATA) + + protected readonly stretch: ImageStretchDialog = { showDialog: false, - auto: true, - shadow: 0, - highlight: 1, - midtone: 0.5, + transformation: this.transformation.stretch, } - readonly stretchShadow = model(0) - readonly stretchHighlight = model(65536) - readonly stretchMidtone = model(32768) - readonly stretchShadowAndHighlight = computed(() => [this.stretchShadow(), this.stretchHighlight()]) - - readonly transformation: ImageTransformation = { - force: false, - debayer: true, - stretch: this.stretch, - mirrorHorizontal: false, - mirrorVertical: false, - invert: false, - scnr: this.scnr, - } - - calibrationViaCamera = true - - readonly annotation: ImageAnnotationDialog = { + protected readonly scnr: ImageSCNRDialog = { showDialog: false, - running: false, - visible: false, - useStarsAndDSOs: true, - useMinorPlanets: false, - minorPlanetsMagLimit: 18.0, - includeMinorPlanetsWithoutMagnitude: true, - useSimbad: false, - data: [], - } - - readonly annotationInfo: AnnotationInfoDialog = { - showDialog: false, - } - - readonly starDetection: StarDetectionDialog = { - showDialog: false, - running: false, - type: 'ASTAP', - minSNR: 0, - maxStars: 0, - visible: false, - stars: [], - computed: { - hfd: 0, - snr: 0, - stdDev: 0, - fluxMax: 0, - fluxMin: 0, - }, - selected: { - x: 0, - y: 0, - snr: 0, - hfd: 0, - flux: 0, - }, + transformation: this.transformation.scnr, } - readonly solver: ImageSolverDialog = { + protected readonly astronomicalObject: AstronomicalObjectDialog = { showDialog: false, - running: false, - type: 'ASTAP', - blind: true, - centerRA: '', - centerDEC: '', - radius: 4, - focalLength: 0, - pixelSize: 0, - solved: structuredClone(DEFAULT_IMAGE_SOLVED), } - crossHair = false - - readonly fitsHeaders: ImageFITSHeadersDialog = { + protected readonly headers: ImageHeadersDialog = { showDialog: false, headers: [], } - showStatisticsDialog = false - - readonly statisticsBitOptions: ImageStatisticsBitOption[] = IMAGE_STATISTICS_BIT_OPTIONS - statisticsBitLength = this.statisticsBitOptions[0] - - readonly fov: ImageFOVDialog = { - ...structuredClone(DEFAULT_FOV), - showDialog: false, - fovs: [], - showCameraDialog: false, - cameras: [], - showTelescopeDialog: false, - telescopes: [], - } - - get canAddFOV() { - return this.fov.aperture && this.fov.focalLength && this.fov.cameraSize.width && this.fov.cameraSize.height && this.fov.pixelSize.width && this.fov.pixelSize.height && this.fov.bin - } - - private panZoom?: PanZoom - private imageMouseX = 0 - private imageMouseY = 0 - - readonly imageROI: ImageROI = { - show: false, - x: 0, - y: 0, - width: 128, - height: 128, - } - - readonly saveAs: ImageSaveDialog = { - showDialog: false, - format: 'FITS', - bitpix: 'BYTE', - path: '', - shouldBeTransformed: true, - transformation: this.transformation, - } + protected imageInfo?: ImageInfo private readonly saveAsMenuItem: MenuItem = { label: 'Save as...', icon: 'mdi mdi-content-save', command: async () => { - const preference = this.preference.imagePreference.get() - - const path = await this.electron.saveImage({ defaultPath: preference.savePath }) + const path = await this.electronService.saveImage({ defaultPath: this.preference.savePath }) if (path) { const extension = extname(path).toLowerCase() - this.saveAs.format = - extension === '.xisf' ? 'XISF' - : extension === '.png' ? 'PNG' - : extension === '.jpg' ? 'JPG' - : 'FITS' + this.saveAs.format = imageFormatFromExtension(extension) this.saveAs.bitpix = this.imageInfo?.bitpix ?? 'BYTE' this.saveAs.path = path - this.saveAs.showDialog = true - preference.savePath = dirname(path) - this.preference.imagePreference.set(preference) + this.preference.savePath = dirname(path) + this.savePreference() + + this.saveAs.showDialog = true } }, } @@ -285,7 +158,8 @@ export class ImageComponent implements AfterViewInit, OnDestroy { command: () => { this.transformation.mirrorHorizontal = !this.transformation.mirrorHorizontal this.horizontalMirrorMenuItem.selected = this.transformation.mirrorHorizontal - void this.loadImage() + this.savePreference() + return this.loadImage() }, } @@ -296,7 +170,8 @@ export class ImageComponent implements AfterViewInit, OnDestroy { command: () => { this.transformation.mirrorVertical = !this.transformation.mirrorVertical this.verticalMirrorMenuItem.selected = this.transformation.mirrorVertical - void this.loadImage() + this.savePreference() + return this.loadImage() }, } @@ -319,7 +194,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { icon: 'mdi mdi-chart-histogram', label: 'Statistics', command: () => { - this.showStatisticsDialog = true + this.statistics.showDialog = true return this.computeHistogram() }, } @@ -328,7 +203,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { icon: 'mdi mdi-list-box', label: 'FITS Header', command: () => { - this.fitsHeaders.showDialog = true + this.headers.showDialog = true }, } @@ -341,7 +216,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { if (path) { void this.executeMount((mount) => { - return this.api.pointMountHere(mount, path, this.imageMouseX, this.imageMouseY) + return this.api.pointMountHere(mount, path, this.mouseMountCoordinate) }) } }, @@ -352,7 +227,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { icon: 'mdi mdi-image', disabled: true, command: () => { - const coordinate = this.mouseCoordinateInterpolation?.interpolate(this.imageMouseX, this.imageMouseY, false, false) + const coordinate = this.mouseCoordinate.interpolator?.interpolate(this.mouseMountCoordinate.x, this.mouseMountCoordinate.y, false, false) if (coordinate) { void this.frame(coordinate) @@ -379,7 +254,6 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.annotation.showDialog = true }, check: (event) => { - event.originalEvent?.stopImmediatePropagation() this.annotation.visible = !!event.checked }, } @@ -391,11 +265,10 @@ export class ImageComponent implements AfterViewInit, OnDestroy { checkable: false, selected: false, command: () => { - this.starDetection.showDialog = true + this.starDetector.showDialog = true }, check: (event) => { - this.starDetection.visible = !!event.checked - event.originalEvent?.stopImmediatePropagation() + this.starDetector.visible = !!event.checked }, } @@ -427,7 +300,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { items: [this.crosshairMenuItem, this.annotationMenuItem, this.detectStarsMenuItem, this.roiMenuItem, this.fovMenuItem], } - readonly contextMenuItems = [ + protected readonly contextMenuModel = [ this.saveAsMenuItem, SEPARATOR_MENU_ITEM, this.plateSolveMenuItem, @@ -448,25 +321,6 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.frameAtThisCoordinateMenuItem, ] - mouseCoordinate?: InterpolatedCoordinate & Partial<{ x: number; y: number }> - private mouseCoordinateInterpolation?: CoordinateInterpolator - - get isMouseCoordinateVisible() { - return !!this.mouseCoordinate && !this.transformation.mirrorHorizontal && !this.transformation.mirrorVertical - } - - get imagePath() { - if (this.liveStackingMode === 'NONE' || this.liveStackingMode === 'RAW' || !this.imageData.liveStackedPath) { - return this.imageData.path - } else { - return this.imageData.liveStackedPath - } - } - - get canPlateSolve() { - return (this.solver.type !== 'SIRIL' && this.solver.type !== 'PIXINSIGHT') || (this.solver.focalLength > 0 && this.solver.pixelSize > 0) - } - private readonly liveStackingMenuItem: MenuItem = { label: 'RAW', icon: 'mdi mdi-image-multiple', @@ -488,14 +342,56 @@ export class ImageComponent implements AfterViewInit, OnDestroy { ], } + @ViewChild('image') + private readonly image!: ElementRef + + @ViewChild('roi') + private readonly roi!: ElementRef + + @ViewChild('menu') + private readonly menu!: ContextMenu + + @ViewChild('deviceMenu') + private readonly deviceMenu!: DeviceListMenuComponent + + @ViewChild('histogram') + private readonly histogram?: HistogramComponent + + @ViewChild('detectedStarCanvas') + private readonly detectedStarCanvas!: ElementRef + + @ViewChild('moveable') + private readonly moveable!: NgxLegacyMoveableComponent + + get isMouseCoordinateVisible() { + return this.mouseCoordinate.show && !!this.mouseCoordinate.interpolator && !this.transformation.mirrorHorizontal && !this.transformation.mirrorVertical + } + + get imagePath() { + if (this.liveStacking.mode === 'NONE' || this.liveStacking.mode === 'RAW' || !this.liveStacking.path) { + return this.imageData.path + } else { + return this.liveStacking.path + } + } + + get canPlateSolve() { + return (this.solver.request.type !== 'SIRIL' && this.solver.request.type !== 'PIXINSIGHT') || (this.solver.request.focalLength > 0 && this.solver.request.pixelSize > 0) + } + + get canAddFOV() { + const fov = this.fov.selected + return fov.aperture && fov.focalLength && fov.cameraSize.width && fov.cameraSize.height && fov.pixelSize.width && fov.pixelSize.height && fov.bin + } + constructor( private readonly app: AppComponent, private readonly route: ActivatedRoute, private readonly api: ApiService, - private readonly electron: ElectronService, - private readonly browserWindow: BrowserWindowService, - private readonly preference: PreferenceService, - private readonly prime: PrimeService, + private readonly electronService: ElectronService, + private readonly browserWindowService: BrowserWindowService, + private readonly preferenceService: PreferenceService, + private readonly primeService: PrimeService, ngZone: NgZone, ) { app.title = 'Image' @@ -540,22 +436,18 @@ export class ImageComponent implements AfterViewInit, OnDestroy { }, }) - this.stretchShadow.subscribe((value) => { - this.stretch.shadow = value / 65536 - }) - - this.stretchHighlight.subscribe((value) => { - this.stretch.highlight = value / 65536 - }) - - this.stretchMidtone.subscribe((value) => { - this.stretch.midtone = value / 65536 + app.topMenu.push({ + icon: 'mdi mdi-cog', + label: 'Settings', + command: () => { + this.settings.showDialog = true + } }) - electron.on('CAMERA.CAPTURE_ELAPSED', async (event) => { + electronService.on('CAMERA.CAPTURE_ELAPSED', async (event) => { if (event.state === 'EXPOSURE_FINISHED' && event.camera.id === this.imageData.camera?.id) { await ngZone.run(async () => { - if (this.liveStackingMode === 'NONE') { + if (this.liveStacking.mode === 'NONE') { if (event.liveStackedPath) { await this.changeLiveStackingMode('STACKED') } @@ -564,9 +456,9 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } this.imageData.path = event.savedPath - this.imageData.liveStackedPath = event.liveStackedPath this.imageData.capture = event.capture this.imageData.exposureCount = event.exposureCount + this.liveStacking.path = event.liveStackedPath this.clearOverlay() @@ -575,13 +467,13 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } }) - electron.on('DATA.CHANGED', (event: OpenImage) => { + electronService.on('DATA.CHANGED', (event: OpenImage) => { return ngZone.run(() => { return this.loadImageFromOpenImage(event) }) }) - electron.on('CALIBRATION.CHANGED', async () => { + electronService.on('CALIBRATION.CHANGED', async () => { return ngZone.run(() => { return this.loadCalibrationGroups() }) @@ -642,19 +534,21 @@ export class ImageComponent implements AfterViewInit, OnDestroy { @HostListener('window:unload') ngOnDestroy() { - void this.closeImage(true) + this.zoom.panZoom?.dispose() + void this.closeImage() } - private markCalibrationGroupItem(name?: string) { + private markCalibrationGroupItem(name: string | undefined = this.transformation.calibrationGroup) { const items = this.calibrationMenuItem.items + const calibrationViaCamera = this.calibration.source === 'CAMERA' if (items) { items[2].disabled = !this.imageInfo?.camera?.id - items[2].selected = this.calibrationViaCamera + items[2].selected = calibrationViaCamera for (let i = 3; i < items.length; i++) { const item = items[i] - item.selected = !this.calibrationViaCamera && item.data === name + item.selected = !calibrationViaCamera && item.data === name } } } @@ -667,7 +561,8 @@ export class ImageComponent implements AfterViewInit, OnDestroy { if (!found) { reloadImage = !!this.transformation.calibrationGroup this.transformation.calibrationGroup = undefined - this.calibrationViaCamera = true + this.savePreference() + this.calibration.source = 'CAMERA' } const makeItem = (name?: string) => { @@ -677,11 +572,12 @@ export class ImageComponent implements AfterViewInit, OnDestroy { return { label, icon, - selected: !this.calibrationViaCamera && this.transformation.calibrationGroup === name, + selected: this.calibration.source === 'MENU' && this.transformation.calibrationGroup === name, data: name, command: () => { - this.calibrationViaCamera = false + this.calibration.source = 'MENU' this.transformation.calibrationGroup = name + this.savePreference() this.markCalibrationGroupItem(name) void this.loadImage() }, @@ -694,7 +590,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { label: 'Open', icon: 'mdi mdi-wrench', command: () => { - return this.browserWindow.openCalibration() + return this.browserWindowService.openCalibration() }, }) @@ -703,13 +599,13 @@ export class ImageComponent implements AfterViewInit, OnDestroy { menu.push({ label: 'Camera', icon: 'mdi mdi-camera-iris', - selected: this.calibrationViaCamera, + selected: this.calibration.source === 'CAMERA', disabled: !this.imageInfo?.camera?.id, data: 0, command: () => { if (this.imageInfo?.camera?.id) { - this.calibrationViaCamera = !this.calibrationViaCamera - this.markCalibrationGroupItem(this.transformation.calibrationGroup) + this.calibration.source = this.calibration.source === 'CAMERA' ? 'MENU' : 'CAMERA' + this.markCalibrationGroupItem() void this.loadImage() } }, @@ -722,7 +618,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } this.calibrationMenuItem.items = menu - this.menu.model = this.contextMenuItems + this.menu.model = this.contextMenuModel this.menu.cd.markForCheck() if (reloadImage) { @@ -730,29 +626,28 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } } - private async closeImage(force: boolean = false) { - if (this.imageData.path && force) { - await this.api.closeImage(this.imageData.path) - } - if (this.imageData.liveStackedPath && force) { - await this.api.closeImage(this.imageData.liveStackedPath) + private async closeImage() { + const path = this.imagePath + + if (path) { + await this.api.closeImage(path) } } - private async changeLiveStackingMode(mode: LiveStackingMode) { - this.liveStackingMode = mode + private changeLiveStackingMode(mode: LiveStackingMode) { + this.liveStacking.mode = mode - if (this.liveStackingMode !== 'NONE') { + if (this.liveStacking.mode !== 'NONE') { this.disableCalibration(true) } - this.liveStackingMenuItem.visible = this.liveStackingMode !== 'NONE' + this.liveStackingMenuItem.visible = this.liveStacking.mode !== 'NONE' this.liveStackingMenuItem.label = mode - await this.loadImage(true) + return this.loadImage(true) } - roiDrag(event: OnDrag) { + protected roiDrag(event: OnDrag) { const { target, transform } = event target.style.transform = transform @@ -761,7 +656,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.imageROI.y = Math.trunc(rect.top) } - roiResize(event: OnResize) { + protected roiResize(event: OnResize) { const { target, width, height, transform } = event target.style.transform = transform @@ -776,19 +671,19 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.imageROI.height = Math.trunc(height) } - roiRotate(event: OnRotate) { + protected roiRotate(event: OnRotate) { const { target, transform } = event target.style.transform = transform } - roiForCamera() { + protected roiForCamera() { return this.executeCamera((camera) => { const x = Math.max(0, Math.min(camera.x + this.imageROI.x, camera.maxX)) const y = Math.max(0, Math.min(camera.y + this.imageROI.y, camera.maxY)) const width = Math.max(0, Math.min(camera.binX * this.imageROI.width, camera.maxWidth)) const height = Math.max(0, Math.min(camera.binY * this.imageROI.height, camera.maxHeight)) - return this.electron.send('ROI.SELECTED', { camera, x, y, width, height }) + return this.electronService.send('ROI.SELECTED', { camera, x, y, width, height }) }, false) } @@ -796,9 +691,10 @@ export class ImageComponent implements AfterViewInit, OnDestroy { Object.assign(this.imageData, data) // Not clicked on menu item. - if (this.calibrationViaCamera && this.transformation.calibrationGroup !== data.capture?.calibrationGroup) { + if (this.calibration.source === 'CAMERA' && this.transformation.calibrationGroup !== data.capture?.calibrationGroup) { this.transformation.calibrationGroup = data.capture?.calibrationGroup - this.markCalibrationGroupItem(this.transformation.calibrationGroup) + this.savePreference() + this.markCalibrationGroupItem() } if (data.source === 'FRAMING') { @@ -822,8 +718,8 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.annotation.visible = false this.annotationMenuItem.checkable = false - this.starDetection.stars = [] - this.starDetection.visible = false + this.starDetector.stars = [] + this.starDetector.visible = false this.detectStarsMenuItem.checkable = false Object.assign(this.solver.solved, DEFAULT_IMAGE_SOLVED) @@ -831,37 +727,29 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.histogram?.update([]) } - private async computeHistogram() { + protected async computeHistogram() { const path = this.imagePath if (path) { - const data = await this.api.imageHistogram(path, this.statisticsBitLength.bitLength) + const data = await this.api.imageHistogram(path, this.statistics.bitOption.bitLength) this.histogram?.update(data) } } - statisticsBitLengthChanged() { - return this.computeHistogram() - } - - async detectStars() { + protected async detectStars() { const path = this.imagePath if (path) { const request: StarDetectionRequest = { - ...this.preference.settings.get().starDetector[this.starDetection.type], - type: this.starDetection.type, - minSNR: this.starDetection.minSNR, - maxStars: this.starDetection.maxStars, + ...this.starDetector.request, + ...this.preferenceService.settings.get().starDetector[this.starDetector.request.type], } - Object.assign(this.starDetection, this.preference.settings.get().starDetector[this.starDetection.type]) - try { - this.starDetection.running = true - this.starDetection.stars = await this.api.detectStars(path, request) + this.starDetector.running = true + this.starDetector.stars = await this.api.detectStars(path, request) } finally { - this.starDetection.running = false + this.starDetector.running = false } let hfd = 0 @@ -870,12 +758,12 @@ export class ImageComponent implements AfterViewInit, OnDestroy { let fluxMin = 0 let fluxMax = 0 - const starCount = this.starDetection.stars.length + const starCount = this.starDetector.stars.length if (starCount) { - fluxMax = this.starDetection.stars[0].flux + fluxMax = this.starDetector.stars[0].flux - for (const star of this.starDetection.stars) { + for (const star of this.starDetector.stars) { hfd += star.hfd snr += star.snr fluxMax = Math.min(fluxMax, star.flux) @@ -887,29 +775,29 @@ export class ImageComponent implements AfterViewInit, OnDestroy { let squared = 0 - for (const star of this.starDetection.stars) { + for (const star of this.starDetector.stars) { squared += Math.pow(star.hfd - hfd, 2) } stdDev = Math.sqrt(squared / starCount) } - this.starDetection.computed.hfd = hfd - this.starDetection.computed.stdDev = stdDev - this.starDetection.computed.snr = snr - this.starDetection.computed.fluxMax = fluxMin - this.starDetection.computed.fluxMin = fluxMax + this.starDetector.computed.hfd = hfd + this.starDetector.computed.stdDev = stdDev + this.starDetector.computed.snr = snr + this.starDetector.computed.fluxMax = fluxMin + this.starDetector.computed.fluxMin = fluxMax this.savePreference() - this.starDetection.visible = this.starDetection.stars.length > 0 - this.detectStarsMenuItem.checkable = this.starDetection.visible - this.detectStarsMenuItem.checked = this.starDetection.visible + this.starDetector.visible = this.starDetector.stars.length > 0 + this.detectStarsMenuItem.checkable = this.starDetector.visible + this.detectStarsMenuItem.checked = this.starDetector.visible } } - selectDetectedStar(star: DetectedStar) { - Object.assign(this.starDetection.selected, star) + protected drawDetectedStar(star: DetectedStar) { + Object.assign(this.starDetector.selected, star) const canvas = this.detectedStarCanvas.nativeElement const ctx = canvas.getContext('2d') @@ -917,7 +805,9 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } private async loadImage(force: boolean = false) { - await this.closeImage(force) + if (force) { + await this.closeImage() + } const path = this.imagePath @@ -948,7 +838,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { const image = this.image.nativeElement const transformation = structuredClone(this.transformation) - if (this.calibrationViaCamera && this.liveStackingMode !== 'NONE') transformation.calibrationGroup = this.imageData.capture?.calibrationGroup + if (this.calibration.source === 'CAMERA' && this.liveStacking.mode !== 'NONE') transformation.calibrationGroup = this.imageData.capture?.calibrationGroup const { info, blob } = await this.api.openImage(path, transformation, this.imageData.camera) if (!blob || !info) return @@ -956,29 +846,25 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.imageInfo = info this.scnrMenuItem.disabled = info.mono - if (info.rightAscension) this.solver.centerRA = info.rightAscension - if (info.declination) this.solver.centerDEC = info.declination - this.solver.blind = !this.solver.centerRA || !this.solver.centerDEC + if (info.rightAscension) this.solver.request.centerRA = info.rightAscension + if (info.declination) this.solver.request.centerDEC = info.declination + this.solver.request.blind = !this.solver.request.centerRA || !this.solver.request.centerDEC - if (this.stretch.auto) { - this.stretchShadow.set(Math.trunc(info.stretchShadow * 65536)) - this.stretchHighlight.set(Math.trunc(info.stretchHighlight * 65536)) - this.stretchMidtone.set(Math.trunc(info.stretchMidtone * 65536)) + if (this.stretch.transformation.auto) { + Object.assign(this.stretch.transformation, info.stretch) } this.updateImageSolved(info.solved) - this.fitsHeaders.headers = info.headers + this.headers.headers = info.headers this.retrieveInfoFromImageHeaders(info.headers) - if (this.imageURL) window.URL.revokeObjectURL(this.imageURL) - this.imageURL = window.URL.createObjectURL(blob) - image.src = this.imageURL + image.src = URL.createObjectURL(blob) if (!info.camera?.id) { - this.calibrationViaCamera = false - this.markCalibrationGroupItem(this.transformation.calibrationGroup) + this.calibration.source = 'MENU' + this.markCalibrationGroupItem() } else if (this.calibrationMenuItem.items) { this.calibrationMenuItem.items[2].disabled = false } @@ -986,46 +872,38 @@ export class ImageComponent implements AfterViewInit, OnDestroy { return this.retrieveCoordinateInterpolation() } - private retrieveInfoFromImageHeaders(headers: FITSHeaderItem[]) { - const imagePreference = this.preference.imagePreference.get() - + private retrieveInfoFromImageHeaders(headers: ImageHeaderItem[]) { for (const item of headers) { if (item.name === 'FOCALLEN') { - this.solver.focalLength = parseFloat(item.value) + this.solver.request.focalLength = parseFloat(item.value) } else if (item.name === 'XPIXSZ') { - this.solver.pixelSize = parseFloat(item.value) + this.solver.request.pixelSize = parseFloat(item.value) } } - - this.solver.focalLength ||= imagePreference.solver?.focalLength ?? 0 - this.solver.pixelSize ||= imagePreference.solver?.pixelSize ?? 0 } - imageClicked(event: MouseEvent, contextMenu: boolean) { - this.imageMouseX = event.offsetX - this.imageMouseY = event.offsetY + protected imageClicked(event: MouseEvent, contextMenu: boolean) { + this.mouseMountCoordinate.x = event.offsetX + this.mouseMountCoordinate.y = event.offsetY if (contextMenu) { this.menu.show(event) } } - imageMouseMoved(event: MouseEvent) { + protected imageMouseMoved(event: MouseEvent) { this.imageMouseMovedWithCoordinates(event.offsetX, event.offsetY) } - imageMouseMovedWithCoordinates(x: number, y: number) { - if (!this.menu.visible()) { - this.mouseCoordinate = this.mouseCoordinateInterpolation?.interpolateAsText(x, y, true, true, false) - - if (this.mouseCoordinate) { - this.mouseCoordinate.x = x - this.mouseCoordinate.y = y - } + private imageMouseMovedWithCoordinates(x: number, y: number) { + if (!this.menu.visible() && this.mouseCoordinate.interpolator) { + Object.assign(this.mouseCoordinate, this.mouseCoordinate.interpolator.interpolateAsText(x, y, true, true, false)) + this.mouseCoordinate.x = x + this.mouseCoordinate.y = y } } - async saveImageAs() { + protected async saveImageAs() { const path = this.imagePath if (path) { @@ -1034,13 +912,13 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } } - async annotateImage() { + protected async annotateImage() { const path = this.imagePath if (path) { try { this.annotation.running = true - this.annotation.data = await this.api.annotationsOfImage(path, this.annotation.useStarsAndDSOs, this.annotation.useMinorPlanets, this.annotation.minorPlanetsMagLimit, this.annotation.includeMinorPlanetsWithoutMagnitude, this.annotation.useSimbad) + this.annotation.data = await this.api.annotationsOfImage(path, this.annotation.request) this.annotation.visible = this.annotation.data.length > 0 this.annotationMenuItem.checkable = this.annotation.visible this.annotationMenuItem.checked = this.annotation.visible @@ -1051,94 +929,101 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } } - showAnnotationInfo(annotation: ImageAnnotation) { - this.annotationInfo.info = annotation.star ?? annotation.dso ?? annotation.minorPlanet - this.annotationInfo.showDialog = true + protected showAnnotationInfo(annotation: ImageAnnotation) { + this.astronomicalObject.info = annotation.star ?? annotation.dso ?? annotation.minorPlanet + this.astronomicalObject.showDialog = true } private disableAutoStretch() { - this.stretch.auto = false + this.stretch.transformation.auto = false + this.savePreference() this.autoStretchMenuItem.selected = false } private disableCalibration(canEnable: boolean = true) { this.transformation.calibrationGroup = undefined + this.savePreference() this.markCalibrationGroupItem(undefined) this.calibrationMenuItem.disabled = !canEnable } - autoStretch() { - this.stretch.auto = true + protected autoStretch() { + this.stretch.transformation.auto = true + this.savePreference() this.autoStretchMenuItem.selected = true return this.loadImage() } - async resetStretch(load: boolean = true) { - this.stretchShadow.set(0) - this.stretchHighlight.set(65536) - this.stretchMidtone.set(32768) + protected async resetStretch(load: boolean = true) { + this.stretch.transformation.shadow = 0 + this.stretch.transformation.highlight = 65536 + this.stretch.transformation.midtone = 32768 + this.savePreference() if (load) { await this.stretchImage() } } - async toggleStretch() { - this.stretch.auto = !this.stretch.auto - this.autoStretchMenuItem.selected = this.stretch.auto + private async toggleStretch() { + this.stretch.transformation.auto = !this.stretch.transformation.auto + this.savePreference() + this.autoStretchMenuItem.selected = this.stretch.transformation.auto - if (!this.stretch.auto) { - await this.resetStretch() + if (this.stretch.transformation.auto) { + return this.loadImage() } else { - await this.loadImage() + return this.resetStretch() } } - stretchImage() { + protected stretchImage() { this.disableAutoStretch() return this.loadImage() } - invertImage() { + private invertImage() { this.transformation.invert = !this.transformation.invert this.invertMenuItem.selected = this.transformation.invert + this.savePreference() return this.loadImage() } - scnrImage() { + protected scnrImage() { return this.loadImage() } - toggleCrosshair() { - this.crossHair = !this.crossHair - this.crosshairMenuItem.selected = this.crossHair + private toggleCrosshair() { + this.preference.crossHair = !this.preference.crossHair + this.savePreference() + this.crosshairMenuItem.selected = this.preference.crossHair } - zoomIn() { - if (!this.panZoom) return - const { scale } = this.panZoom.getTransform() - this.panZoom.smoothZoomAbs(window.innerWidth / 2, window.innerHeight / 2, scale * 1.1) + private zoomIn() { + if (!this.zoom.panZoom) return + const { scale } = this.zoom.panZoom.getTransform() + this.zoom.panZoom.smoothZoomAbs(window.innerWidth / 2, window.innerHeight / 2, scale * 1.1) } - zoomOut() { - if (!this.panZoom) return - const { scale } = this.panZoom.getTransform() - this.panZoom.smoothZoomAbs(window.innerWidth / 2, window.innerHeight / 2, scale * 0.9) + private zoomOut() { + if (!this.zoom.panZoom) return + const { scale } = this.zoom.panZoom.getTransform() + this.zoom.panZoom.smoothZoomAbs(window.innerWidth / 2, window.innerHeight / 2, scale * 0.9) } - center() { + private center() { const { width, height } = this.image.nativeElement.getBoundingClientRect() - this.panZoom?.moveTo(window.innerWidth / 2 - width / 2, (window.innerHeight - 42) / 2 - height / 2) + this.zoom.panZoom?.moveTo(window.innerWidth / 2 - width / 2, (window.innerHeight - 42) / 2 - height / 2) } - resetZoom(fitToScreen: boolean = false, center: boolean = true) { + private resetZoom(fitToScreen: boolean = false, center: boolean = true) { if (fitToScreen) { const { width, height } = this.image.nativeElement const factor = Math.min(window.innerWidth, window.innerHeight - 42) / Math.min(width, height) - this.panZoom?.smoothZoomAbs(window.innerWidth / 2, window.innerHeight / 2, factor) + this.zoom.panZoom?.smoothZoomAbs(window.innerWidth / 2, window.innerHeight / 2, factor) } else { - this.panZoom?.smoothZoomAbs(window.innerWidth / 2, window.innerHeight / 2, 1.0) + this.zoom.panZoom?.smoothZoomAbs(window.innerWidth / 2, window.innerHeight / 2, 1.0) } if (center) { @@ -1146,34 +1031,36 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } } - async enterFullscreen() { - this.app.showTopBar = !(await this.electron.fullscreenWindow(true)) + private async enterFullscreen() { + this.app.showTopBar = !(await this.electronService.fullscreenWindow(true)) } - async exitFullscreen() { - this.app.showTopBar = !(await this.electron.fullscreenWindow(false)) + private async exitFullscreen() { + this.app.showTopBar = !(await this.electronService.fullscreenWindow(false)) } private async retrieveCoordinateInterpolation() { const path = this.imagePath if (path) { - const coordinate = await this.api.coordinateInterpolation(this.imagePath) + const coordinate = await this.api.coordinateInterpolation(path) if (coordinate && this.imageInfo) { const { ma, md, x0, y0, x1, y1, delta } = coordinate - const x = Math.max(0, Math.min(this.mouseCoordinate?.x ?? 0, this.imageInfo.width)) - const y = Math.max(0, Math.min(this.mouseCoordinate?.y ?? 0, this.imageInfo.height)) - this.mouseCoordinateInterpolation = new CoordinateInterpolator(ma, md, x0, y0, x1, y1, delta) + const x = Math.max(0, Math.min(this.mouseCoordinate.x, this.imageInfo.width)) + const y = Math.max(0, Math.min(this.mouseCoordinate.y, this.imageInfo.height)) + this.mouseCoordinate.interpolator = new CoordinateInterpolator(ma, md, x0, y0, x1, y1, delta) + this.mouseCoordinate.show = true this.imageMouseMovedWithCoordinates(x, y) - } else { - this.mouseCoordinateInterpolation = undefined - this.mouseCoordinate = undefined + return } } + + this.mouseCoordinate.interpolator = undefined + this.mouseCoordinate.show = false } - async solverStart() { + protected async solverStart() { const path = this.imagePath if (path) { @@ -1181,15 +1068,12 @@ export class ImageComponent implements AfterViewInit, OnDestroy { try { const request: PlateSolverRequest = { - ...this.preference.settings.get().plateSolver[this.solver.type], - type: this.solver.type, - pixelSize: this.solver.pixelSize, - focalLength: this.solver.focalLength, + ...this.solver.request, + ...this.preferenceService.settings.get().plateSolver[this.solver.request.type], } - const solved = await this.api.solverStart(request, path, this.solver.blind, this.solver.centerRA, this.solver.centerDEC, this.solver.radius) + const solved = await this.api.solverStart(request, path) - this.savePreference() this.updateImageSolved(solved) } catch { this.updateImageSolved(this.imageInfo?.solved) @@ -1203,7 +1087,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } } - solverStop() { + protected solverStop() { return this.api.solverStop() } @@ -1218,27 +1102,27 @@ export class ImageComponent implements AfterViewInit, OnDestroy { else this.fov.fovs.forEach((e) => (e.computed = undefined)) } - mountSync(coordinate: EquatorialCoordinateJ2000) { + protected mountSync(coordinate: EquatorialCoordinateJ2000) { return this.executeMount((mount) => { return this.api.mountSync(mount, coordinate.rightAscensionJ2000, coordinate.declinationJ2000, true) }) } - mountGoTo(coordinate: EquatorialCoordinateJ2000) { + protected mountGoTo(coordinate: EquatorialCoordinateJ2000) { return this.executeMount((mount) => { return this.api.mountGoTo(mount, coordinate.rightAscensionJ2000, coordinate.declinationJ2000, true) }) } - mountSlew(coordinate: EquatorialCoordinateJ2000) { + protected mountSlew(coordinate: EquatorialCoordinateJ2000) { return this.executeMount((mount) => { return this.api.mountSlew(mount, coordinate.rightAscensionJ2000, coordinate.declinationJ2000, true) }) } - async frame(coordinate: EquatorialCoordinateJ2000) { + protected async frame(coordinate: EquatorialCoordinateJ2000) { if (this.solver.solved.solved) { - await this.browserWindow.openFraming({ + await this.browserWindowService.openFraming({ rightAscension: coordinate.rightAscensionJ2000, declination: coordinate.declinationJ2000, fov: this.solver.solved.width / 60, @@ -1247,11 +1131,15 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } } - imageLoaded() { - const imageWrapperElement = this.image.nativeElement.parentElement + protected imageLoaded() { + const image = this.image.nativeElement + const imageWrapper = image.parentElement + + URL.revokeObjectURL(image.src) + console.log(image.src) - if (!this.panZoom && imageWrapperElement) { - this.panZoom = createPanZoom(imageWrapperElement, { + if (!this.zoom.panZoom && imageWrapper) { + const panZoom = createPanZoom(imageWrapper, { minZoom: 0.1, maxZoom: 500.0, autocenter: true, @@ -1261,21 +1149,23 @@ export class ImageComponent implements AfterViewInit, OnDestroy { return true }, beforeWheel: (e) => { - return e.target !== this.image.nativeElement && e.target !== this.roi.nativeElement + return e.target !== this.image.nativeElement && e.target !== this.roi.nativeElement && (e.target as HTMLElement).tagName !== 'circle' }, beforeMouseDown: (e) => { - return e.target !== this.image.nativeElement + return e.target !== this.image.nativeElement && (e.target as HTMLElement).tagName !== 'circle' }, }) - this.panZoom.on('zoom', () => { - const { scale } = this.panZoom!.getTransform() - this.imageZoom = scale + panZoom.on('transform', () => { + const { scale } = panZoom.getTransform() + this.zoom.scale = scale }) + + this.zoom.panZoom = panZoom } } - async showFOVCameras() { + protected async showFOVCameraDialog() { if (!this.fov.cameras.length) { this.fov.cameras = await this.api.fovCameras() } @@ -1284,7 +1174,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.fov.showCameraDialog = true } - async showFOVTelescopes() { + protected async showFOVTelescopeDialog() { if (!this.fov.telescopes.length) { this.fov.telescopes = await this.api.fovTelescopes() } @@ -1293,48 +1183,35 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.fov.showTelescopeDialog = true } - chooseCamera() { + protected chooseCamera() { if (this.fov.camera) { - this.fov.cameraSize.width = this.fov.camera.width - this.fov.cameraSize.height = this.fov.camera.height - this.fov.pixelSize.width = this.fov.camera.pixelSize - this.fov.pixelSize.height = this.fov.camera.pixelSize + this.fov.selected.cameraSize.width = this.fov.camera.width + this.fov.selected.cameraSize.height = this.fov.camera.height + this.fov.selected.pixelSize.width = this.fov.camera.pixelSize + this.fov.selected.pixelSize.height = this.fov.camera.pixelSize this.fov.camera = undefined this.fov.showCameraDialog = false } } - chooseTelescope() { + protected chooseTelescope() { if (this.fov.telescope) { - this.fov.aperture = this.fov.telescope.aperture - this.fov.focalLength = this.fov.telescope.focalLength + this.fov.selected.aperture = this.fov.telescope.aperture + this.fov.selected.focalLength = this.fov.telescope.focalLength this.fov.telescope = undefined this.fov.showTelescopeDialog = false } } - addFOV() { - if (this.computeFOV(this.fov)) { - this.fov.fovs.push(structuredClone(this.fov)) - this.preference.imageFOVs.set(this.fov.fovs) + protected addFOV() { + if (this.computeFOV(this.fov.selected)) { + this.fov.fovs.push(structuredClone(this.fov.selected)) + this.savePreference() } } editFOV(fov: FOV) { - Object.assign(this.fov, structuredClone(fov)) - this.fov.edited = fov - } - - cancelEditFOV() { - this.fov.edited = undefined - } - - saveFOV() { - if (this.fov.edited && this.computeFOV(this.fov)) { - Object.assign(this.fov.edited, structuredClone(this.fov)) - this.preference.imageFOVs.set(this.fov.fovs) - this.fov.edited = undefined - } + this.fov.selected = fov } private computeFOV(fov: FOV) { @@ -1379,50 +1256,36 @@ export class ImageComponent implements AfterViewInit, OnDestroy { const index = this.fov.fovs.indexOf(fov) if (index >= 0) { - if (this.fov.fovs[index] === this.fov.edited) { - this.fov.edited = undefined - } - this.fov.fovs.splice(index, 1) - this.preference.imageFOVs.set(this.fov.fovs) + this.savePreference() } } private loadPreference() { - const preference = this.preference.imagePreference.get() - this.solver.radius = preference.solver?.radius ?? this.solver.radius - this.solver.type = preference.solver?.type ?? 'ASTAP' - this.solver.focalLength = preference.solver?.focalLength ?? 0 - this.solver.pixelSize = preference.solver?.pixelSize ?? 0 - this.starDetection.type = preference.starDetection?.type ?? this.starDetection.type - - this.fov.fovs = this.preference.imageFOVs.get() - this.fov.fovs.forEach((e) => { - e.enabled = false - e.computed = undefined - }) + Object.assign(this.preference, this.preferenceService.imagePreference.get()) + this.solver.request = this.preference.solver + this.starDetector.request = this.preference.starDetector + this.settings.preference = this.preference + this.transformation = this.preference.transformation + this.saveAs.transformation = this.transformation + this.stretch.transformation = this.transformation.stretch + this.scnr.transformation = this.transformation.scnr + this.annotation.request = this.preference.annotation + this.fov.fovs = this.preference.fovs + + this.autoStretchMenuItem.selected = this.transformation.stretch.auto + this.invertMenuItem.selected = this.transformation.invert + this.horizontalMirrorMenuItem.selected = this.transformation.mirrorHorizontal + this.verticalMirrorMenuItem.selected = this.transformation.mirrorVertical + this.crosshairMenuItem.selected = this.preference.crossHair } - private savePreference() { - const preference = this.preference.imagePreference.get() - - preference.solver = { - type: this.solver.type, - focalLength: this.solver.focalLength, - pixelSize: this.solver.pixelSize, - radius: this.solver.radius, - } - preference.starDetection = { - type: this.starDetection.type, - maxStars: this.starDetection.maxStars, - minSNR: this.starDetection.minSNR, - } - - this.preference.imagePreference.set(preference) + protected savePreference() { + this.preferenceService.imagePreference.set(this.preference) } private async executeCamera(action: (camera: Camera) => void | Promise, showConfirmation: boolean = true) { - if (showConfirmation && (await this.prime.confirm('Are you sure that you want to proceed?'))) { + if (showConfirmation && (await this.primeService.confirm('Are you sure that you want to proceed?'))) { return false } @@ -1444,7 +1307,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } private async executeMount(action: (mount: Mount) => void | Promise, showConfirmation: boolean = true) { - if (showConfirmation && (await this.prime.confirm('Are you sure that you want to proceed?'))) { + if (showConfirmation && (await this.primeService.confirm('Are you sure that you want to proceed?'))) { return false } diff --git a/desktop/src/shared/components/menu-bar/menu-bar.component.html b/desktop/src/shared/components/menu-bar/menu-bar.component.html index 903a9e8c3..19ed08fea 100644 --- a/desktop/src/shared/components/menu-bar/menu-bar.component.html +++ b/desktop/src/shared/components/menu-bar/menu-bar.component.html @@ -22,7 +22,7 @@ [binary]="true" [disabled]="item.disabled ?? false" [(ngModel)]="item.checked" - (onChange)="item.check?.($event)" /> + (onChange)="item.check?.($event); $event.originalEvent?.stopImmediatePropagation()" />
} @else if (item.label && item.splitButtonMenu?.length) { + (onChange)="item.check?.($event); $event.originalEvent?.stopImmediatePropagation()" /> } @if (item.items?.length || item.slideMenu?.length) { diff --git a/desktop/src/shared/interceptors/confirmation.interceptor.ts b/desktop/src/shared/interceptors/confirmation.interceptor.ts index 3a29b4d5e..30f476127 100644 --- a/desktop/src/shared/interceptors/confirmation.interceptor.ts +++ b/desktop/src/shared/interceptors/confirmation.interceptor.ts @@ -15,7 +15,6 @@ export class ConfirmationInterceptor implements HttpInterceptor { const idempotencyKey = req.headers.get(IdempotencyKeyInterceptor.HEADER_KEY) if (idempotencyKey) { - console.info('registered confirmation:', req.method, req.urlWithParams, idempotencyKey) this.confirmation.register(idempotencyKey) } @@ -24,7 +23,6 @@ export class ConfirmationInterceptor implements HttpInterceptor { if (idempotencyKey) { return res.pipe( finalize(() => { - console.info('unregistered confirmation:', req.method, req.urlWithParams, idempotencyKey) this.confirmation.unregister(idempotencyKey) }), ) diff --git a/desktop/src/shared/pipes/dropdown-options.pipe.ts b/desktop/src/shared/pipes/dropdown-options.pipe.ts index 7daf27113..7f7253c13 100644 --- a/desktop/src/shared/pipes/dropdown-options.pipe.ts +++ b/desktop/src/shared/pipes/dropdown-options.pipe.ts @@ -4,7 +4,7 @@ import { AutoFocusFittingMode, BacklashCompensationMode } from '../types/autofoc import { ExposureMode, FrameType, LiveStackerType } from '../types/camera.types' import { GuideDirection, GuiderPlotMode, GuiderYAxisUnit } from '../types/guider.types' import { ConnectionType } from '../types/home.types' -import { Bitpix, ImageChannel, ImageFormat, SCNRProtectionMethod } from '../types/image.types' +import { Bitpix, IMAGE_STATISTICS_BIT_OPTIONS, ImageChannel, ImageFormat, ImageStatisticsBitOption, SCNRProtectionMethod } from '../types/image.types' import { MountRemoteControlType } from '../types/mount.types' import { PlateSolverType } from '../types/platesolver.types' import { SequenceCaptureMode } from '../types/sequencer.types' @@ -36,6 +36,7 @@ export interface DropdownOptions { SETTINGS_TAB: SettingsTabKey[] STACKER_GROUP_TYPE: StackerGroupType[] CONNECTION_TYPE: ConnectionType[] + IMAGE_STATISTICS_BIT_OPTIONS: ImageStatisticsBitOption[] } @Pipe({ name: 'dropdownOptions' }) @@ -88,6 +89,8 @@ export class DropdownOptionsPipe implements PipeTransform { return ['LUMINANCE', 'RED', 'GREEN', 'BLUE', 'MONO', 'RGB'] as DropdownOptions[K] case 'CONNECTION_TYPE': return ['INDI', 'ALPACA'] as DropdownOptions[K] + case 'IMAGE_STATISTICS_BIT_OPTIONS': + return IMAGE_STATISTICS_BIT_OPTIONS as DropdownOptions[K] } return [] diff --git a/desktop/src/shared/pipes/enum-dropdown.pipe.ts b/desktop/src/shared/pipes/enum-dropdown.pipe.ts index f544b2972..2d344d126 100644 --- a/desktop/src/shared/pipes/enum-dropdown.pipe.ts +++ b/desktop/src/shared/pipes/enum-dropdown.pipe.ts @@ -1,16 +1,12 @@ import { Pipe, PipeTransform } from '@angular/core' +import { DropdownItem } from '../types/angular.types' import { EnumPipe, EnumPipeKey } from './enum.pipe' -export interface EnumDropdownItem { - label: string - value: EnumPipeKey -} - @Pipe({ name: 'enumDropdown' }) export class EnumDropdownPipe implements PipeTransform { constructor(private readonly enumPipe: EnumPipe) {} - transform(value: EnumPipeKey[]): EnumDropdownItem[] { + transform(value: EnumPipeKey[]): DropdownItem[] { return value.map((value) => { return { label: this.enumPipe.transform(value), value } }) diff --git a/desktop/src/shared/pipes/enum.pipe.ts b/desktop/src/shared/pipes/enum.pipe.ts index 607919209..d3f3ecb63 100644 --- a/desktop/src/shared/pipes/enum.pipe.ts +++ b/desktop/src/shared/pipes/enum.pipe.ts @@ -5,7 +5,7 @@ import { AutoFocusFittingMode, AutoFocusState, BacklashCompensationMode } from ' import { CameraCaptureState, ExposureMode, ExposureTimeUnit, FrameType, LiveStackerType } from '../types/camera.types' import { FlatWizardState } from '../types/flat-wizard.types' import { GuideDirection, GuideState, GuiderPlotMode, GuiderYAxisUnit } from '../types/guider.types' -import { Bitpix, SCNRProtectionMethod } from '../types/image.types' +import { Bitpix, ImageChannel, SCNRProtectionMethod } from '../types/image.types' import { MountRemoteControlType } from '../types/mount.types' import { PlateSolverType } from '../types/platesolver.types' import { SequenceCaptureMode, SequencerState } from '../types/sequencer.types' @@ -44,6 +44,7 @@ export type EnumPipeKey = | SettingsTabKey | SequencerState | ExposureTimeUnit + | ImageChannel | 'ALL' @Pipe({ name: 'enum' }) @@ -206,6 +207,7 @@ export class EnumPipe implements PipeTransform { GRAVITATIONALLY_LENSED_IMAGE_OF_A_GALAXY: 'Gravitationally Lensed Image of a Galaxy', GRAVITATIONALLY_LENSED_IMAGE_OF_A_QUASAR: 'Gravitationally Lensed Image of a Quasar', GRAVITATIONALLY_LENSED_IMAGE: 'Gravitationally Lensed Image', + GRAY: 'Gray', GREEN: 'Green', GROUP_OF_GALAXIES: 'Group of Galaxies', GRU: 'Grus', diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts index 4972131e5..6675e181d 100644 --- a/desktop/src/shared/services/api.service.ts +++ b/desktop/src/shared/services/api.service.ts @@ -11,7 +11,7 @@ import { Focuser } from '../types/focuser.types' import { HipsSurvey } from '../types/framing.types' import { GuideDirection, GuideOutput, Guider, GuiderHistoryStep, SettleInfo } from '../types/guider.types' import { ConnectionStatus, ConnectionType } from '../types/home.types' -import { CoordinateInterpolation, DetectedStar, FOVCamera, FOVTelescope, ImageAnnotation, ImageInfo, ImageSaveDialog, ImageSolved, ImageTransformation } from '../types/image.types' +import { AnnotateImageRequest, CoordinateInterpolation, DetectedStar, FOVCamera, FOVTelescope, ImageAnnotation, ImageInfo, ImageMousePosition, ImageSaveDialog, ImageSolved, ImageTransformation } from '../types/image.types' import { CelestialLocationType, Mount, MountRemoteControl, MountRemoteControlType, SlewRate, TrackMode } from '../types/mount.types' import { PlateSolverRequest } from '../types/platesolver.types' import { Rotator } from '../types/rotator.types' @@ -174,8 +174,8 @@ export class ApiService { return this.http.get(`mounts/${mount.id}/location/${type}`) } - pointMountHere(mount: Mount, path: string, x: number, y: number) { - const query = this.http.query({ path, x, y }) + pointMountHere(mount: Mount, path: string, point: ImageMousePosition) { + const query = this.http.query({ path, ...point }) return this.http.put(`mounts/${mount.id}/point-here?${query}`) } @@ -536,9 +536,9 @@ export class ApiService { return this.http.get(`sky-atlas/minor-planets/close-approaches?${query}`) } - annotationsOfImage(path: string, starsAndDSOs: boolean = true, minorPlanets: boolean = false, minorPlanetMagLimit: number = 12.0, includeMinorPlanetsWithoutMagnitude: boolean = false, useSimbad: boolean = false) { - const query = this.http.query({ path, starsAndDSOs, minorPlanets, minorPlanetMagLimit, includeMinorPlanetsWithoutMagnitude, useSimbad, hasLocation: true }) - return this.http.get(`image/annotations?${query}`) + annotationsOfImage(path: string, request: AnnotateImageRequest) { + const query = this.http.query({ path, hasLocation: true }) + return this.http.put(`image/annotations?${query}`, request) } saveImageAs(path: string, save: ImageSaveDialog, camera?: Camera) { @@ -663,8 +663,8 @@ export class ApiService { // SOLVER - solverStart(solver: PlateSolverRequest, path: string, blind: boolean, centerRA: Angle, centerDEC: Angle, radius: Angle) { - const query = this.http.query({ path, blind, centerRA, centerDEC, radius }) + solverStart(solver: PlateSolverRequest, path: string) { + const query = this.http.query({ path }) return this.http.put(`plate-solver/start?${query}`, solver) } diff --git a/desktop/src/shared/services/confirmation.service.ts b/desktop/src/shared/services/confirmation.service.ts index 3f996eb4c..45918bfb5 100644 --- a/desktop/src/shared/services/confirmation.service.ts +++ b/desktop/src/shared/services/confirmation.service.ts @@ -26,7 +26,6 @@ export class ConfirmationService { } async processConfirmationEvent(event: ConfirmationEvent) { - console.info('processing confirmation event', event) const response = await this.prime.confirm(event.message) await this.api.confirm(event.idempotencyKey, response === ConfirmEventType.ACCEPT) this.unregister(event.idempotencyKey) diff --git a/desktop/src/shared/services/electron.service.ts b/desktop/src/shared/services/electron.service.ts index 9609f6eeb..4204fb9c5 100644 --- a/desktop/src/shared/services/electron.service.ts +++ b/desktop/src/shared/services/electron.service.ts @@ -126,8 +126,6 @@ export class ElectronService { } on(channel: K, listener: (arg: EventMappedType[K]) => void) { - console.info('listening to channel: %s', channel) - this.ipcRenderer.on(channel, (_, arg) => { listener(arg) }) diff --git a/desktop/src/shared/services/preference.service.ts b/desktop/src/shared/services/preference.service.ts index f0635a816..f757898a6 100644 --- a/desktop/src/shared/services/preference.service.ts +++ b/desktop/src/shared/services/preference.service.ts @@ -9,7 +9,7 @@ import { DEFAULT_FOCUSER_PREFERENCE, Focuser, FocuserPreference, focuserPreferen import { DEFAULT_FRAMING_PREFERENCE, FramingPreference, framingPreferenceWithDefault } from '../types/framing.types' import { DEFAULT_GUIDER_PREFERENCE, GuiderPreference, guiderPreferenceWithDefault } from '../types/guider.types' import { DEFAULT_HOME_PREFERENCE, HomePreference, homePreferenceWithDefault } from '../types/home.types' -import { DEFAULT_IMAGE_PREFERENCE, FOV, ImagePreference } from '../types/image.types' +import { DEFAULT_IMAGE_PREFERENCE, ImagePreference, imagePreferenceWithDefault } from '../types/image.types' import { DEFAULT_MOUNT_PREFERENCE, Mount, MountPreference, mountPreferenceWithDefault } from '../types/mount.types' import { DEFAULT_ROTATOR_PREFERENCE, Rotator, RotatorPreference, rotatorPreferenceWithDefault } from '../types/rotator.types' import { DEFAULT_SEQUENCER_PREFERENCE, SequencerPreference } from '../types/sequencer.types' @@ -82,10 +82,9 @@ export class PreferenceService { } readonly home = new PreferenceData(this.storage, 'home', () => structuredClone(DEFAULT_HOME_PREFERENCE), homePreferenceWithDefault) - readonly imagePreference = new PreferenceData(this.storage, 'image', () => structuredClone(DEFAULT_IMAGE_PREFERENCE)) + readonly imagePreference = new PreferenceData(this.storage, 'image', () => structuredClone(DEFAULT_IMAGE_PREFERENCE), imagePreferenceWithDefault) readonly skyAtlasPreference = new PreferenceData(this.storage, 'atlas', () => structuredClone(DEFAULT_SKY_ATLAS_PREFERENCE)) readonly alignment = new PreferenceData(this.storage, 'alignment', () => structuredClone(DEFAULT_ALIGNMENT_PREFERENCE), alignmentPreferenceWithDefault) - readonly imageFOVs = new PreferenceData(this.storage, 'image.fovs', () => []) readonly calibrationPreference = new PreferenceData(this.storage, 'calibration', () => structuredClone(DEFAULT_CALIBRATION_PREFERENCE), calibrationPreferenceWithDefault) readonly sequencerPreference = new PreferenceData(this.storage, 'sequencer', () => structuredClone(DEFAULT_SEQUENCER_PREFERENCE)) readonly stacker = new PreferenceData(this.storage, 'stacker', () => structuredClone(DEFAULT_STACKER_PREFERENCE), stackerPreferenceWithDefault) diff --git a/desktop/src/shared/types/angular.types.ts b/desktop/src/shared/types/angular.types.ts new file mode 100644 index 000000000..713244b9b --- /dev/null +++ b/desktop/src/shared/types/angular.types.ts @@ -0,0 +1,4 @@ +export interface DropdownItem { + label: string + value: T +} diff --git a/desktop/src/shared/types/camera.types.ts b/desktop/src/shared/types/camera.types.ts index 60136dc83..b59246e2b 100644 --- a/desktop/src/shared/types/camera.types.ts +++ b/desktop/src/shared/types/camera.types.ts @@ -22,12 +22,7 @@ export type LiveStackerType = 'SIRIL' | 'PIXINSIGHT' export type CameraCaptureState = 'IDLE' | 'CAPTURE_STARTED' | 'EXPOSURE_STARTED' | 'EXPOSURING' | 'WAITING' | 'SETTLING' | 'DITHERING' | 'STACKING' | 'PAUSING' | 'PAUSED' | 'EXPOSURE_FINISHED' | 'CAPTURE_FINISHED' -export enum ExposureTimeUnit { - MINUTE = 'MINUTE', - SECOND = 'SECOND', - MILLISECOND = 'MILLISECOND', - MICROSECOND = 'MICROSECOND', -} +export type ExposureTimeUnit = 'MINUTE' | 'SECOND' | 'MILLISECOND' | 'MICROSECOND' export interface Camera extends GuideOutput, Thermometer { readonly exposuring: boolean @@ -323,7 +318,7 @@ export const DEFAULT_CAMERA_START_CAPTURE: CameraStartCapture = { export const DEFAULT_CAMERA_PREFERENCE: CameraPreference = { request: DEFAULT_CAMERA_START_CAPTURE, setpointTemperature: 0, - exposureTimeUnit: ExposureTimeUnit.MICROSECOND, + exposureTimeUnit: 'MICROSECOND', exposureMode: 'SINGLE', subFrame: false, } diff --git a/desktop/src/shared/types/image.types.ts b/desktop/src/shared/types/image.types.ts index 2da2f3a1f..4f7a15348 100644 --- a/desktop/src/shared/types/image.types.ts +++ b/desktop/src/shared/types/image.types.ts @@ -1,8 +1,10 @@ import type { Point, Size } from 'electron' +import type { PanZoom } from 'panzoom' +import type { CoordinateInterpolator, InterpolatedCoordinate } from '../utils/coordinate-interpolation' import type { Angle, AstronomicalObject, DeepSkyObject, EquatorialCoordinateJ2000, Star } from './atlas.types' import type { Camera, CameraStartCapture, FrameType } from './camera.types' -import type { PlateSolverRequest } from './platesolver.types' -import type { StarDetectionRequest } from './stardetector.types' +import { DEFAULT_PLATE_SOLVER_REQUEST, plateSolverRequestWithDefault, type PlateSolverRequest } from './platesolver.types' +import { DEFAULT_STAR_DETECTION_REQUEST, starDetectionRequestWithDefault, type StarDetectionRequest } from './stardetector.types' export type ImageChannel = 'RED' | 'GREEN' | 'BLUE' | 'GRAY' @@ -16,6 +18,10 @@ export type Bitpix = 'BYTE' | 'SHORT' | 'INTEGER' | 'LONG' | 'FLOAT' | 'DOUBLE' export type LiveStackingMode = 'NONE' | 'RAW' | 'STACKED' +export type ImageCalibrationSource = 'CAMERA' | 'MENU' + +export type ImageMousePosition = Point + export interface Image { type: FrameType width: number @@ -28,7 +34,18 @@ export interface Image { filter?: string } -export interface FITSHeaderItem { +export interface ImagePreference { + savePath?: string + crossHair: boolean + transformation: ImageTransformation + solver: PlateSolverRequest + starDetector: StarDetectionRequest + annotation: AnnotateImageRequest + fovs: FOV[] + pixelated: boolean +} + +export interface ImageHeaderItem { name: string value: string } @@ -39,13 +56,11 @@ export interface ImageInfo { width: number height: number mono: boolean - stretchShadow: number - stretchHighlight: number - stretchMidtone: number + stretch: ImageStretch rightAscension?: Angle declination?: Angle solved?: ImageSolved - headers: FITSHeaderItem[] + headers: ImageHeaderItem[] bitpix: Bitpix statistics: ImageStatistics } @@ -67,17 +82,6 @@ export interface ImageSolved extends EquatorialCoordinateJ2000 { radius: number } -export const DEFAULT_IMAGE_SOLVED: ImageSolved = { - solved: false, - orientation: 0, - scale: 0, - width: 0, - height: 0, - radius: 0, - rightAscensionJ2000: '00h00m00s', - declinationJ2000: '+000ยฐ00\'00"', -} - export interface CoordinateInterpolation { ma: number[] md: number[] @@ -111,16 +115,6 @@ export interface ImageStatisticsBitOption { bitLength: number } -export const IMAGE_STATISTICS_BIT_OPTIONS: ImageStatisticsBitOption[] = [ - { name: 'Normalized: [0, 1]', rangeMax: 1, bitLength: 16 }, - { name: '8-bit: [0, 255]', rangeMax: 255, bitLength: 8 }, - { name: '9-bit: [0, 511]', rangeMax: 511, bitLength: 9 }, - { name: '10-bit: [0, 1023]', rangeMax: 1023, bitLength: 10 }, - { name: '12-bit: [0, 4095]', rangeMax: 4095, bitLength: 12 }, - { name: '14-bit: [0, 16383]', rangeMax: 16383, bitLength: 14 }, - { name: '16-bit: [0, 65535]', rangeMax: 65535, bitLength: 16 }, -] as const - export interface ImageStatistics { count: number maxCount: number @@ -134,34 +128,6 @@ export interface ImageStatistics { maximum: number } -export type StarDetectionImagePreference = Pick - -export interface PlateSolverImagePreference extends Pick { - radius: number - focalLength: number - pixelSize: number -} - -export interface ImagePreference { - savePath?: string - solver?: PlateSolverImagePreference - starDetection?: StarDetectionImagePreference -} - -export const DEFAULT_IMAGE_PREFERENCE: ImagePreference = { - solver: { - type: 'ASTAP', - radius: 4, - focalLength: 0, - pixelSize: 0, - }, - starDetection: { - type: 'ASTAP', - minSNR: 0, - maxStars: 0, - }, -} - export interface OpenImage { camera?: Camera path: string @@ -174,11 +140,10 @@ export interface OpenImage { export interface ImageData { camera?: Camera path?: string - liveStackedPath?: string - source?: ImageSource + source: ImageSource title?: string capture?: CameraStartCapture - exposureCount?: number + exposureCount: number } export interface FOV { @@ -199,24 +164,6 @@ export interface FOV { } } -export const DEFAULT_FOV: FOV = { - enabled: true, - focalLength: 600, - aperture: 80, - cameraSize: { - width: 1392, - height: 1040, - }, - pixelSize: { - width: 6.45, - height: 6.45, - }, - barlowReducer: 1, - bin: 1, - rotation: 0, - color: '#FFFF00', -} - export interface FOVEquipment { id: number name: string @@ -234,39 +181,45 @@ export interface FOVTelescope extends FOVEquipment { focalLength: number } -export interface ImageSCNRDialog { - showDialog: boolean +export interface ImageSCNR { channel?: ImageChannel amount: number method: SCNRProtectionMethod } -export interface ImageFITSHeadersDialog { +export interface ImageSCNRDialog { showDialog: boolean - headers: FITSHeaderItem[] + transformation: ImageSCNR } -export interface ImageStretchDialog { +export interface ImageHeadersDialog { showDialog: boolean + headers: ImageHeaderItem[] +} + +export interface ImageStretch { auto: boolean shadow: number highlight: number midtone: number } -export interface ImageSolverDialog extends PlateSolverImagePreference { +export interface ImageStretchDialog { + showDialog: boolean + transformation: ImageStretch +} + +export interface ImageSolverDialog { showDialog: boolean running: boolean - blind: boolean - centerRA: Angle - centerDEC: Angle + request: PlateSolverRequest readonly solved: ImageSolved } -export interface ImageFOVDialog extends FOV { +export interface ImageFOVDialog { showDialog: boolean + selected: FOV fovs: FOV[] - edited?: FOV showCameraDialog: boolean cameras: FOVCamera[] camera?: FOVCamera @@ -275,12 +228,8 @@ export interface ImageFOVDialog extends FOV { telescope?: FOVTelescope } -export interface ImageROI { +export interface ImageROI extends Size, Point { show: boolean - x: number - y: number - width: number - height: number } export interface ImageSaveDialog { @@ -296,22 +245,27 @@ export interface ImageTransformation { force: boolean calibrationGroup?: string debayer: boolean - stretch: Omit + stretch: ImageStretch mirrorHorizontal: boolean mirrorVertical: boolean invert: boolean - scnr: Pick + scnr: ImageSCNR + useJPEG: boolean } -export interface ImageAnnotationDialog { - showDialog: boolean - running: boolean - visible: boolean +export interface AnnotateImageRequest { useStarsAndDSOs: boolean useMinorPlanets: boolean minorPlanetsMagLimit: number includeMinorPlanetsWithoutMagnitude: boolean useSimbad: boolean +} + +export interface ImageAnnotationDialog { + showDialog: boolean + running: boolean + visible: boolean + request: AnnotateImageRequest data: ImageAnnotation[] } @@ -323,16 +277,317 @@ export interface ROISelected { height: number } -export interface StarDetectionDialog extends StarDetectionImagePreference { +export interface StarDetectorDialog { showDialog: boolean running: boolean visible: boolean stars: DetectedStar[] computed: ComputedDetectedStars selected: DetectedStar + request: StarDetectionRequest } -export interface AnnotationInfoDialog { +export interface AstronomicalObjectDialog { showDialog: boolean info?: AstronomicalObject & Partial } + +export interface ImageStatisticsDialog { + showDialog: boolean + statistics: ImageStatistics + bitOption: ImageStatisticsBitOption +} + +export interface ImageMouseCoordinates extends InterpolatedCoordinate, ImageMousePosition { + show: boolean + interpolator?: CoordinateInterpolator +} + +export interface ImageCalibration { + source: ImageCalibrationSource +} + +export interface ImageLiveStacking { + mode: LiveStackingMode + path?: string +} + +export interface ImageZoom { + scale: number + panZoom?: PanZoom +} + +export interface ImageSettingsDialog { + showDialog: boolean + preference: ImagePreference +} + +export const DEFAULT_IMAGE_SOLVED: ImageSolved = { + solved: false, + orientation: 0, + scale: 0, + width: 0, + height: 0, + radius: 0, + rightAscensionJ2000: '00h00m00s', + declinationJ2000: '+000ยฐ00\'00"', +} + +export const DEFAULT_IMAGE_STRETCH: ImageStretch = { + auto: true, + shadow: 0, + highlight: 1, + midtone: 0.5, +} + +export const DEFAULT_IMAGE_STRETCH_DIALOG: ImageStretchDialog = { + showDialog: false, + transformation: DEFAULT_IMAGE_STRETCH, +} + +export const DEFAULT_IMAGE_SCNR: ImageSCNR = { + amount: 0.5, + method: 'AVERAGE_NEUTRAL', +} + +export const DEFAULT_IMAGE_SCNR_DIALOG: ImageSCNRDialog = { + showDialog: false, + transformation: DEFAULT_IMAGE_SCNR, +} + +export const DEFAULT_IMAGE_TRANSFORMATION: ImageTransformation = { + force: false, + debayer: true, + stretch: DEFAULT_IMAGE_STRETCH, + mirrorHorizontal: false, + mirrorVertical: false, + invert: false, + scnr: DEFAULT_IMAGE_SCNR, + useJPEG: true, +} + +export const DEFAULT_IMAGE_SOLVER_DIALOG: ImageSolverDialog = { + showDialog: false, + running: false, + request: DEFAULT_PLATE_SOLVER_REQUEST, + solved: DEFAULT_IMAGE_SOLVED, +} + +export const IMAGE_STATISTICS_BIT_OPTIONS: ImageStatisticsBitOption[] = [ + { name: 'Normalized: [0, 1]', rangeMax: 1, bitLength: 16 }, + { name: '8-bit: [0, 255]', rangeMax: 255, bitLength: 8 }, + { name: '9-bit: [0, 511]', rangeMax: 511, bitLength: 9 }, + { name: '10-bit: [0, 1023]', rangeMax: 1023, bitLength: 10 }, + { name: '12-bit: [0, 4095]', rangeMax: 4095, bitLength: 12 }, + { name: '14-bit: [0, 16383]', rangeMax: 16383, bitLength: 14 }, + { name: '16-bit: [0, 65535]', rangeMax: 65535, bitLength: 16 }, +] as const + +export const DEFAULT_FOV: FOV = { + enabled: true, + focalLength: 600, + aperture: 80, + cameraSize: { + width: 1392, + height: 1040, + }, + pixelSize: { + width: 6.45, + height: 6.45, + }, + barlowReducer: 1, + bin: 1, + rotation: 0, + color: '#FFFF00', +} + +export const DEFAULT_IMAGE_FOV_DIALOG: ImageFOVDialog = { + selected: DEFAULT_FOV, + showDialog: false, + fovs: [], + showCameraDialog: false, + cameras: [], + showTelescopeDialog: false, + telescopes: [], +} + +export const DEFAULT_COMPUTED_DETECTED_STARS: ComputedDetectedStars = { + hfd: 0, + snr: 0, + stdDev: 0, + fluxMax: 0, + fluxMin: 0, +} + +export const DEFAULT_DETECTED_STAR: DetectedStar = { + x: 0, + y: 0, + snr: 0, + hfd: 0, + flux: 0, +} + +export const DEFAULT_STAR_DETECTOR_DIALOG: StarDetectorDialog = { + showDialog: false, + running: false, + visible: false, + stars: [], + computed: DEFAULT_COMPUTED_DETECTED_STARS, + selected: DEFAULT_DETECTED_STAR, + request: DEFAULT_STAR_DETECTION_REQUEST, +} + +export const DEFAULT_ANNOTATE_IMAGE_REQUEST: AnnotateImageRequest = { + useStarsAndDSOs: true, + useMinorPlanets: false, + minorPlanetsMagLimit: 18.0, + includeMinorPlanetsWithoutMagnitude: true, + useSimbad: false, +} + +export const DEFAULT_IMAGE_ANNOTATION_DIALOG: ImageAnnotationDialog = { + showDialog: false, + running: false, + visible: false, + data: [], + request: DEFAULT_ANNOTATE_IMAGE_REQUEST, +} + +export const DEFAULT_IMAGE_ROI: ImageROI = { + show: false, + x: 0, + y: 0, + width: 0, + height: 0, +} + +export const DEFAULT_IMAGE_SAVE_DIALOG: ImageSaveDialog = { + showDialog: false, + format: 'FITS', + bitpix: 'BYTE', + path: '', + shouldBeTransformed: true, + transformation: DEFAULT_IMAGE_TRANSFORMATION, +} + +export const DEFAULT_IMAGE_STATISTICS: ImageStatistics = { + count: 0, + maxCount: 0, + mean: 0, + sumOfSquares: 0, + median: 0, + variance: 0, + stdDev: 0, + avgDev: 0, + minimum: 0, + maximum: 0, +} + +export const DEFAULT_IMAGE_STATISTICS_DIALOG: ImageStatisticsDialog = { + showDialog: false, + statistics: DEFAULT_IMAGE_STATISTICS, + bitOption: IMAGE_STATISTICS_BIT_OPTIONS[0], +} + +export const DEFAULT_IMAGE_DATA: ImageData = { + source: 'PATH', + exposureCount: 0, +} + +export const DEFAULT_IMAGE_MOUSE_POSITION: ImageMousePosition = { + x: 0, + y: 0, +} + +export const DEFAULT_IMAGE_MOUSE_COORDINATES: ImageMouseCoordinates = { + show: false, + ...DEFAULT_IMAGE_MOUSE_POSITION, + alpha: '', + delta: '', + rightAscensionJ2000: '', + declinationJ2000: '', +} + +export const DEFAULT_IMAGE_CALIBRATION: ImageCalibration = { + source: 'CAMERA', +} + +export const DEFAULT_IMAGE_LIVE_STACKING: ImageLiveStacking = { + mode: 'NONE', +} + +export const DEFAULT_IMAGE_ZOOM: ImageZoom = { + scale: 1, +} + +export const DEFAULT_IMAGE_PREFERENCE: ImagePreference = { + crossHair: false, + transformation: DEFAULT_IMAGE_TRANSFORMATION, + solver: DEFAULT_PLATE_SOLVER_REQUEST, + starDetector: DEFAULT_STAR_DETECTION_REQUEST, + annotation: DEFAULT_ANNOTATE_IMAGE_REQUEST, + fovs: [], + pixelated: true, +} + +export const DEFAULT_IMAGE_SETTINGS_DIALOG: ImageSettingsDialog = { + showDialog: false, + preference: DEFAULT_IMAGE_PREFERENCE, +} + +export function imageFormatFromExtension(extension: string): ImageFormat { + return ( + extension === '.xisf' ? 'XISF' + : extension === '.png' ? 'PNG' + : extension === '.jpg' ? 'JPG' + : 'FITS' + ) +} + +export function imageStretchWithDefault(stretch?: Partial, source: ImageStretch = DEFAULT_IMAGE_STRETCH) { + if (!stretch) return structuredClone(source) + stretch.auto ??= source.auto + stretch.shadow ??= source.shadow + stretch.highlight ??= source.highlight + stretch.midtone ??= source.midtone + return stretch as ImageStretch +} + +export function annotateImageRequestWithDefault(request?: Partial, source: AnnotateImageRequest = DEFAULT_ANNOTATE_IMAGE_REQUEST) { + if (!request) return structuredClone(source) + request.useStarsAndDSOs ??= source.useStarsAndDSOs + request.useMinorPlanets ??= source.useMinorPlanets + request.minorPlanetsMagLimit ??= source.minorPlanetsMagLimit + request.includeMinorPlanetsWithoutMagnitude ??= source.includeMinorPlanetsWithoutMagnitude + request.useSimbad ??= source.useSimbad + return request as AnnotateImageRequest +} + +export function imageTransformationWithDefault(transformation?: Partial, source: ImageTransformation = DEFAULT_IMAGE_TRANSFORMATION) { + if (!transformation) return structuredClone(source) + transformation.force ??= source.force + transformation.calibrationGroup ||= source.calibrationGroup + transformation.debayer ??= source.debayer + transformation.stretch = imageStretchWithDefault(transformation.stretch, source.stretch) + transformation.mirrorHorizontal ??= source.mirrorHorizontal + transformation.mirrorVertical ??= source.mirrorVertical + transformation.invert ??= source.invert + transformation.scnr ??= source.scnr + transformation.useJPEG ??= source.useJPEG + return transformation as ImageTransformation +} + +export function imagePreferenceWithDefault(preference?: Partial, source: ImagePreference = DEFAULT_IMAGE_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.savePath ||= source.savePath + preference.crossHair ??= source.crossHair + preference.transformation = imageTransformationWithDefault(preference.transformation, source.transformation) + preference.solver = plateSolverRequestWithDefault(preference.solver, source.solver) + preference.starDetector = starDetectionRequestWithDefault(preference.starDetector, source.starDetector) + preference.annotation = annotateImageRequestWithDefault(preference.annotation, source.annotation) + preference.fovs ??= structuredClone(source.fovs) + preference.pixelated ??= source.pixelated + preference.fovs.forEach((e) => (e.enabled = false)) + preference.fovs.forEach((e) => (e.computed = undefined)) + return preference as ImagePreference +} diff --git a/desktop/src/shared/types/platesolver.types.ts b/desktop/src/shared/types/platesolver.types.ts index c573e17c5..b79bc1f52 100644 --- a/desktop/src/shared/types/platesolver.types.ts +++ b/desktop/src/shared/types/platesolver.types.ts @@ -1,3 +1,5 @@ +import type { Angle } from './atlas.types' + export type PlateSolverType = 'ASTROMETRY_NET' | 'ASTROMETRY_NET_ONLINE' | 'ASTAP' | 'SIRIL' | 'PIXINSIGHT' export interface PlateSolverSettings { @@ -11,8 +13,12 @@ export interface PlateSolverSettings { export interface PlateSolverRequest extends PlateSolverSettings { type: PlateSolverType - pixelSize?: number - focalLength?: number + blind: boolean + centerRA: Angle + centerDEC: Angle + radius: Angle + pixelSize: number + focalLength: number } export const NOVA_ASTROMETRY_NET_URL = 'https://nova.astrometry.net/' @@ -29,6 +35,12 @@ export const DEFAULT_PLATE_SOLVER_SETTINGS: PlateSolverSettings = { export const DEFAULT_PLATE_SOLVER_REQUEST: PlateSolverRequest = { ...DEFAULT_PLATE_SOLVER_SETTINGS, type: 'ASTAP', + blind: true, + centerRA: 0, + centerDEC: 0, + radius: 4, + focalLength: 0, + pixelSize: 0, } export function plateSolverSettingsWithDefault(settings?: Partial, source: PlateSolverSettings = DEFAULT_PLATE_SOLVER_SETTINGS) { diff --git a/desktop/tsconfig.serve.json b/desktop/tsconfig.serve.json index 44fe8ddb5..06b36ba89 100644 --- a/desktop/tsconfig.serve.json +++ b/desktop/tsconfig.serve.json @@ -2,11 +2,10 @@ "compilerOptions": { "sourceMap": true, "declaration": false, - "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "resolveJsonModule": true, - "module": "CommonJS", + "module": "NodeNext", "target": "ES2022", "noFallthroughCasesInSwitch": true, "esModuleInterop": true, diff --git a/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt b/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt index fef1fce0e..2e5f3c609 100644 --- a/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt +++ b/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt @@ -71,11 +71,8 @@ data object FitsFormat : ImageFormat { val numberOfChannels = header.numberOfChannels val bitpix = header.bitpix val position = source.position - val rangeMin = header.getFloat(FitsKeyword.DATAMIN, 0f) - val rangeMax = header.getFloat(FitsKeyword.DATAMAX, 1f) - val range = rangeMin..rangeMax - val data = SeekableSourceImageData(source, position, width, height, numberOfChannels, bitpix, range) + val data = SeekableSourceImageData(source, position, width, height, numberOfChannels, bitpix) val skipBytes = computeRemainingBytesToSkip(data.totalSizeInBytes) if (skipBytes > 0L) source.seek(position + data.totalSizeInBytes + skipBytes) diff --git a/nebulosa-fits/src/main/kotlin/nebulosa/fits/SeekableSourceImageData.kt b/nebulosa-fits/src/main/kotlin/nebulosa/fits/SeekableSourceImageData.kt index 8733dde85..c514726a9 100644 --- a/nebulosa-fits/src/main/kotlin/nebulosa/fits/SeekableSourceImageData.kt +++ b/nebulosa-fits/src/main/kotlin/nebulosa/fits/SeekableSourceImageData.kt @@ -7,7 +7,6 @@ import nebulosa.io.SeekableSource import nebulosa.log.loggerFor import okio.Buffer import okio.Sink -import kotlin.math.max import kotlin.math.min @Suppress("NOTHING_TO_INLINE") @@ -18,7 +17,6 @@ internal data class SeekableSourceImageData( override val height: Int, override val numberOfChannels: Int, private val bitpix: Bitpix, - private val range: ClosedFloatingPointRange, ) : ImageData { @JvmField internal val channelSizeInBytes = (numberOfPixels * bitpix.byteLength).toLong() @@ -100,14 +98,12 @@ internal data class SeekableSourceImageData( } if (min < 0f || max > 1f) { - val rangeMin = min(range.start, min) - val rangeMax = max(range.endInclusive, max) - val rangeDelta = rangeMax - rangeMin + val rangeDelta = max - min - LOG.info("rescaling [{}, {}] to [0, 1]. channel={}, delta={}", rangeMin, rangeMax, channel, rangeDelta) + LOG.info("rescaling [{}, {}] to [0, 1]. channel={}, delta={}", min, max, channel, rangeDelta) for (i in output.indices) { - output[i] = (output[i] - rangeMin) / rangeDelta + output[i] = (output[i] - min) / rangeDelta } } } diff --git a/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/transformation/ScreenTransformFunction.kt b/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/transformation/ScreenTransformFunction.kt index 8c9737a48..87c17d9bc 100644 --- a/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/transformation/ScreenTransformFunction.kt +++ b/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/transformation/ScreenTransformFunction.kt @@ -16,11 +16,13 @@ data class ScreenTransformFunction( ) : TransformAlgorithm { data class Parameters( - val midtone: Float = 0.5f, - val shadow: Float = 0f, - val highlight: Float = 1f, + @JvmField val midtone: Float = 0.5f, + @JvmField val shadow: Float = 0f, + @JvmField val highlight: Float = 1f, ) { + constructor(midtone: Int, shadow: Int, highlight: Int) : this(midtone / 65536f, shadow / 65536f, highlight / 65536f) + companion object { @JvmStatic val DEFAULT = Parameters() diff --git a/nebulosa-image/src/test/kotlin/FitsTransformAlgorithmTest.kt b/nebulosa-image/src/test/kotlin/FitsTransformAlgorithmTest.kt index fba695c05..629b6512d 100644 --- a/nebulosa-image/src/test/kotlin/FitsTransformAlgorithmTest.kt +++ b/nebulosa-image/src/test/kotlin/FitsTransformAlgorithmTest.kt @@ -15,373 +15,371 @@ import org.junit.jupiter.api.Test class FitsTransformAlgorithmTest { - init { - @Test - fun monoRaw() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.save("fits-mono-raw").second shouldBe "e17cfc29c3b343409cd8617b6913330e" - } - - @Test - fun monoVerticalFlip() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(VerticalFlip) - mImage.save("fits-mono-vertical-flip").second shouldBe "262260dfe719726c0e7829a088279a21" - } - - @Test - fun monoHorizontalFlip() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(HorizontalFlip) - mImage.save("fits-mono-horizontal-flip").second shouldBe "daf0f05db5de3750962f338527564b27" - } - - @Test - fun monoVerticalAndHorizontalFlip() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(VerticalFlip, HorizontalFlip) - mImage.save("fits-mono-vertical-horizontal-flip").second shouldBe "3bc81f579a0e34ce9312c3b242209166" - } - - @Test - fun monoSubframe() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - val nImage = mImage.transform(SubFrame(45, 70, 16, 16)) - nImage.width shouldBeExactly 16 - nImage.height shouldBeExactly 16 - nImage.mono.shouldBeTrue() - nImage.save("fits-mono-subframe").second shouldBe "4d9984e778f82dde10b9aeeee7a29fe0" - } - - @Test - fun monoSharpen() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(Sharpen) - mImage.save("fits-mono-sharpen").second shouldBe "0b162242a4e673f6480b5206cf49ca50" - } - - @Test - fun monoMean() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(Mean) - mImage.save("fits-mono-mean").second shouldBe "cf866292f657c379ae3965931dd8eeea" - } - - @Test - fun monoInvert() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(Invert) - mImage.save("fits-mono-invert").second shouldBe "6e94463bb5b9561de1f0ee0a154db53e" - } - - @Test - fun monoEmboss() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(Emboss) - mImage.save("fits-mono-emboss").second shouldBe "94a8ef5e4573e392d087cf10c905ba12" - } - - @Test - fun monoEdges() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(Edges) - mImage.save("fits-mono-edges").second shouldBe "27ccd5f5e6098d0cae27e7495e18dd72" - } - - @Test - fun monoBlur() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(Blur) - mImage.save("fits-mono-blur").second shouldBe "f2c5466dccf71b5c4bee86c5fbbb95fc" - } - - @Test - fun monoGaussianBlur() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(GaussianBlur(sigma = 5.0, size = 9)) - mImage.save("fits-mono-gaussian-blur").second shouldBe "69057b0c4461fb0d55b779da9e72fd69" - } - - @Test - fun monoStfMidtone01Shadow00Highlight10() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.1f)) - mImage.save("fits-mono-stf-01-00-10").second shouldBe "22c0bd985e70a01330722d912869d6ee" - } - - @Test - fun monoStfMidtone09Shadow00Highlight10() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.9f)) - mImage.save("fits-mono-stf-09-00-10").second shouldBe "553ccb7546dce3a8f742d5e8f7c58a3f" - } - - @Test - fun monoStfMidtone01Shadow05Highlight10() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.1f, shadow = 0.5f)) - mImage.save("fits-mono-stf-01-05-10").second shouldBe "f31db854fab72033dce2f8c572ec6783" - } - - @Test - fun monoStfMidtone09Shadow05Highlight10() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.9f, shadow = 0.5f)) - mImage.save("fits-mono-stf-09-05-10").second shouldBe "633b49c4a1dbb5ad8e6a9d74f330636d" - } - - @Test - fun monoStfMidtone01Shadow00Highlight05() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.1f, highlight = 0.5f)) - mImage.save("fits-mono-stf-01-00-05").second shouldBe "26036937eb3e5f99cd6129f709ce4b31" - } - - @Test - fun monoStfMidtone09Shadow00Highlight05() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.9f, highlight = 0.5f)) - mImage.save("fits-mono-stf-09-00-05").second shouldBe "e8f694dae666ac15ce2f8a169eb84024" - } - - @Test - fun monoStfMidtone01Shadow04Highlight06() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.1f, 0.4f, 0.6f)) - mImage.save("fits-mono-stf-01-04-06").second shouldBe "5226aba21669a24f985703b3e7220568" - } - - @Test - fun monoStfMidtone09Shadow04Highlight06() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.9f, 0.4f, 0.6f)) - mImage.save("fits-mono-stf-09-04-06").second shouldBe "c2acb25ef7be92a51f63e673ec9a850f" - } - - @Test - fun monoAutoStf() { - val mImage = NGC3344_MONO_8_FITS.fits().asImage() - mImage.transform(AutoScreenTransformFunction) - mImage.save("fits-mono-auto-stf").second shouldBe "e17cfc29c3b343409cd8617b6913330e" - } - - @Test - fun colorRaw() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.save("fits-color-raw").second shouldBe "18fb83e240bc7a4cbafbc1aba2741db6" - } - - @Test - fun colorVerticalFlip() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(VerticalFlip) - mImage.save("fits-color-vertical-flip").second shouldBe "b717ecda5c5bba50cfa06304ef2bca88" - } - - @Test - fun colorHorizontalFlip() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(HorizontalFlip) - mImage.save("fits-color-horizontal-flip").second shouldBe "f70228600c77551473008ed4b9986439" - } - - @Test - fun colorVerticalAndHorizontalFlip() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(VerticalFlip, HorizontalFlip) - mImage.save("fits-color-vertical-horizontal-flip").second shouldBe "1237314044f20307b76203148af855e3" - } - - @Test - fun colorSubframe() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - val nImage = mImage.transform(SubFrame(45, 70, 16, 16)) - nImage.width shouldBeExactly 16 - nImage.height shouldBeExactly 16 - nImage.mono.shouldBeFalse() - nImage.save("fits-color-subframe").second shouldBe "282fc4fdf9142fcb4b18e1df1eef4caa" - } - - @Test - fun colorSharpen() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(Sharpen) - mImage.save("fits-color-sharpen").second shouldBe "e562282bdafdeba6ce88981bb9c3ba61" - } - - @Test - fun colorMean() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(Mean) - mImage.save("fits-color-mean").second shouldBe "a8380d928aaa756e202ba43bd3a2f207" - } - - @Test - fun colorInvert() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(Invert) - mImage.save("fits-color-invert").second shouldBe "decad269ec26450aebeaf7546867b5f8" - } - - @Test - fun colorEmboss() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(Emboss) - mImage.save("fits-color-emboss").second shouldBe "58d69250f1233055aa33f9ec7ca40af1" - } - - @Test - fun colorEdges() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(Edges) - mImage.save("fits-color-edges").second shouldBe "091f2955740a8edcd2401dc416d19d51" - } - - @Test - fun colorBlur() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(Blur) - mImage.save("fits-color-blur").second shouldBe "0fca440b763de5380fa29de736f3c792" - } - - @Test - fun colorGaussianBlur() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(GaussianBlur(sigma = 5.0, size = 9)) - mImage.save("fits-color-gaussian-blur").second shouldBe "394d1a4f136f15c802dd73004c421d64" - } - - @Test - fun colorStfMidtone01Shadow00Highlight10() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.1f)) - mImage.save("fits-color-stf-01-00-10").second shouldBe "e952bd263df6fd275b9a80aca554cb4b" - } - - @Test - fun colorStfMidtone09Shadow00Highlight10() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.9f)) - mImage.save("fits-color-stf-09-00-10").second shouldBe "038809d7612018e2e5c19d5e1f551abd" - } - - @Test - fun colorStfMidtone01Shadow05Highlight10() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.1f, shadow = 0.5f)) - mImage.save("fits-color-stf-01-05-10").second shouldBe "70e812260f56f8621002327575611f31" - } - - @Test - fun colorStfMidtone09Shadow05Highlight10() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.9f, shadow = 0.5f)) - mImage.save("fits-color-stf-09-05-10").second shouldBe "6ca400f617f466a9eb02a3a6f2985d99" - } - - @Test - fun colorStfMidtone01Shadow00Highlight05() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.1f, highlight = 0.5f)) - mImage.save("fits-color-stf-01-00-05").second shouldBe "3cd98ee9a8949d5100295acccd77010b" - } - - @Test - fun colorStfMidtone09Shadow00Highlight05() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.9f, highlight = 0.5f)) - mImage.save("fits-color-stf-09-00-05").second shouldBe "2cfeffc88c893cc5883d8a2221f29b91" - } - - @Test - fun colorStfMidtone01Shadow04Highlight06() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.1f, 0.4f, 0.6f)) - mImage.save("fits-color-stf-01-04-06").second shouldBe "532a07a1a166eb007c2e40651aec2097" - } - - @Test - fun colorStfMidtone09Shadow04Highlight06() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(ScreenTransformFunction(0.9f, 0.4f, 0.6f)) - mImage.save("fits-color-stf-09-04-06").second shouldBe "eb3d940d9fd2c8814e930715e89897c4" - } - - @Test - fun colorAutoStf() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(AutoScreenTransformFunction) - mImage.save("fits-color-auto-stf").second shouldBe "a9c3657d8597b927607eb438e666d3a0" - } - - @Test - fun colorScnrMaximumMask() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(SubtractiveChromaticNoiseReduction(ImageChannel.RED, 1f, ProtectionMethod.MAXIMUM_MASK)) - mImage.save("fits-color-scnr-maximum-mask").second shouldBe "e7d2155e18ff1e3172f4e849ae983145" - } - - @Test - fun colorScnrAdditiveMask() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(SubtractiveChromaticNoiseReduction(ImageChannel.RED, 1f, ProtectionMethod.ADDITIVE_MASK)) - mImage.save("fits-color-scnr-additive-mask").second shouldBe "a458c44cedcda704de16d80053fd87eb" - } - - @Test - fun colorScnrAverageNeutral() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(SubtractiveChromaticNoiseReduction(ImageChannel.RED, 1f, ProtectionMethod.AVERAGE_NEUTRAL)) - mImage.save("fits-color-scnr-average-neutral").second shouldBe "e07345ffc4982a62301c95c76d3efb35" - } - - @Test - fun colorScnrMaximumNeutral() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(SubtractiveChromaticNoiseReduction(ImageChannel.RED, 1f, ProtectionMethod.MAXIMUM_NEUTRAL)) - mImage.save("fits-color-scnr-maximum-neutral").second shouldBe "a1d4b04f57b001ba4a996bab0407fd7e" - } - - @Test - fun colorScnrMinimumNeutral() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - mImage.transform(SubtractiveChromaticNoiseReduction(ImageChannel.RED, 1f, ProtectionMethod.MINIMUM_NEUTRAL)) - mImage.save("fits-color-scnr-minimum-neutral").second shouldBe "8b7be57ff38da9c97b35d7888047c0f9" - } - - @Test - fun colorGrayscaleBt709() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - val nImage = mImage.transform(Grayscale.BT709) - nImage.save("fits-color-grayscale-bt709").second shouldBe "cab675aa35390a2d58cd48555d91054f" - } - - @Test - fun colorGrayscaleRmy() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - val nImage = mImage.transform(Grayscale.RMY) - nImage.save("fits-color-grayscale-rmy").second shouldBe "e113627002a4178d1010a2f6246e325f" - } - - @Test - fun colorGrayscaleY() { - val mImage = NGC3344_COLOR_32_FITS.fits().asImage() - val nImage = mImage.transform(Grayscale.Y) - nImage.save("fits-color-grayscale-y").second shouldBe "24dd4a7e0fa9e4be34c53c924a78a940" - } - - @Test - fun colorDebayer() { - val mImage = DEBAYER_FITS.fits().asImage() - val nImage = mImage.transform(AutoScreenTransformFunction) - nImage.save("fits-color-debayer").second shouldBe "86b5bdd67dfd6bbf5495afae4bf2bc04" - } - - @Test - fun colorNoDebayer() { - val mImage = DEBAYER_FITS.fits().asImage(false) - val nImage = mImage.transform(AutoScreenTransformFunction) - nImage.save("fits-color-no-debayer").second shouldBe "958ccea020deec1f0c075042a9ba37c3" - } + @Test + fun monoRaw() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.save("fits-mono-raw").second shouldBe "e17cfc29c3b343409cd8617b6913330e" + } + + @Test + fun monoVerticalFlip() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(VerticalFlip) + mImage.save("fits-mono-vertical-flip").second shouldBe "262260dfe719726c0e7829a088279a21" + } + + @Test + fun monoHorizontalFlip() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(HorizontalFlip) + mImage.save("fits-mono-horizontal-flip").second shouldBe "daf0f05db5de3750962f338527564b27" + } + + @Test + fun monoVerticalAndHorizontalFlip() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(VerticalFlip, HorizontalFlip) + mImage.save("fits-mono-vertical-horizontal-flip").second shouldBe "3bc81f579a0e34ce9312c3b242209166" + } + + @Test + fun monoSubframe() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + val nImage = mImage.transform(SubFrame(45, 70, 16, 16)) + nImage.width shouldBeExactly 16 + nImage.height shouldBeExactly 16 + nImage.mono.shouldBeTrue() + nImage.save("fits-mono-subframe").second shouldBe "4d9984e778f82dde10b9aeeee7a29fe0" + } + + @Test + fun monoSharpen() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(Sharpen) + mImage.save("fits-mono-sharpen").second shouldBe "0b162242a4e673f6480b5206cf49ca50" + } + + @Test + fun monoMean() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(Mean) + mImage.save("fits-mono-mean").second shouldBe "cf866292f657c379ae3965931dd8eeea" + } + + @Test + fun monoInvert() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(Invert) + mImage.save("fits-mono-invert").second shouldBe "6e94463bb5b9561de1f0ee0a154db53e" + } + + @Test + fun monoEmboss() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(Emboss) + mImage.save("fits-mono-emboss").second shouldBe "94a8ef5e4573e392d087cf10c905ba12" + } + + @Test + fun monoEdges() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(Edges) + mImage.save("fits-mono-edges").second shouldBe "27ccd5f5e6098d0cae27e7495e18dd72" + } + + @Test + fun monoBlur() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(Blur) + mImage.save("fits-mono-blur").second shouldBe "f2c5466dccf71b5c4bee86c5fbbb95fc" + } + + @Test + fun monoGaussianBlur() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(GaussianBlur(sigma = 5.0, size = 9)) + mImage.save("fits-mono-gaussian-blur").second shouldBe "69057b0c4461fb0d55b779da9e72fd69" + } + + @Test + fun monoStfMidtone01Shadow00Highlight10() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.1f)) + mImage.save("fits-mono-stf-01-00-10").second shouldBe "22c0bd985e70a01330722d912869d6ee" + } + + @Test + fun monoStfMidtone09Shadow00Highlight10() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.9f)) + mImage.save("fits-mono-stf-09-00-10").second shouldBe "553ccb7546dce3a8f742d5e8f7c58a3f" + } + + @Test + fun monoStfMidtone01Shadow05Highlight10() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.1f, shadow = 0.5f)) + mImage.save("fits-mono-stf-01-05-10").second shouldBe "f31db854fab72033dce2f8c572ec6783" + } + + @Test + fun monoStfMidtone09Shadow05Highlight10() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.9f, shadow = 0.5f)) + mImage.save("fits-mono-stf-09-05-10").second shouldBe "633b49c4a1dbb5ad8e6a9d74f330636d" + } + + @Test + fun monoStfMidtone01Shadow00Highlight05() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.1f, highlight = 0.5f)) + mImage.save("fits-mono-stf-01-00-05").second shouldBe "26036937eb3e5f99cd6129f709ce4b31" + } + + @Test + fun monoStfMidtone09Shadow00Highlight05() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.9f, highlight = 0.5f)) + mImage.save("fits-mono-stf-09-00-05").second shouldBe "e8f694dae666ac15ce2f8a169eb84024" + } + + @Test + fun monoStfMidtone01Shadow04Highlight06() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.1f, 0.4f, 0.6f)) + mImage.save("fits-mono-stf-01-04-06").second shouldBe "5226aba21669a24f985703b3e7220568" + } + + @Test + fun monoStfMidtone09Shadow04Highlight06() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.9f, 0.4f, 0.6f)) + mImage.save("fits-mono-stf-09-04-06").second shouldBe "c2acb25ef7be92a51f63e673ec9a850f" + } + + @Test + fun monoAutoStf() { + val mImage = NGC3344_MONO_8_FITS.fits().asImage() + mImage.transform(AutoScreenTransformFunction) + mImage.save("fits-mono-auto-stf").second shouldBe "e17cfc29c3b343409cd8617b6913330e" + } + + @Test + fun colorRaw() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.save("fits-color-raw").second shouldBe "18fb83e240bc7a4cbafbc1aba2741db6" + } + + @Test + fun colorVerticalFlip() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(VerticalFlip) + mImage.save("fits-color-vertical-flip").second shouldBe "b717ecda5c5bba50cfa06304ef2bca88" + } + + @Test + fun colorHorizontalFlip() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(HorizontalFlip) + mImage.save("fits-color-horizontal-flip").second shouldBe "f70228600c77551473008ed4b9986439" + } + + @Test + fun colorVerticalAndHorizontalFlip() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(VerticalFlip, HorizontalFlip) + mImage.save("fits-color-vertical-horizontal-flip").second shouldBe "1237314044f20307b76203148af855e3" + } + + @Test + fun colorSubframe() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + val nImage = mImage.transform(SubFrame(45, 70, 16, 16)) + nImage.width shouldBeExactly 16 + nImage.height shouldBeExactly 16 + nImage.mono.shouldBeFalse() + nImage.save("fits-color-subframe").second shouldBe "282fc4fdf9142fcb4b18e1df1eef4caa" + } + + @Test + fun colorSharpen() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(Sharpen) + mImage.save("fits-color-sharpen").second shouldBe "e562282bdafdeba6ce88981bb9c3ba61" + } + + @Test + fun colorMean() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(Mean) + mImage.save("fits-color-mean").second shouldBe "a8380d928aaa756e202ba43bd3a2f207" + } + + @Test + fun colorInvert() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(Invert) + mImage.save("fits-color-invert").second shouldBe "decad269ec26450aebeaf7546867b5f8" + } + + @Test + fun colorEmboss() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(Emboss) + mImage.save("fits-color-emboss").second shouldBe "58d69250f1233055aa33f9ec7ca40af1" + } + + @Test + fun colorEdges() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(Edges) + mImage.save("fits-color-edges").second shouldBe "091f2955740a8edcd2401dc416d19d51" + } + + @Test + fun colorBlur() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(Blur) + mImage.save("fits-color-blur").second shouldBe "0fca440b763de5380fa29de736f3c792" + } + + @Test + fun colorGaussianBlur() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(GaussianBlur(sigma = 5.0, size = 9)) + mImage.save("fits-color-gaussian-blur").second shouldBe "394d1a4f136f15c802dd73004c421d64" + } + + @Test + fun colorStfMidtone01Shadow00Highlight10() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.1f)) + mImage.save("fits-color-stf-01-00-10").second shouldBe "e952bd263df6fd275b9a80aca554cb4b" + } + + @Test + fun colorStfMidtone09Shadow00Highlight10() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.9f)) + mImage.save("fits-color-stf-09-00-10").second shouldBe "038809d7612018e2e5c19d5e1f551abd" + } + + @Test + fun colorStfMidtone01Shadow05Highlight10() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.1f, shadow = 0.5f)) + mImage.save("fits-color-stf-01-05-10").second shouldBe "70e812260f56f8621002327575611f31" + } + + @Test + fun colorStfMidtone09Shadow05Highlight10() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.9f, shadow = 0.5f)) + mImage.save("fits-color-stf-09-05-10").second shouldBe "6ca400f617f466a9eb02a3a6f2985d99" + } + + @Test + fun colorStfMidtone01Shadow00Highlight05() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.1f, highlight = 0.5f)) + mImage.save("fits-color-stf-01-00-05").second shouldBe "3cd98ee9a8949d5100295acccd77010b" + } + + @Test + fun colorStfMidtone09Shadow00Highlight05() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.9f, highlight = 0.5f)) + mImage.save("fits-color-stf-09-00-05").second shouldBe "2cfeffc88c893cc5883d8a2221f29b91" + } + + @Test + fun colorStfMidtone01Shadow04Highlight06() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.1f, 0.4f, 0.6f)) + mImage.save("fits-color-stf-01-04-06").second shouldBe "532a07a1a166eb007c2e40651aec2097" + } + + @Test + fun colorStfMidtone09Shadow04Highlight06() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(ScreenTransformFunction(0.9f, 0.4f, 0.6f)) + mImage.save("fits-color-stf-09-04-06").second shouldBe "eb3d940d9fd2c8814e930715e89897c4" + } + + @Test + fun colorAutoStf() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(AutoScreenTransformFunction) + mImage.save("fits-color-auto-stf").second shouldBe "a9c3657d8597b927607eb438e666d3a0" + } + + @Test + fun colorScnrMaximumMask() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(SubtractiveChromaticNoiseReduction(ImageChannel.RED, 1f, ProtectionMethod.MAXIMUM_MASK)) + mImage.save("fits-color-scnr-maximum-mask").second shouldBe "e7d2155e18ff1e3172f4e849ae983145" + } + + @Test + fun colorScnrAdditiveMask() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(SubtractiveChromaticNoiseReduction(ImageChannel.RED, 1f, ProtectionMethod.ADDITIVE_MASK)) + mImage.save("fits-color-scnr-additive-mask").second shouldBe "a458c44cedcda704de16d80053fd87eb" + } + + @Test + fun colorScnrAverageNeutral() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(SubtractiveChromaticNoiseReduction(ImageChannel.RED, 1f, ProtectionMethod.AVERAGE_NEUTRAL)) + mImage.save("fits-color-scnr-average-neutral").second shouldBe "e07345ffc4982a62301c95c76d3efb35" + } + + @Test + fun colorScnrMaximumNeutral() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(SubtractiveChromaticNoiseReduction(ImageChannel.RED, 1f, ProtectionMethod.MAXIMUM_NEUTRAL)) + mImage.save("fits-color-scnr-maximum-neutral").second shouldBe "a1d4b04f57b001ba4a996bab0407fd7e" + } + + @Test + fun colorScnrMinimumNeutral() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + mImage.transform(SubtractiveChromaticNoiseReduction(ImageChannel.RED, 1f, ProtectionMethod.MINIMUM_NEUTRAL)) + mImage.save("fits-color-scnr-minimum-neutral").second shouldBe "8b7be57ff38da9c97b35d7888047c0f9" + } + + @Test + fun colorGrayscaleBt709() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + val nImage = mImage.transform(Grayscale.BT709) + nImage.save("fits-color-grayscale-bt709").second shouldBe "cab675aa35390a2d58cd48555d91054f" + } + + @Test + fun colorGrayscaleRmy() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + val nImage = mImage.transform(Grayscale.RMY) + nImage.save("fits-color-grayscale-rmy").second shouldBe "e113627002a4178d1010a2f6246e325f" + } + + @Test + fun colorGrayscaleY() { + val mImage = NGC3344_COLOR_32_FITS.fits().asImage() + val nImage = mImage.transform(Grayscale.Y) + nImage.save("fits-color-grayscale-y").second shouldBe "24dd4a7e0fa9e4be34c53c924a78a940" + } + + @Test + fun colorDebayer() { + val mImage = DEBAYER_FITS.fits().asImage() + val nImage = mImage.transform(AutoScreenTransformFunction) + nImage.save("fits-color-debayer").second shouldBe "86b5bdd67dfd6bbf5495afae4bf2bc04" + } + + @Test + fun colorNoDebayer() { + val mImage = DEBAYER_FITS.fits().asImage(false) + val nImage = mImage.transform(AutoScreenTransformFunction) + nImage.save("fits-color-no-debayer").second shouldBe "958ccea020deec1f0c075042a9ba37c3" } } diff --git a/nebulosa-platesolver/src/main/kotlin/nebulosa/platesolver/PlateSolution.kt b/nebulosa-platesolver/src/main/kotlin/nebulosa/platesolver/PlateSolution.kt index 97404a9ae..cdf0f583f 100644 --- a/nebulosa-platesolver/src/main/kotlin/nebulosa/platesolver/PlateSolution.kt +++ b/nebulosa-platesolver/src/main/kotlin/nebulosa/platesolver/PlateSolution.kt @@ -46,7 +46,7 @@ data class PlateSolution( val height = header.getIntOrNull(FitsKeyword.NAXIS2) ?: header.getInt("IMAGEH", 0) LOG.debug { - "solution from %s: ORIE=%f, SCALE=%f, RA=%s, DEC=%s".format( + "solution from %s: ORIE=%s, SCALE=%f, RA=%s, DEC=%s".format( header, crota2.formatSignedDMS(), cdelt2.toArcsec, crval1.formatHMS(), crval2.formatSignedDMS(), ) } From 04784eadc3d495a25f5ed1c19766aaf53d40cf5f Mon Sep 17 00:00:00 2001 From: tiagohm Date: Tue, 6 Aug 2024 17:37:38 -0300 Subject: [PATCH 092/104] [api][desktop]: Refactor Sky Atlas --- .../kotlin/nebulosa/api/atlas/MinorPlanet.kt | 6 +- .../api/beans/annotations/Subscriber.kt | 1 - .../api/beans/converters/angle/AngleParam.kt | 1 - .../converters/device/DeviceOrEntityParam.kt | 1 - .../converters/location/LocationParam.kt | 1 - .../beans/converters/time/DateAndTimeParam.kt | 3 +- ...mageAnnotatation.kt => ImageAnnotation.kt} | 2 +- .../kotlin/nebulosa/api/image/ImageService.kt | 14 +- desktop/package-lock.json | 10 - desktop/package.json | 1 - desktop/src/app/app.module.ts | 4 +- desktop/src/app/atlas/atlas.component.html | 196 +++-- desktop/src/app/atlas/atlas.component.ts | 633 +++++++--------- desktop/src/app/image/image.component.html | 2 +- desktop/src/app/mount/mount.component.ts | 4 +- .../src/app/settings/settings.component.html | 8 +- .../src/app/settings/settings.component.ts | 25 +- .../location/location.dialog.html | 0 .../location/location.dialog.ts | 4 +- .../menu-item/menu-item.component.ts | 2 +- .../components/moon/moon.component.html | 3 +- .../shared/components/moon/moon.component.ts | 27 +- .../interceptors/location.interceptor.ts | 26 +- .../src/shared/pipes/dropdown-options.pipe.ts | 14 +- .../src/shared/pipes/enum-dropdown.pipe.ts | 4 +- desktop/src/shared/services/api.service.ts | 78 +- .../src/shared/services/electron.service.ts | 4 + .../src/shared/services/preference.service.ts | 4 +- desktop/src/shared/types/angular.types.ts | 26 + desktop/src/shared/types/api.types.ts | 4 +- desktop/src/shared/types/app.types.ts | 47 +- desktop/src/shared/types/atlas.types.ts | 692 +++++++++++++----- desktop/src/shared/types/settings.types.ts | 9 +- .../src/main/kotlin/nebulosa/math/Unsafe.kt | 2 +- .../nebulosa/retrofit/RawAsByteArray.kt | 1 - .../kotlin/nebulosa/retrofit/RawAsString.kt | 1 - .../main/kotlin/nebulosa/test/LinuxOnly.kt | 3 +- .../kotlin/nebulosa/test/NonGitHubOnly.kt | 1 - .../main/kotlin/nebulosa/test/WindowsOnly.kt | 3 +- 39 files changed, 1041 insertions(+), 826 deletions(-) rename api/src/main/kotlin/nebulosa/api/image/{ImageAnnotatation.kt => ImageAnnotation.kt} (98%) rename desktop/src/shared/{dialogs => components}/location/location.dialog.html (100%) rename desktop/src/shared/{dialogs => components}/location/location.dialog.ts (88%) diff --git a/api/src/main/kotlin/nebulosa/api/atlas/MinorPlanet.kt b/api/src/main/kotlin/nebulosa/api/atlas/MinorPlanet.kt index 5d13a502a..1cdfcf562 100644 --- a/api/src/main/kotlin/nebulosa/api/atlas/MinorPlanet.kt +++ b/api/src/main/kotlin/nebulosa/api/atlas/MinorPlanet.kt @@ -11,7 +11,7 @@ data class MinorPlanet( @JvmField val neo: Boolean = false, @JvmField val orbitType: String = "", @JvmField val parameters: List = emptyList(), - @JvmField val searchItems: List = emptyList(), + @JvmField val list: List = emptyList(), ) { data class OrbitalPhysicalParameter( @@ -60,8 +60,8 @@ data class MinorPlanet( body.body!!.pha, body.body!!.neo, body.body?.type?.name ?: "", items, ) } else if (body.list != null) { - val searchItems = body.list!!.map { SearchItem(it.name, it.pdes) } - return MinorPlanet(searchItems = searchItems) + val list = body.list!!.map { SearchItem(it.name, it.pdes) } + return MinorPlanet(list = list) } else { return EMPTY } diff --git a/api/src/main/kotlin/nebulosa/api/beans/annotations/Subscriber.kt b/api/src/main/kotlin/nebulosa/api/beans/annotations/Subscriber.kt index f49f4c467..d9bfee611 100644 --- a/api/src/main/kotlin/nebulosa/api/beans/annotations/Subscriber.kt +++ b/api/src/main/kotlin/nebulosa/api/beans/annotations/Subscriber.kt @@ -2,7 +2,6 @@ package nebulosa.api.beans.annotations import org.springframework.context.annotation.Lazy -@Retention @Lazy(false) @Target(AnnotationTarget.CLASS) annotation class Subscriber diff --git a/api/src/main/kotlin/nebulosa/api/beans/converters/angle/AngleParam.kt b/api/src/main/kotlin/nebulosa/api/beans/converters/angle/AngleParam.kt index 147d173a6..f89ae63fd 100644 --- a/api/src/main/kotlin/nebulosa/api/beans/converters/angle/AngleParam.kt +++ b/api/src/main/kotlin/nebulosa/api/beans/converters/angle/AngleParam.kt @@ -1,6 +1,5 @@ package nebulosa.api.beans.converters.angle -@Retention @Target(AnnotationTarget.VALUE_PARAMETER) annotation class AngleParam( val name: String = "", diff --git a/api/src/main/kotlin/nebulosa/api/beans/converters/device/DeviceOrEntityParam.kt b/api/src/main/kotlin/nebulosa/api/beans/converters/device/DeviceOrEntityParam.kt index 0d7e2970b..e02e8eebf 100644 --- a/api/src/main/kotlin/nebulosa/api/beans/converters/device/DeviceOrEntityParam.kt +++ b/api/src/main/kotlin/nebulosa/api/beans/converters/device/DeviceOrEntityParam.kt @@ -1,7 +1,6 @@ package nebulosa.api.beans.converters.device @Target(AnnotationTarget.VALUE_PARAMETER) -@Retention(AnnotationRetention.RUNTIME) annotation class DeviceOrEntityParam( val name: String = "", val defaultValue: String = "" diff --git a/api/src/main/kotlin/nebulosa/api/beans/converters/location/LocationParam.kt b/api/src/main/kotlin/nebulosa/api/beans/converters/location/LocationParam.kt index e2c1a1bf5..311e3db3e 100644 --- a/api/src/main/kotlin/nebulosa/api/beans/converters/location/LocationParam.kt +++ b/api/src/main/kotlin/nebulosa/api/beans/converters/location/LocationParam.kt @@ -1,5 +1,4 @@ package nebulosa.api.beans.converters.location -@Retention @Target(AnnotationTarget.VALUE_PARAMETER) annotation class LocationParam diff --git a/api/src/main/kotlin/nebulosa/api/beans/converters/time/DateAndTimeParam.kt b/api/src/main/kotlin/nebulosa/api/beans/converters/time/DateAndTimeParam.kt index cdcc85c38..e41fad45d 100644 --- a/api/src/main/kotlin/nebulosa/api/beans/converters/time/DateAndTimeParam.kt +++ b/api/src/main/kotlin/nebulosa/api/beans/converters/time/DateAndTimeParam.kt @@ -1,10 +1,9 @@ package nebulosa.api.beans.converters.time -@Retention @Target(AnnotationTarget.VALUE_PARAMETER) annotation class DateAndTimeParam( val datePattern: String = "yyyy-MM-dd", - val timePattern: String = "HH:mm", + val timePattern: String = "HH:mm:ss", val noSeconds: Boolean = true, val nullable: Boolean = false, ) diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageAnnotatation.kt b/api/src/main/kotlin/nebulosa/api/image/ImageAnnotation.kt similarity index 98% rename from api/src/main/kotlin/nebulosa/api/image/ImageAnnotatation.kt rename to api/src/main/kotlin/nebulosa/api/image/ImageAnnotation.kt index e6365e937..1db713fd5 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageAnnotatation.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageAnnotation.kt @@ -12,7 +12,7 @@ import nebulosa.skycatalog.DeepSkyObject import nebulosa.skycatalog.SkyObject import nebulosa.skycatalog.SkyObjectType -data class ImageAnnotatation( +data class ImageAnnotation( override val x: Double, override val y: Double, @JvmField val star: StarDSO? = null, diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageService.kt b/api/src/main/kotlin/nebulosa/api/image/ImageService.kt index ea7704882..ee4dc029f 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageService.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageService.kt @@ -7,7 +7,7 @@ import nebulosa.api.atlas.SimbadEntityRepository import nebulosa.api.calibration.CalibrationFrameService import nebulosa.api.connection.ConnectionService import nebulosa.api.framing.FramingService -import nebulosa.api.image.ImageAnnotatation.StarDSO +import nebulosa.api.image.ImageAnnotation.StarDSO import nebulosa.fits.* import nebulosa.image.Image import nebulosa.image.algorithms.computation.Histogram @@ -173,7 +173,7 @@ class ImageService( } @Synchronized - fun annotations(path: Path, request: AnnotateImageRequest, location: Location? = null): List { + fun annotations(path: Path, request: AnnotateImageRequest, location: Location? = null): List { val (image, calibration) = imageBucket.open(path) if (image == null || calibration.isNullOrEmpty() || !calibration.solved) { @@ -187,7 +187,7 @@ class ImageService( return emptyList() } - val annotations = Vector(64) + val annotations = Vector(64) val tasks = ArrayList>(2) val dateTime = image.header.observationDate ?: LocalDateTime.now() @@ -219,8 +219,8 @@ class ImageService( val declination = it[2].deg.takeIf(Angle::isFinite) ?: return@forEach val (x, y) = wcs.skyToPix(rightAscension, declination) val magnitude = it[6].replace(INVALID_MAG_CHARS, "").toDoubleOrNull() ?: SkyObject.UNKNOWN_MAGNITUDE - val minorPlanet = ImageAnnotatation.MinorPlanet(0L, it[0], rightAscension, declination, magnitude) - val annotation = ImageAnnotatation(x, y, minorPlanet = minorPlanet) + val minorPlanet = ImageAnnotation.MinorPlanet(0L, it[0], rightAscension, declination, magnitude) + val annotation = ImageAnnotation(x, y, minorPlanet = minorPlanet) annotations.add(annotation) count++ } @@ -254,8 +254,8 @@ class ImageService( val astrometric = barycentric.observe(entry).equatorial() val (x, y) = wcs.skyToPix(astrometric.longitude.normalized, astrometric.latitude) - val annotation = if (entry.type.classification == ClassificationType.STAR) ImageAnnotatation(x, y, star = StarDSO(entry)) - else ImageAnnotatation(x, y, dso = StarDSO(entry)) + val annotation = if (entry.type.classification == ClassificationType.STAR) ImageAnnotation(x, y, star = StarDSO(entry)) + else ImageAnnotation(x, y, dso = StarDSO(entry)) annotations.add(annotation) count++ } diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 181e67c23..118e713cc 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -24,7 +24,6 @@ "chartjs-plugin-zoom": "2.0.1", "hotkeys-js": "3.13.7", "leaflet": "1.9.4", - "moment": "2.30.1", "ngx-moveable": "0.50.0", "nuid": "2.0.1-2", "panzoom": "9.4.3", @@ -14515,15 +14514,6 @@ "node": ">=10" } }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/moveable": { "version": "0.53.0", "resolved": "https://registry.npmjs.org/moveable/-/moveable-0.53.0.tgz", diff --git a/desktop/package.json b/desktop/package.json index e6e43e6e4..789d2b5f3 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -49,7 +49,6 @@ "chartjs-plugin-zoom": "2.0.1", "hotkeys-js": "3.13.7", "leaflet": "1.9.4", - "moment": "2.30.1", "ngx-moveable": "0.50.0", "nuid": "2.0.1-2", "panzoom": "9.4.3", diff --git a/desktop/src/app/app.module.ts b/desktop/src/app/app.module.ts index 46138ff7b..d816d784b 100644 --- a/desktop/src/app/app.module.ts +++ b/desktop/src/app/app.module.ts @@ -49,6 +49,7 @@ import { DeviceChooserComponent } from '../shared/components/device-chooser/devi import { DeviceListMenuComponent } from '../shared/components/device-list-menu/device-list-menu.component' import { DialogMenuComponent } from '../shared/components/dialog-menu/dialog-menu.component' import { HistogramComponent } from '../shared/components/histogram/histogram.component' +import { LocationComponent } from '../shared/components/location/location.dialog' import { MapComponent } from '../shared/components/map/map.component' import { MenuBarComponent } from '../shared/components/menu-bar/menu-bar.component' import { MenuItemComponent } from '../shared/components/menu-item/menu-item.component' @@ -56,7 +57,6 @@ import { MoonComponent } from '../shared/components/moon/moon.component' import { PathChooserComponent } from '../shared/components/path-chooser/path-chooser.component' import { SlideMenuComponent } from '../shared/components/slide-menu/slide-menu.component' import { ConfirmDialog } from '../shared/dialogs/confirm/confirm.dialog' -import { LocationDialog } from '../shared/dialogs/location/location.dialog' import { NoDropdownDirective } from '../shared/directives/no-dropdown.directive' import { SpinnableNumberDirective } from '../shared/directives/spinnable-number.directive' import { StopPropagationDirective } from '../shared/directives/stop-propagation.directive' @@ -135,7 +135,7 @@ import { StackerComponent } from './stacker/stacker.component' SpinnableNumberDirective, INDIComponent, INDIPropertyComponent, - LocationDialog, + LocationComponent, MapComponent, MenuBarComponent, MenuItemComponent, diff --git a/desktop/src/app/atlas/atlas.component.html b/desktop/src/app/atlas/atlas.component.html index ae52a34f4..840e598a0 100644 --- a/desktop/src/app/atlas/atlas.component.html +++ b/desktop/src/app/atlas/atlas.component.html @@ -17,12 +17,14 @@
+ [class.invisible]="!sun.image" + style="height: 225px"> + [src]="sun.image" + style="width: 223px" /> SDO/HMI @@ -43,12 +45,12 @@
+ style="height: 225px"> + [width]="200" + [height]="200" + [illuminationRatio]="moon.position.illuminated / 100" + [waning]="moon.position.leading" />
- +
@@ -109,13 +111,13 @@
@@ -168,7 +170,7 @@ [step]="1" [showButtons]="true" inputStyleClass="p-inputtext-sm border-0 w-full" - [(ngModel)]="closeApproachDays" + [(ngModel)]="minorPlanet.closeApproach.days" spinnableNumber /> @@ -181,13 +183,13 @@ [showButtons]="true" inputStyleClass="p-inputtext-sm border-0 w-full" locale="en" - [(ngModel)]="closeApproachDistance" + [(ngModel)]="minorPlanet.closeApproach.lunarDistance" spinnableNumber />
@@ -263,7 +265,7 @@ + [(ngModel)]="skyObject.search.filter.text" />
@@ -278,7 +280,7 @@ tooltipPosition="bottom" />
+ [(ngModel)]="satellite.search.filter.text" />
@@ -376,7 +378,7 @@ tooltipPosition="bottom" />
+ [value]="position.rightAscensionJ2000" />
@@ -463,7 +465,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="bodyPosition.declinationJ2000" /> + [value]="position.declinationJ2000" />
@@ -473,7 +475,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="bodyPosition.rightAscension" /> + [value]="position.rightAscension" />
@@ -483,7 +485,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="bodyPosition.declination" /> + [value]="position.declination" />
@@ -493,7 +495,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="bodyPosition.azimuth" /> + [value]="position.azimuth" />
@@ -503,7 +505,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="bodyPosition.altitude" /> + [value]="position.altitude" />
@@ -513,7 +515,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="bodyPosition.magnitude < 30 ? bodyPosition.magnitude.toFixed(2) : '-'" /> + [value]="position.magnitude < 30 ? position.magnitude.toFixed(2) : '-'" />
@@ -523,7 +525,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="bodyPosition.constellation" /> + [value]="position.constellation" />
@@ -533,8 +535,8 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="bodyPosition.distance.toFixed(3)" /> - + [value]="position.distance.toFixed(3)" /> +
@@ -543,7 +545,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="bodyPosition.illuminated.toFixed(3)" /> + [value]="position.illuminated.toFixed(3)" />
@@ -553,7 +555,7 @@ pInputText readonly class="p-inputtext-sm border-0 w-full" - [value]="bodyPosition.elongation.toFixed(3)" /> + [value]="position.elongation.toFixed(3)" />
@@ -573,7 +575,7 @@
- {{ name ?? '' }} + {{ body.name }}
@@ -643,12 +645,12 @@
-
+
+ [value]="skyObject.search.filter.rightAscension" />
@@ -679,9 +679,9 @@ + [value]="skyObject.search.filter.declination" />
@@ -696,16 +696,17 @@ [showButtons]="true" inputStyleClass="p-inputtext-sm border-0 w-full" locale="en" - [(ngModel)]="skyObjectFilter.radius" + [(ngModel)]="skyObject.search.filter.radius" spinnableNumber />
+ @let constellations = ['ALL'].concat('CONSTELLATION' | dropdownOptions);
+ @let skyObjectTypes = ['ALL'].concat('SKY_OBJECT_TYPE' | dropdownOptions); @@ -756,7 +758,7 @@ [showButtons]="true" inputStyleClass="p-inputtext-sm border-0 w-full" locale="en" - [(ngModel)]="skyObjectFilter.magnitude[1]" + [(ngModel)]="skyObject.search.filter.magnitude[1]" spinnableNumber /> @@ -769,26 +771,28 @@ icon="mdi mdi-filter" label="Filter" size="small" - (onClick)="filterSkyObject()" /> + (onClick)="searchSkyObject()" />
- + @let groups = 'SATELLITE_GROUP_TYPE' | dropdownOptions; + + @for (group of groups; track $index) { - + }
@@ -799,33 +803,14 @@ icon="mdi mdi-restore" label="Reset" size="small" - (onClick)="resetSatelliteFilter()" /> + (onClick)="resetSatelliteSearchGroups()" /> - -
- - -
-
-
- - + (onClick)="searchSatellite()" />
@@ -837,8 +822,8 @@
Date Time + [(ngModel)]="dateTimeAndLocation.manual" + (ngModelChange)="manualDateTimeChanged()" />
@@ -889,7 +874,8 @@ + [header]="body.name" /> diff --git a/desktop/src/app/atlas/atlas.component.ts b/desktop/src/app/atlas/atlas.component.ts index 982eeb03c..cdcbe3554 100644 --- a/desktop/src/app/atlas/atlas.component.ts +++ b/desktop/src/app/atlas/atlas.component.ts @@ -1,12 +1,11 @@ -import { AfterContentInit, AfterViewInit, Component, ElementRef, HostListener, NgZone, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core' +import { AfterContentInit, AfterViewInit, Component, HostListener, NgZone, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core' import { ActivatedRoute } from '@angular/router' import { Chart, ChartData, ChartOptions } from 'chart.js' import zoomPlugin from 'chartjs-plugin-zoom' -import moment from 'moment' import { UIChart } from 'primeng/chart' import { ListboxChangeEvent } from 'primeng/listbox' import { OverlayPanel } from 'primeng/overlaypanel' -import { Subscription, timer } from 'rxjs' +import { timer } from 'rxjs' import { DeviceListMenuComponent } from '../../shared/components/device-list-menu/device-list-menu.component' import { SlideMenuItem } from '../../shared/components/menu-item/menu-item.component' import { ONE_DECIMAL_PLACE_FORMATTER, TWO_DIGITS_FORMATTER } from '../../shared/constants' @@ -16,24 +15,27 @@ import { BrowserWindowService } from '../../shared/services/browser-window.servi import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' import { PrimeService } from '../../shared/services/prime.service' +import { extractDate, extractTime } from '../../shared/types/angular.types' import { - CONSTELLATIONS, - CloseApproach, - Constellation, - DEFAULT_BODY_POSITION, + AltitudeDataPoint, + BodyTabType, + BodyTag, + DEFAULT_BODY_TAB_REFRESH, + DEFAULT_DATE_TIME_AND_LOCATION, DEFAULT_LOCATION, - DEFAULT_SEARCH_FILTER, - DeepSkyObject, + DEFAULT_MINOR_PLANET, + DEFAULT_MOON, + DEFAULT_PLANET, + DEFAULT_SATELLITE, + DEFAULT_SKY_ATLAS_PREFERENCE, + DEFAULT_SKY_OBJECT, + DEFAULT_SUN, Location, - MinorPlanet, - MinorPlanetSearchItem, - PlanetTableItem, + MinorPlanetListItem, SATELLITE_GROUPS, - Satellite, - SatelliteGroupType, - SettingsDialog, SkyAtlasInput, - SkyAtlasTab, + resetSatelliteSearchGroup, + searchFilterWithDefault, } from '../../shared/types/atlas.types' import { Mount } from '../../shared/types/mount.types' import { AppComponent } from '../app.component' @@ -45,106 +47,20 @@ import { AppComponent } from '../app.component' encapsulation: ViewEncapsulation.None, }) export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, OnDestroy { - refreshingPosition = false - refreshingChart = false - tab = SkyAtlasTab.SUN - - // TODO: juntar locations e dateTime num objeto + protected readonly sun = structuredClone(DEFAULT_SUN) + protected readonly moon = structuredClone(DEFAULT_MOON) + protected readonly planet = structuredClone(DEFAULT_PLANET) + protected readonly minorPlanet = structuredClone(DEFAULT_MINOR_PLANET) + protected readonly skyObject = structuredClone(DEFAULT_SKY_OBJECT) + protected readonly satellite = structuredClone(DEFAULT_SATELLITE) + protected readonly preference = structuredClone(DEFAULT_SKY_ATLAS_PREFERENCE) + protected readonly refresh = structuredClone(DEFAULT_BODY_TAB_REFRESH) + protected readonly dateTimeAndLocation = structuredClone(DEFAULT_DATE_TIME_AND_LOCATION) + + protected tab = BodyTabType.SUN protected locations: Location[] = [structuredClone(DEFAULT_LOCATION)] - // TODO: location fica em Atlas preference - protected location = this.locations[0] - - get refreshing() { - return this.refreshingPosition || this.refreshingChart - } - - readonly bodyPosition = structuredClone(DEFAULT_BODY_POSITION) - moonIlluminated = 1 - moonWaning = false - - useManualDateTime = false - dateTime = new Date() - dateTimeHour = this.dateTime.getHours() - dateTimeMinute = this.dateTime.getMinutes() - - planet?: PlanetTableItem - readonly planets: PlanetTableItem[] = [ - { name: 'Mercury', type: 'Planet', code: '199' }, - { name: 'Venus', type: 'Planet', code: '299' }, - { name: 'Mars', type: 'Planet', code: '499' }, - { name: 'Jupiter', type: 'Planet', code: '599' }, - { name: 'Saturn', type: 'Planet', code: '699' }, - { name: 'Uranus', type: 'Planet', code: '799' }, - { name: 'Neptune', type: 'Planet', code: '899' }, - { name: 'Pluto', type: 'Dwarf Planet', code: '999' }, - { name: 'Phobos', type: `Mars' Satellite`, code: '401' }, - { name: 'Deimos', type: `Mars' Satellite`, code: '402' }, - { name: 'Io', type: `Jupiter's Satellite`, code: '501' }, - { name: 'Europa', type: `Jupiter's Satellite`, code: '402' }, - { name: 'Ganymede', type: `Jupiter's Satellite`, code: '403' }, - { name: 'Callisto', type: `Jupiter's Satellite`, code: '504' }, - { name: 'Mimas', type: `Saturn's Satellite`, code: '601' }, - { name: 'Enceladus', type: `Saturn's Satellite`, code: '602' }, - { name: 'Tethys', type: `Saturn's Satellite`, code: '603' }, - { name: 'Dione', type: `Saturn's Satellite`, code: '604' }, - { name: 'Rhea', type: `Saturn's Satellite`, code: '605' }, - { name: 'Titan', type: `Saturn's Satellite`, code: '606' }, - { name: 'Hyperion', type: `Saturn's Satellite`, code: '607' }, - { name: 'Iapetus', type: `Saturn's Satellite`, code: '608' }, - { name: 'Ariel', type: `Uranus' Satellite`, code: '701' }, - { name: 'Umbriel', type: `Uranus' Satellite`, code: '702' }, - { name: 'Titania', type: `Uranus' Satellite`, code: '703' }, - { name: 'Oberon', type: `Uranus' Satellite`, code: '704' }, - { name: 'Miranda', type: `Uranus' Satellite`, code: '705' }, - { name: 'Triton', type: `Neptune's Satellite`, code: '801' }, - { name: 'Charon', type: `Pluto's Satellite`, code: '901' }, - { name: '1 Ceres', type: 'Dwarf Planet', code: '1;' }, - { name: '90377 Sedna', type: 'Dwarf Planet', code: '90377;' }, - { name: '136199 Eris', type: 'Dwarf Planet', code: '136199;' }, - { name: '2 Pallas', type: 'Asteroid', code: '2;' }, - { name: '3 Juno', type: 'Asteroid', code: '3;' }, - { name: '4 Vesta', type: 'Asteroid', code: '4;' }, - ] - - minorPlanetTab = 0 - minorPlanet?: MinorPlanet - minorPlanetSearchText = '' - minorPlanetChoiceItems: { name: string; pdes: string }[] = [] - showMinorPlanetChoiceDialog = false - closeApproach?: CloseApproach - closeApproaches: CloseApproach[] = [] - closeApproachDays = 7 - closeApproachDistance = 10 - - skyObject?: DeepSkyObject - skyObjectItems: DeepSkyObject[] = [] - skyObjectSearchText = '' - readonly skyObjectFilter = structuredClone(DEFAULT_SEARCH_FILTER) - showSkyObjectFilter = false - readonly constellationOptions: (Constellation | 'ALL')[] = ['ALL', ...CONSTELLATIONS] - - satellite?: Satellite - satelliteItems: Satellite[] = [] - satelliteSearchText = '' - showSatelliteFilterDialog = false - readonly satelliteSearchGroup = new Map() - - name? = 'Sun' - tags: { title: string; severity: 'success' | 'info' | 'warning' | 'danger' }[] = [] - - @ViewChild('imageOfSun') - private readonly imageOfSun!: ElementRef - - @ViewChild('deviceMenu') - private readonly deviceMenu!: DeviceListMenuComponent - - @ViewChild('dateTimeAndLocationPanel') - private readonly dateTimeAndLocationPanel!: OverlayPanel - @ViewChild('chart') - private readonly chart!: UIChart - - readonly altitudeData: ChartData = { + protected readonly altitudeData: ChartData = { labels: ['12h', '13h', '14h', '15h', '16h', '17h', '18h', '19h', '20h', '21h', '22h', '23h', '0h', '1h', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', '10h', '11h', '12h'], datasets: [ // Day. @@ -267,7 +183,7 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, ], } - readonly altitudeOptions: ChartOptions = { + protected readonly altitudeOptions: ChartOptions = { responsive: true, plugins: { legend: { @@ -376,54 +292,73 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, }, } - private static readonly DEFAULT_SATELLITE_FILTERS: SatelliteGroupType[] = ['AMATEUR', 'BEIDOU', 'GALILEO', 'GLO_OPS', 'GNSS', 'GPS_OPS', 'ONEWEB', 'SCIENCE', 'STARLINK', 'STATIONS', 'VISUAL'] - - readonly ephemerisModel: SlideMenuItem[] = [ + protected readonly ephemerisModel: SlideMenuItem[] = [ { icon: 'mdi mdi-magnify', label: 'Find sky objects around this object', slideMenu: [], command: async () => { - this.skyObjectFilter.rightAscension = this.bodyPosition.rightAscensionJ2000 - this.skyObjectFilter.declination = this.bodyPosition.declinationJ2000 - if (this.skyObjectFilter.radius <= 0) this.skyObjectFilter.radius = 4 + this.skyObject.search.filter.rightAscension = this.position.rightAscensionJ2000 + this.skyObject.search.filter.declination = this.position.declinationJ2000 + if (this.skyObject.search.filter.radius <= 0) this.skyObject.search.filter.radius = 4 - this.tab = SkyAtlasTab.SKY_OBJECT + this.tab = BodyTabType.SKY_OBJECT await this.tabChanged() - await this.filterSkyObject() + await this.searchSkyObject() }, }, ] - private refreshTimer?: Subscription - private refreshTabCount = 0 + @ViewChild('deviceMenu') + private readonly deviceMenu!: DeviceListMenuComponent - readonly settings: SettingsDialog = { - showDialog: false, + @ViewChild('dateTimeAndLocationPanel') + private readonly dateTimeAndLocationPanel!: OverlayPanel + + @ViewChild('chart') + private readonly chart!: UIChart + + get body() { + switch (this.tab) { + case BodyTabType.SUN: + return this.sun + case BodyTabType.MOON: + return this.moon + case BodyTabType.PLANET: + return this.planet + case BodyTabType.MINOR_PLANET: + return this.minorPlanet + case BodyTabType.SKY_OBJECT: + return this.skyObject + case BodyTabType.SATELLITE: + return this.satellite + default: + return this.sun + } + } + + get position() { + return this.body.position + } + + get refreshing() { + return this.refresh.position || this.refresh.chart } constructor( private readonly app: AppComponent, private readonly api: ApiService, - private readonly browserWindow: BrowserWindowService, + private readonly browserWindowService: BrowserWindowService, private readonly route: ActivatedRoute, electron: ElectronService, - private readonly preference: PreferenceService, + private readonly preferenceService: PreferenceService, private readonly skyObjectPipe: SkyObjectPipe, - private readonly prime: PrimeService, + private readonly primeService: PrimeService, ngZone: NgZone, ) { app.title = 'Sky Atlas' - app.topMenu.push({ - icon: 'mdi mdi-cog', - tooltip: 'Settings', - visible: false, - command: () => { - this.settings.showDialog = true - }, - }) app.topMenu.push({ icon: 'mdi mdi-calendar', tooltip: 'Date Time and Location', @@ -432,10 +367,13 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, }, }) - electron.on('LOCATION.CHANGED', async () => { - await ngZone.run(() => { + electron.on('LOCATION.CHANGED', (location) => { + ngZone.run(() => { this.loadLocations() - return this.refreshTab(true, true) + + if (this.dateTimeAndLocation.location.id === location.id) { + void this.refreshTab(true, true) + } }) }) @@ -443,18 +381,13 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, await this.loadTabFromData(event) }) - const settings = this.preference.settings.get() - this.location = settings.locations[settings.location] - // TODO: Refresh graph and twilight if hours past 12 (noon) } - async ngOnInit() { + ngOnInit() { Chart.register(zoomPlugin) this.loadPreference() - const types = await this.api.skyObjectTypes() - this.skyObjectFilter.types = ['ALL', ...types] } ngAfterContentInit() { @@ -468,8 +401,8 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, const now = new Date() const initialDelay = 60 * 1000 - (now.getSeconds() * 1000 + now.getMilliseconds()) - this.refreshTimer = timer(initialDelay, 60 * 1000).subscribe(async () => { - if (!this.useManualDateTime) { + this.refresh.timer = timer(initialDelay, 60 * 1000).subscribe(async () => { + if (!this.dateTimeAndLocation.manual) { await this.refreshTab() } }) @@ -486,277 +419,240 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, @HostListener('window:unload') ngOnDestroy() { - this.refreshTimer?.unsubscribe() + this.refresh.timer?.unsubscribe() } private async loadTabFromData(data?: SkyAtlasInput) { - if (data?.tab) { + if (data && data.tab >= BodyTabType.SUN) { this.tab = data.tab - if (this.tab === SkyAtlasTab.SKY_OBJECT) { - this.skyObjectFilter.rightAscension = data.filter?.rightAscension ?? this.skyObjectFilter.rightAscension - this.skyObjectFilter.declination = data.filter?.declination ?? this.skyObjectFilter.declination - this.skyObjectFilter.radius = (data.filter?.radius ?? this.skyObjectFilter.radius) || 4.0 - this.skyObjectFilter.constellation = data.filter?.constellation ?? this.skyObjectFilter.constellation - this.skyObjectFilter.magnitude = data.filter?.magnitude ?? this.skyObjectFilter.magnitude - this.skyObjectFilter.type = data.filter?.type ?? this.skyObjectFilter.type + if (this.tab === BodyTabType.SKY_OBJECT) { + this.skyObject.search.filter = searchFilterWithDefault(data.filter, this.skyObject.search.filter) await this.tabChanged() - await this.filterSkyObject() + await this.searchSkyObject() } } } - async tabChanged() { - await this.refreshTab(false, true) + protected tabChanged() { + return this.refreshTab(false, true) } - async planetChanged() { - await this.refreshTab(false, true) + protected async planetChanged() { + if (this.planet.selected) { + this.planet.name = this.planet.selected.name + await this.refreshTab(false, true) + } } - async searchMinorPlanet() { - this.refreshingPosition = true + protected async searchMinorPlanet() { + this.refresh.position = true try { - const minorPlanet = await this.api.searchMinorPlanet(this.minorPlanetSearchText) + const minorPlanet = await this.api.searchMinorPlanet(this.minorPlanet.search.text) if (minorPlanet.found) { - this.minorPlanet = minorPlanet + this.minorPlanet.search.result = minorPlanet + this.minorPlanet.name = minorPlanet.name + + const tags: BodyTag[] = [] + // if (minorPlanet.kind) tags.push({ label: minorPlanet.kind, severity: 'success' }) + if (minorPlanet.orbitType) tags.push({ label: minorPlanet.orbitType, severity: 'success' }) + if (minorPlanet.pha) tags.push({ label: 'PHA', severity: 'danger' }) + if (minorPlanet.neo) tags.push({ label: 'NEO', severity: 'warning' }) + this.minorPlanet.tags = tags + await this.refreshTab(false, true) - } else { - this.minorPlanetChoiceItems = minorPlanet.searchItems - this.showMinorPlanetChoiceDialog = true + } else if (minorPlanet.list.length) { + this.minorPlanet.list.items = minorPlanet.list + this.minorPlanet.list.showDialog = true } } finally { - this.refreshingPosition = false + this.refresh.position = false } } - async minorPlanetChoosen(event: ListboxChangeEvent) { - this.minorPlanetSearchText = (event.value as MinorPlanetSearchItem).pdes + protected async minorPlanetSelected(event: ListboxChangeEvent) { + const value = event.value as MinorPlanetListItem + this.minorPlanet.search.text = value.pdes + this.minorPlanet.list.showDialog = false await this.searchMinorPlanet() - this.showMinorPlanetChoiceDialog = false } - async closeApproachesForMinorPlanets() { - this.refreshingPosition = true + protected async closeApproachesOfMinorPlanets() { + this.refresh.position = true try { - this.closeApproaches = await this.api.closeApproachesForMinorPlanets(this.closeApproachDays, this.closeApproachDistance, this.dateTime) + this.minorPlanet.closeApproach.result = await this.api.closeApproachesOfMinorPlanets(this.minorPlanet.closeApproach.days, this.minorPlanet.closeApproach.lunarDistance, this.dateTimeAndLocation.dateTime) - if (!this.closeApproaches.length) { - this.prime.message('No close approaches found for the given days and lunar distance', 'warn') + if (!this.minorPlanet.closeApproach.result.length) { + this.primeService.message('No close approaches found for the given days and lunar distance', 'warn') } } finally { - this.refreshingPosition = false + this.refresh.position = false } } - async closeApproachChanged() { - if (this.closeApproach) { - this.minorPlanetSearchText = this.closeApproach.designation - this.minorPlanetTab = 0 + protected async closeApproachChanged() { + if (this.minorPlanet.closeApproach.selected) { + this.minorPlanet.search.text = this.minorPlanet.closeApproach.selected.designation + this.minorPlanet.tab = 0 await this.searchMinorPlanet() } } - starChanged() { - return this.refreshTab(false, true) - } - - dsoChanged() { - return this.refreshTab(false, true) - } - - skyObjectChanged() { - return this.refreshTab(false, true) - } - - satelliteChanged() { - return this.refreshTab(false, true) + protected async skyObjectChanged() { + if (this.skyObject.search.selected) { + this.skyObject.name = this.skyObjectPipe.transform(this.skyObject.search.selected, 'name') ?? '-' + await this.refreshTab(false, true) + } } - showSkyObjectFilterDialog() { - this.showSkyObjectFilter = true + protected async satelliteChanged() { + if (this.satellite.search.selected) { + this.satellite.name = this.satellite.search.selected.name + await this.refreshTab(false, true) + } } - async searchSkyObject() { - const constellation = this.skyObjectFilter.constellation === 'ALL' ? undefined : this.skyObjectFilter.constellation - const type = this.skyObjectFilter.type === 'ALL' ? undefined : this.skyObjectFilter.type + protected async searchSkyObject() { + const constellation = this.skyObject.search.filter.constellation === 'ALL' ? undefined : this.skyObject.search.filter.constellation + const type = this.skyObject.search.filter.type === 'ALL' ? undefined : this.skyObject.search.filter.type - this.refreshingPosition = true + this.refresh.position = true try { - this.skyObjectItems = await this.api.searchSkyObject(this.skyObjectSearchText, this.skyObjectFilter.rightAscension, this.skyObjectFilter.declination, this.skyObjectFilter.radius, constellation, this.skyObjectFilter.magnitude[0], this.skyObjectFilter.magnitude[1], type) + const { text, rightAscension, declination, radius, magnitude } = this.skyObject.search.filter + this.skyObject.search.result = await this.api.searchSkyObject(text, rightAscension, declination, radius, constellation, magnitude[0], magnitude[1], type) } finally { - this.refreshingPosition = false + this.skyObject.search.showDialog = false + this.refresh.position = false } } - async filterSkyObject() { - await this.searchSkyObject() - this.showSkyObjectFilter = false - } - - async searchSatellite() { - this.refreshingPosition = true + protected async searchSatellite() { + this.refresh.position = true try { - this.savePreference() - const groups = SATELLITE_GROUPS.filter((e) => this.satelliteSearchGroup.get(e)) - this.satelliteItems = await this.api.searchSatellites(this.satelliteSearchText, groups) + const groups = SATELLITE_GROUPS.filter((e) => this.satellite.search.filter.groups[e]) + this.satellite.search.result = await this.api.searchSatellites(this.satellite.search.filter.text, groups) } finally { - this.refreshingPosition = false + this.satellite.search.showDialog = false + this.refresh.position = false } } - resetSatelliteFilter() { - for (const group of SATELLITE_GROUPS) { - const enabled = AtlasComponent.DEFAULT_SATELLITE_FILTERS.includes(group) - this.satelliteSearchGroup.set(group, enabled) - } - + protected resetSatelliteSearchGroups() { + resetSatelliteSearchGroup(this.satellite.search.filter.groups) this.savePreference() } - async filterSatellite() { - await this.searchSatellite() - this.showSatelliteFilterDialog = false - } - - async dateTimeChanged(dateChanged: boolean) { + protected async dateTimeChanged(dateChanged: boolean) { + this.savePreference() await this.refreshTab(dateChanged, true) } - async useManualDateTimeChanged() { - if (!this.useManualDateTime) { + protected async manualDateTimeChanged() { + this.savePreference() + + if (!this.dateTimeAndLocation.manual) { await this.refreshTab(true, true) } } - mountGoTo() { + protected locationChanged() { + this.savePreference() + return this.refreshTab(true, true) + } + + protected mountGoTo() { return this.executeMount((mount) => { - return this.api.mountGoTo(mount, this.bodyPosition.rightAscension, this.bodyPosition.declination, false) + return this.api.mountGoTo(mount, this.position.rightAscension, this.position.declination, false) }) } - mountSlew() { + protected mountSlew() { return this.executeMount((mount) => { - return this.api.mountSlew(mount, this.bodyPosition.rightAscension, this.bodyPosition.declination, false) + return this.api.mountSlew(mount, this.position.rightAscension, this.position.declination, false) }) } - mountSync() { + protected mountSync() { return this.executeMount((mount) => { - return this.api.mountSync(mount, this.bodyPosition.rightAscension, this.bodyPosition.declination, false) + return this.api.mountSync(mount, this.position.rightAscension, this.position.declination, false) }) } - frame() { - return this.browserWindow.openFraming({ - rightAscension: this.bodyPosition.rightAscensionJ2000, - declination: this.bodyPosition.declinationJ2000, + protected frame() { + return this.browserWindowService.openFraming({ + rightAscension: this.position.rightAscensionJ2000, + declination: this.position.declinationJ2000, }) } - async refreshTab(refreshTwilight: boolean = false, refreshChart: boolean = false) { - this.refreshingPosition = true - this.refreshTabCount++ + private async refreshTab(refreshTwilight: boolean = false, refreshChart: boolean = false) { + this.refresh.position = true + this.refresh.count++ - if (!this.useManualDateTime) { - this.dateTime = new Date() - this.dateTimeHour = this.dateTime.getHours() - this.dateTimeMinute = this.dateTime.getMinutes() - } else { - this.dateTime.setHours(this.dateTimeHour) - this.dateTime.setMinutes(this.dateTimeMinute) + if (!this.dateTimeAndLocation.manual) { + this.dateTimeAndLocation.dateTime = new Date() } - this.app.subTitle = `${this.location.name} ยท ${moment(this.dateTime).format('YYYY-MM-DD HH:mm')}` + const { dateTime, location } = this.dateTimeAndLocation + + this.app.subTitle = `${location.name} ยท ${extractDate(dateTime)} ${extractTime(dateTime, false)}` try { // Sun. - if (this.tab === SkyAtlasTab.SUN) { - this.name = 'Sun' - this.tags = [] - this.imageOfSun.nativeElement.src = `${this.api.baseUrl}/sky-atlas/sun/image` - const bodyPosition = await this.api.positionOfSun(this.dateTime) - Object.assign(this.bodyPosition, bodyPosition) + if (this.tab === BodyTabType.SUN) { + this.sun.image = `${this.api.baseUrl}/sky-atlas/sun/image` + const position = await this.api.positionOfSun(dateTime, location) + Object.assign(this.sun.position, position) } // Moon. - else if (this.tab === SkyAtlasTab.MOON) { - this.name = 'Moon' - this.tags = [] - const bodyPosition = await this.api.positionOfMoon(this.dateTime) - Object.assign(this.bodyPosition, bodyPosition) - this.moonIlluminated = this.bodyPosition.illuminated / 100.0 - this.moonWaning = this.bodyPosition.leading + else if (this.tab === BodyTabType.MOON) { + const position = await this.api.positionOfMoon(dateTime, location) + Object.assign(this.moon.position, position) } // Planet. - else if (this.tab === SkyAtlasTab.PLANET) { - this.tags = [] - - if (this.planet) { - this.name = this.planet.name - const bodyPosition = await this.api.positionOfPlanet(this.planet.code, this.dateTime) - Object.assign(this.bodyPosition, bodyPosition) - } else { - this.name = undefined - Object.assign(this.bodyPosition, DEFAULT_BODY_POSITION) + else if (this.tab === BodyTabType.PLANET) { + if (this.planet.selected) { + const position = await this.api.positionOfPlanet(this.planet.selected.code, dateTime, location) + Object.assign(this.planet.position, position) } } // Minor Planet. - else if (this.tab === SkyAtlasTab.MINOR_PLANET) { - this.tags = [] - - if (this.minorPlanet) { - this.name = this.minorPlanet.name - // if (this.minorPlanet.kind) this.tags.push({ title: this.minorPlanet.kind, severity: 'success' }) - if (this.minorPlanet.orbitType) this.tags.push({ title: this.minorPlanet.orbitType, severity: 'success' }) - if (this.minorPlanet.pha) this.tags.push({ title: 'PHA', severity: 'danger' }) - if (this.minorPlanet.neo) this.tags.push({ title: 'NEO', severity: 'warning' }) - const code = `DES=${this.minorPlanet.spkId};` - const bodyPosition = await this.api.positionOfPlanet(code, this.dateTime) - Object.assign(this.bodyPosition, bodyPosition) - } else { - this.name = undefined - Object.assign(this.bodyPosition, DEFAULT_BODY_POSITION) + else if (this.tab === BodyTabType.MINOR_PLANET) { + if (this.minorPlanet.search.result) { + const code = `DES=${this.minorPlanet.search.result.spkId};` + const position = await this.api.positionOfPlanet(code, dateTime, location) + Object.assign(this.minorPlanet.position, position) } } // Sky Object. - else if (this.tab === SkyAtlasTab.SKY_OBJECT) { - this.tags = [] + else if (this.tab === BodyTabType.SKY_OBJECT) { + const selected = this.skyObject.search.selected - if (this.skyObject) { - this.name = this.skyObjectPipe.transform(this.skyObject, 'name') - const bodyPosition = await this.api.positionOfSkyObject(this.skyObject, this.dateTime) - Object.assign(this.bodyPosition, bodyPosition) - } else { - this.name = undefined - Object.assign(this.bodyPosition, DEFAULT_BODY_POSITION) + if (selected) { + const position = await this.api.positionOfSkyObject(selected, dateTime, location) + Object.assign(this.skyObject.position, position) } } // Satellite. else { - this.tags = [] - - if (this.satellite) { - this.name = this.satellite.name - const bodyPosition = await this.api.positionOfSatellite(this.satellite, this.dateTime) - Object.assign(this.bodyPosition, bodyPosition) - } else { - this.name = undefined - Object.assign(this.bodyPosition, DEFAULT_BODY_POSITION) + if (this.satellite.search.selected) { + const position = await this.api.positionOfSatellite(this.satellite.search.selected, dateTime, location) + Object.assign(this.satellite.position, position) } } - this.refreshingPosition = false + this.refresh.position = false - if (this.refreshTabCount === 1 || refreshTwilight) { - this.refreshingChart = true + if (this.refresh.count === 1 || refreshTwilight) { + this.refresh.chart = true - const twilight = await this.api.twilight(this.dateTime) + const twilight = await this.api.twilight(dateTime, location) this.altitudeData.datasets[0].data = [ [0.0, 90], [twilight.civilDusk[0], 90], @@ -793,109 +689,108 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, [twilight.civilDawn[1], 90], [24.0, 90], ] + this.chart.refresh() } - if (this.refreshTabCount === 1 || refreshChart) { + if (this.refresh.count === 1 || refreshChart) { await this.refreshChart() } } finally { - this.refreshingPosition = false - this.refreshingChart = false + this.refresh.position = false + this.refresh.chart = false } } private async refreshChart() { - this.refreshingChart = true + this.refresh.chart = true + + const { dateTime, location } = this.dateTimeAndLocation try { // Sun. - if (this.tab === SkyAtlasTab.SUN) { - const points = await this.api.altitudePointsOfSun(this.dateTime) - AtlasComponent.belowZeroPoints(points) - this.altitudeData.datasets[9].data = points + if (this.tab === BodyTabType.SUN) { + const points = await this.api.altitudePointsOfSun(dateTime, location) + this.updateAltitudeDataPoints(points) } // Moon. - else if (this.tab === SkyAtlasTab.MOON) { - const points = await this.api.altitudePointsOfMoon(this.dateTime) - AtlasComponent.belowZeroPoints(points) - this.altitudeData.datasets[9].data = points + else if (this.tab === BodyTabType.MOON) { + const points = await this.api.altitudePointsOfMoon(dateTime, location) + this.updateAltitudeDataPoints(points) } // Planet. - else if (this.tab === SkyAtlasTab.PLANET && this.planet) { - const points = await this.api.altitudePointsOfPlanet(this.planet.code, this.dateTime) - AtlasComponent.belowZeroPoints(points) - this.altitudeData.datasets[9].data = points + else if (this.tab === BodyTabType.PLANET) { + if (this.planet.selected) { + const points = await this.api.altitudePointsOfPlanet(this.planet.selected.code, dateTime, location) + this.updateAltitudeDataPoints(points) + } else { + this.updateAltitudeDataPoints() + } } // Minor Planet. - else if (this.tab === SkyAtlasTab.MINOR_PLANET) { - if (this.minorPlanet) { - const code = `DES=${this.minorPlanet.spkId};` - const points = await this.api.altitudePointsOfPlanet(code, this.dateTime) - AtlasComponent.belowZeroPoints(points) - this.altitudeData.datasets[9].data = points + else if (this.tab === BodyTabType.MINOR_PLANET) { + if (this.minorPlanet.search.result) { + const code = `DES=${this.minorPlanet.search.result.spkId};` + const points = await this.api.altitudePointsOfPlanet(code, dateTime, location) + this.updateAltitudeDataPoints(points) } else { - this.altitudeData.datasets[9].data = [] + this.updateAltitudeDataPoints() } } // Sky Object. - else if (this.tab === SkyAtlasTab.SKY_OBJECT) { - if (this.skyObject) { - const points = await this.api.altitudePointsOfSkyObject(this.skyObject, this.dateTime) - AtlasComponent.belowZeroPoints(points) - this.altitudeData.datasets[9].data = points + else if (this.tab === BodyTabType.SKY_OBJECT) { + if (this.skyObject.search.selected) { + const points = await this.api.altitudePointsOfSkyObject(this.skyObject.search.selected, dateTime, location) + this.updateAltitudeDataPoints(points) } else { - this.altitudeData.datasets[9].data = [] + this.updateAltitudeDataPoints() } } // Satellite. - else if (this.tab === SkyAtlasTab.SATELLITE) { - if (this.satellite) { - const points = await this.api.altitudePointsOfSatellite(this.satellite, this.dateTime) - AtlasComponent.belowZeroPoints(points) - this.altitudeData.datasets[9].data = points + else { + if (this.satellite.search.selected) { + const points = await this.api.altitudePointsOfSatellite(this.satellite.search.selected, dateTime, location) + this.updateAltitudeDataPoints(points) } else { - this.altitudeData.datasets[9].data = [] + this.updateAltitudeDataPoints() } - } else { - return } this.chart.refresh() } finally { - this.refreshingChart = false + this.refresh.chart = false + } + } + + private updateAltitudeDataPoints(points?: AltitudeDataPoint[]) { + if (points?.length) { + AtlasComponent.removePointsBelowZero(points) + this.altitudeData.datasets[9].data = points + } else { + this.altitudeData.datasets[9].data = [] } } private loadLocations() { - const settings = this.preference.settings.get() + const settings = this.preferenceService.settings.get() this.locations = settings.locations - this.location = this.locations.find((e) => e.id === this.location.id) ?? this.locations[settings.location] + this.dateTimeAndLocation.location = this.locations.find((e) => e.id === this.dateTimeAndLocation.location.id) ?? this.locations.find((e) => e.id === settings.location.id) ?? this.locations[0] } private loadPreference() { - const preference = this.preference.skyAtlasPreference.get() - - for (const group of SATELLITE_GROUPS) { - const satellite = preference.satellites.find((e) => e.group === group) - const enabled = satellite?.enabled ?? AtlasComponent.DEFAULT_SATELLITE_FILTERS.includes(group) - this.satelliteSearchGroup.set(group, enabled) - } + Object.assign(this.preference, this.preferenceService.skyAtlasPreference.get()) + this.satellite.search.filter.groups = this.preference.satellites + this.dateTimeAndLocation.location = this.preference.location this.loadLocations() } - savePreference() { - const preference = this.preference.skyAtlasPreference.get() - - preference.satellites = SATELLITE_GROUPS.map((group) => { - return { group, enabled: this.satelliteSearchGroup.get(group) ?? false } - }) - - this.preference.skyAtlasPreference.set(preference) + protected savePreference() { + this.preference.location = this.dateTimeAndLocation.location + this.preferenceService.skyAtlasPreference.set(this.preference) } - private static belowZeroPoints(points: [number, number][]) { + private static removePointsBelowZero(points: AltitudeDataPoint[]) { for (const point of points) { if (point[1] < 0) { point[1] = NaN @@ -904,7 +799,7 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, } private async executeMount(action: (mount: Mount) => void | Promise) { - if (await this.prime.confirm('Are you sure that you want to proceed?')) { + if (await this.primeService.confirm('Are you sure that you want to proceed?')) { return false } diff --git a/desktop/src/app/image/image.component.html b/desktop/src/app/image/image.component.html index db0c1780f..6f1c38e48 100644 --- a/desktop/src/app/image/image.component.html +++ b/desktop/src/app/image/image.component.html @@ -854,7 +854,7 @@
{ return this.browserWindowService.openSkyAtlas( { - tab: SkyAtlasTab.SKY_OBJECT, + tab: BodyTabType.SKY_OBJECT, filter: { rightAscension: this.currentComputedLocation.rightAscensionJ2000, declination: this.currentComputedLocation.declinationJ2000 }, }, { bringToFront: true }, diff --git a/desktop/src/app/settings/settings.component.html b/desktop/src/app/settings/settings.component.html index 0d2c87435..999c36db7 100644 --- a/desktop/src/app/settings/settings.component.html +++ b/desktop/src/app/settings/settings.component.html @@ -19,7 +19,7 @@
- {{ location.name || '?' }} + {{ preference.location.name || '?' }}
@@ -56,8 +56,8 @@
+ [location]="preference.location" + (locationChange)="locationChanged($event)" />
diff --git a/desktop/src/app/settings/settings.component.ts b/desktop/src/app/settings/settings.component.ts index 1ab68982b..7dd07b6c1 100644 --- a/desktop/src/app/settings/settings.component.ts +++ b/desktop/src/app/settings/settings.component.ts @@ -27,10 +27,6 @@ export class SettingsComponent implements AfterViewInit, OnDestroy { private readonly locationChangePublisher = new Subject() private readonly locationChangeSubscription?: Subscription - get location() { - return this.preference.locations[this.preference.location] ?? DEFAULT_LOCATION - } - get plateSolver() { return this.preference.plateSolver[this.plateSolverType] } @@ -55,7 +51,7 @@ export class SettingsComponent implements AfterViewInit, OnDestroy { app.title = 'Settings' this.locationChangeSubscription = this.locationChangePublisher.pipe(debounceTime(2000)).subscribe((location) => { - return this.electronService.send('LOCATION.CHANGED', location) + return this.electronService.locationChanged(location) }) } @@ -71,32 +67,26 @@ export class SettingsComponent implements AfterViewInit, OnDestroy { const location = structuredClone(DEFAULT_LOCATION) location.id = +new Date() this.preference.locations.push(location) - this.preference.location = this.preference.locations.length - 1 - - this.locationChanged() + this.locationChanged(location) } protected deleteLocation() { if (this.preference.locations.length > 1) { - const index = this.preference.locations.indexOf(this.location) + const index = this.preference.locations.findIndex((e) => e.id === this.preference.location.id) if (index >= 0) { this.preference.locations.splice(index, 1) - this.preference.location = 0 - - this.locationChanged() + this.locationChanged(this.preference.locations[0]) } } } protected locationChanged(location?: Location) { if (location) { - this.preference.location = this.preference.locations.indexOf(location) + this.preference.location = location + this.savePreference() + this.locationChangePublisher.next(location) } - - this.savePreference() - - this.locationChangePublisher.next(this.location) } protected resetCameraCaptureNamingFormat(type: FrameType) { @@ -106,6 +96,7 @@ export class SettingsComponent implements AfterViewInit, OnDestroy { private loadPreference() { Object.assign(this.preference, this.preferenceService.settings.get()) + this.preference.location = this.preference.locations.find((e) => e.id === this.preference.location.id) ?? this.preference.locations[0] } protected savePreference() { diff --git a/desktop/src/shared/dialogs/location/location.dialog.html b/desktop/src/shared/components/location/location.dialog.html similarity index 100% rename from desktop/src/shared/dialogs/location/location.dialog.html rename to desktop/src/shared/components/location/location.dialog.html diff --git a/desktop/src/shared/dialogs/location/location.dialog.ts b/desktop/src/shared/components/location/location.dialog.ts similarity index 88% rename from desktop/src/shared/dialogs/location/location.dialog.ts rename to desktop/src/shared/components/location/location.dialog.ts index be8865098..166e7d5d3 100644 --- a/desktop/src/shared/dialogs/location/location.dialog.ts +++ b/desktop/src/shared/components/location/location.dialog.ts @@ -1,13 +1,13 @@ import { AfterViewInit, Component, EventEmitter, Input, Optional, Output, ViewChild } from '@angular/core' import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog' -import { MapComponent } from '../../components/map/map.component' import { DEFAULT_LOCATION, Location } from '../../types/atlas.types' +import { MapComponent } from '../map/map.component' @Component({ selector: 'neb-location', templateUrl: './location.dialog.html', }) -export class LocationDialog implements AfterViewInit { +export class LocationComponent implements AfterViewInit { @ViewChild('map') private readonly map!: MapComponent diff --git a/desktop/src/shared/components/menu-item/menu-item.component.ts b/desktop/src/shared/components/menu-item/menu-item.component.ts index 3d25971c2..3f08f8ad8 100644 --- a/desktop/src/shared/components/menu-item/menu-item.component.ts +++ b/desktop/src/shared/components/menu-item/menu-item.component.ts @@ -1,7 +1,7 @@ import { Component, Input } from '@angular/core' import { CheckboxChangeEvent } from 'primeng/checkbox' import { InputSwitchChangeEvent } from 'primeng/inputswitch' -import { Severity, TooltipPosition } from '../../types/app.types' +import { Severity, TooltipPosition } from '../../types/angular.types' export interface MenuItemCommandEvent { originalEvent?: Event diff --git a/desktop/src/shared/components/moon/moon.component.html b/desktop/src/shared/components/moon/moon.component.html index e8086e306..70136bde4 100644 --- a/desktop/src/shared/components/moon/moon.component.html +++ b/desktop/src/shared/components/moon/moon.component.html @@ -1,4 +1,5 @@ + [width]="width" + style="filter: brightness(1.5)"> diff --git a/desktop/src/shared/components/moon/moon.component.ts b/desktop/src/shared/components/moon/moon.component.ts index 4825b51b1..382e2c69d 100644 --- a/desktop/src/shared/components/moon/moon.component.ts +++ b/desktop/src/shared/components/moon/moon.component.ts @@ -37,17 +37,14 @@ export class MoonComponent implements AfterViewInit, OnChanges { ctx.clearRect(0, 0, canvas.width, canvas.height) - const offset = 32 - const offset4 = offset / 4 - - const height = canvas.height - offset - const width = canvas.width - offset + const height = canvas.height + const width = canvas.width canvas.style.backgroundImage = `url('assets/images/moon.png')` - canvas.style.backgroundSize = `${height + offset4 * 2 - 2}px` + canvas.style.backgroundSize = `${height - 2}px` - const cx = width / 2 + offset4 - const cy = height / 2 + offset4 + const cx = width / 2 + const cy = height / 2 const pointsA: [number, number][] = [] const pointsB: [number, number][] = [] @@ -56,20 +53,20 @@ export class MoonComponent implements AfterViewInit, OnChanges { const angle = ((a - 90) * Math.PI) / 180 let x1 = Math.ceil(Math.cos(angle) * cx) const y1 = Math.ceil(Math.sin(angle) * cy) - const moonWidth = x1 * 2 - let x2 = Math.floor(moonWidth * this.illuminationRatio) + const w = x1 * 2 + let x2 = Math.floor(w * this.illuminationRatio) if (this.waning) { x1 = cx + x1 - x2 = x1 - (moonWidth - x2) + x2 = x1 - (w - x2) } else { x1 = cx - x1 - x2 = x1 + (moonWidth - x2) + x2 = x1 + (w - x2) } const y2 = cy + y1 - const p1: [number, number] = [x1 + offset4, y2 + offset4] - const p2: [number, number] = [x2 + offset4, y2 + offset4] + const p1: [number, number] = [x1, y2] + const p2: [number, number] = [x2, y2] pointsA.push(p1) pointsB.push(p2) @@ -78,7 +75,7 @@ export class MoonComponent implements AfterViewInit, OnChanges { const newPoints = pointsA.concat(pointsB.reverse()) ctx.beginPath() - ctx.fillStyle = '#121212D8' + ctx.fillStyle = '#121212E8' ctx.filter = 'blur(1px)' let first = true diff --git a/desktop/src/shared/interceptors/location.interceptor.ts b/desktop/src/shared/interceptors/location.interceptor.ts index b45d9a143..b8ef3715b 100644 --- a/desktop/src/shared/interceptors/location.interceptor.ts +++ b/desktop/src/shared/interceptors/location.interceptor.ts @@ -11,11 +11,29 @@ export class LocationInterceptor implements HttpInterceptor { intercept(req: HttpRequest, next: HttpHandler): Observable> { if (req.urlWithParams.includes('hasLocation')) { - const { location, locations } = this.preference.settings.get() + const params = new URLSearchParams(req.urlWithParams) + const hasLocation = params.get('hasLocation') - req = req.clone({ - headers: req.headers.set(LocationInterceptor.HEADER_KEY, JSON.stringify(locations[location])), - }) + if (!hasLocation || hasLocation === 'true') { + const location = this.preference.settings.get().location + + req = req.clone({ + headers: req.headers.set(LocationInterceptor.HEADER_KEY, JSON.stringify(location)), + }) + } else { + const id = parseInt(hasLocation) + + if (id) { + const locations = this.preference.settings.get().locations + const location = locations.find((e) => e.id === id) + + if (location) { + req = req.clone({ + headers: req.headers.set(LocationInterceptor.HEADER_KEY, JSON.stringify(location)), + }) + } + } + } } return next.handle(req) diff --git a/desktop/src/shared/pipes/dropdown-options.pipe.ts b/desktop/src/shared/pipes/dropdown-options.pipe.ts index 7f7253c13..f1f51b59a 100644 --- a/desktop/src/shared/pipes/dropdown-options.pipe.ts +++ b/desktop/src/shared/pipes/dropdown-options.pipe.ts @@ -1,5 +1,6 @@ import { Pipe, PipeTransform } from '@angular/core' import { Hemisphere } from '../types/alignment.types' +import { Constellation, CONSTELLATIONS, SATELLITE_GROUPS, SatelliteGroupType, SKY_OBJECT_TYPES, SkyObjectType } from '../types/atlas.types' import { AutoFocusFittingMode, BacklashCompensationMode } from '../types/autofocus.type' import { ExposureMode, FrameType, LiveStackerType } from '../types/camera.types' import { GuideDirection, GuiderPlotMode, GuiderYAxisUnit } from '../types/guider.types' @@ -36,7 +37,10 @@ export interface DropdownOptions { SETTINGS_TAB: SettingsTabKey[] STACKER_GROUP_TYPE: StackerGroupType[] CONNECTION_TYPE: ConnectionType[] - IMAGE_STATISTICS_BIT_OPTIONS: ImageStatisticsBitOption[] + IMAGE_STATISTICS_BIT_OPTION: ImageStatisticsBitOption[] + SATELLITE_GROUP_TYPE: SatelliteGroupType[] + CONSTELLATION: Constellation[] + SKY_OBJECT_TYPE: SkyObjectType[] } @Pipe({ name: 'dropdownOptions' }) @@ -89,8 +93,14 @@ export class DropdownOptionsPipe implements PipeTransform { return ['LUMINANCE', 'RED', 'GREEN', 'BLUE', 'MONO', 'RGB'] as DropdownOptions[K] case 'CONNECTION_TYPE': return ['INDI', 'ALPACA'] as DropdownOptions[K] - case 'IMAGE_STATISTICS_BIT_OPTIONS': + case 'IMAGE_STATISTICS_BIT_OPTION': return IMAGE_STATISTICS_BIT_OPTIONS as DropdownOptions[K] + case 'SATELLITE_GROUP_TYPE': + return SATELLITE_GROUPS as unknown as DropdownOptions[K] + case 'CONSTELLATION': + return CONSTELLATIONS as unknown as DropdownOptions[K] + case 'SKY_OBJECT_TYPE': + return SKY_OBJECT_TYPES as unknown as DropdownOptions[K] } return [] diff --git a/desktop/src/shared/pipes/enum-dropdown.pipe.ts b/desktop/src/shared/pipes/enum-dropdown.pipe.ts index 2d344d126..1e02fa89e 100644 --- a/desktop/src/shared/pipes/enum-dropdown.pipe.ts +++ b/desktop/src/shared/pipes/enum-dropdown.pipe.ts @@ -1,12 +1,12 @@ import { Pipe, PipeTransform } from '@angular/core' import { DropdownItem } from '../types/angular.types' -import { EnumPipe, EnumPipeKey } from './enum.pipe' +import { EnumPipe } from './enum.pipe' @Pipe({ name: 'enumDropdown' }) export class EnumDropdownPipe implements PipeTransform { constructor(private readonly enumPipe: EnumPipe) {} - transform(value: EnumPipeKey[]): DropdownItem[] { + transform(value: T[]): DropdownItem[] { return value.map((value) => { return { label: this.enumPipe.transform(value), value } }) diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts index 6675e181d..3b26e3d1d 100644 --- a/desktop/src/shared/services/api.service.ts +++ b/desktop/src/shared/services/api.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core' -import moment from 'moment' import { DARVStart, TPPAStart } from '../types/alignment.types' -import { Angle, BodyPosition, CloseApproach, ComputedLocation, Constellation, DeepSkyObject, MinorPlanet, Satellite, SatelliteGroupType, SkyObjectType, Twilight } from '../types/atlas.types' +import { extractDate, extractDateTime } from '../types/angular.types' +import { Angle, BodyPosition, CloseApproach, ComputedLocation, Constellation, DeepSkyObject, Location, MinorPlanet, Satellite, SatelliteGroupType, SkyObjectType, Twilight } from '../types/atlas.types' import { AutoFocusRequest } from '../types/autofocus.type' import { CalibrationFrame } from '../types/calibration.types' import { Camera, CameraStartCapture } from '../types/camera.types' @@ -445,51 +445,51 @@ export class ApiService { // SKY ATLAS - positionOfSun(dateTime: Date, fast: boolean = false) { - const [date, time] = moment(dateTime).format('YYYY-MM-DD HH:mm').split(' ') - const query = this.http.query({ date, time, fast, hasLocation: true }) + positionOfSun(dateTime: Date, location?: Location, fast: boolean = false) { + const [date, time] = extractDateTime(dateTime) + const query = this.http.query({ date, time, fast, hasLocation: location?.id || true }) return this.http.get(`sky-atlas/sun/position?${query}`) } - altitudePointsOfSun(dateTime: Date, fast: boolean = false) { - const date = moment(dateTime).format('YYYY-MM-DD') - const query = this.http.query({ date, fast, hasLocation: true }) + altitudePointsOfSun(dateTime: Date, location?: Location, fast: boolean = false) { + const date = extractDate(dateTime) + const query = this.http.query({ date, fast, hasLocation: location?.id || true }) return this.http.get<[number, number][]>(`sky-atlas/sun/altitude-points?${query}`) } - positionOfMoon(dateTime: Date, fast: boolean = false) { - const [date, time] = moment(dateTime).format('YYYY-MM-DD HH:mm').split(' ') - const query = this.http.query({ date, time, fast, hasLocation: true }) + positionOfMoon(dateTime: Date, location?: Location, fast: boolean = false) { + const [date, time] = extractDateTime(dateTime) + const query = this.http.query({ date, time, fast, hasLocation: location?.id || true }) return this.http.get(`sky-atlas/moon/position?${query}`) } - altitudePointsOfMoon(dateTime: Date, fast: boolean = false) { - const date = moment(dateTime).format('YYYY-MM-DD') - const query = this.http.query({ date, fast, hasLocation: true }) + altitudePointsOfMoon(dateTime: Date, location?: Location, fast: boolean = false) { + const date = extractDate(dateTime) + const query = this.http.query({ date, fast, hasLocation: location?.id || true }) return this.http.get<[number, number][]>(`sky-atlas/moon/altitude-points?${query}`) } - positionOfPlanet(code: string, dateTime: Date, fast: boolean = false) { - const [date, time] = moment(dateTime).format('YYYY-MM-DD HH:mm').split(' ') - const query = this.http.query({ date, time, fast, hasLocation: true }) + positionOfPlanet(code: string, dateTime: Date, location?: Location, fast: boolean = false) { + const [date, time] = extractDateTime(dateTime) + const query = this.http.query({ date, time, fast, hasLocation: location?.id || true }) return this.http.get(`sky-atlas/planets/${encodeURIComponent(code)}/position?${query}`) } - altitudePointsOfPlanet(code: string, dateTime: Date, fast: boolean = false) { - const date = moment(dateTime).format('YYYY-MM-DD') - const query = this.http.query({ date, fast, hasLocation: true }) + altitudePointsOfPlanet(code: string, dateTime: Date, location?: Location, fast: boolean = false) { + const date = extractDate(dateTime) + const query = this.http.query({ date, fast, hasLocation: location?.id || true }) return this.http.get<[number, number][]>(`sky-atlas/planets/${encodeURIComponent(code)}/altitude-points?${query}`) } - positionOfSkyObject(simbad: DeepSkyObject, dateTime: Date) { - const [date, time] = moment(dateTime).format('YYYY-MM-DD HH:mm').split(' ') - const query = this.http.query({ date, time, hasLocation: true }) + positionOfSkyObject(simbad: DeepSkyObject, dateTime: Date, location?: Location) { + const [date, time] = extractDateTime(dateTime) + const query = this.http.query({ date, time, hasLocation: location?.id || true }) return this.http.get(`sky-atlas/sky-objects/${simbad.id}/position?${query}`) } - altitudePointsOfSkyObject(simbad: DeepSkyObject, dateTime: Date) { - const date = moment(dateTime).format('YYYY-MM-DD') - const query = this.http.query({ date, hasLocation: true }) + altitudePointsOfSkyObject(simbad: DeepSkyObject, dateTime: Date, location?: Location) { + const date = extractDate(dateTime) + const query = this.http.query({ date, hasLocation: location?.id || true }) return this.http.get<[number, number][]>(`sky-atlas/sky-objects/${simbad.id}/altitude-points?${query}`) } @@ -502,15 +502,15 @@ export class ApiService { return this.http.get(`sky-atlas/sky-objects/types`) } - positionOfSatellite(satellite: Satellite, dateTime: Date) { - const [date, time] = moment(dateTime).format('YYYY-MM-DD HH:mm').split(' ') - const query = this.http.query({ date, time, hasLocation: true }) + positionOfSatellite(satellite: Satellite, dateTime: Date, location?: Location) { + const [date, time] = extractDateTime(dateTime) + const query = this.http.query({ date, time, hasLocation: location?.id || true }) return this.http.get(`sky-atlas/satellites/${satellite.id}/position?${query}`) } - altitudePointsOfSatellite(satellite: Satellite, dateTime: Date) { - const date = moment(dateTime).format('YYYY-MM-DD') - const query = this.http.query({ date, hasLocation: true }) + altitudePointsOfSatellite(satellite: Satellite, dateTime: Date, location?: Location) { + const date = extractDate(dateTime) + const query = this.http.query({ date, hasLocation: location?.id || true }) return this.http.get<[number, number][]>(`sky-atlas/satellites/${satellite.id}/altitude-points?${query}`) } @@ -519,9 +519,9 @@ export class ApiService { return this.http.get(`sky-atlas/satellites?${query}`) } - twilight(dateTime: Date, fast: boolean = false) { - const date = moment(dateTime).format('YYYY-MM-DD') - const query = this.http.query({ date, fast, hasLocation: true }) + twilight(dateTime: Date, location?: Location, fast: boolean = false) { + const date = extractDate(dateTime) + const query = this.http.query({ date, fast, hasLocation: location?.id || true }) return this.http.get(`sky-atlas/twilight?${query}`) } @@ -530,14 +530,14 @@ export class ApiService { return this.http.get(`sky-atlas/minor-planets?${query}`) } - closeApproachesForMinorPlanets(days: number = 7, distance: number = 10, dateTime?: Date | string) { - const date = !dateTime || typeof dateTime === 'string' ? dateTime : moment(dateTime).format('YYYY-MM-DD') + closeApproachesOfMinorPlanets(days: number = 7, distance: number = 10, dateTime?: Date | string) { + const date = !dateTime || typeof dateTime === 'string' ? dateTime : extractDate(dateTime) const query = this.http.query({ days, distance, date }) return this.http.get(`sky-atlas/minor-planets/close-approaches?${query}`) } - annotationsOfImage(path: string, request: AnnotateImageRequest) { - const query = this.http.query({ path, hasLocation: true }) + annotationsOfImage(path: string, request: AnnotateImageRequest, location?: Location) { + const query = this.http.query({ path, hasLocation: location?.id || true }) return this.http.put(`image/annotations?${query}`, request) } diff --git a/desktop/src/shared/services/electron.service.ts b/desktop/src/shared/services/electron.service.ts index 4204fb9c5..aa8012ddb 100644 --- a/desktop/src/shared/services/electron.service.ts +++ b/desktop/src/shared/services/electron.service.ts @@ -237,4 +237,8 @@ export class ElectronService { calibrationChanged() { return this.send('CALIBRATION.CHANGED') } + + locationChanged(location: Location) { + return this.send('LOCATION.CHANGED', location) + } } diff --git a/desktop/src/shared/services/preference.service.ts b/desktop/src/shared/services/preference.service.ts index f757898a6..1d91e565a 100644 --- a/desktop/src/shared/services/preference.service.ts +++ b/desktop/src/shared/services/preference.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core' import { AlignmentPreference, alignmentPreferenceWithDefault, DEFAULT_ALIGNMENT_PREFERENCE } from '../types/alignment.types' -import { DEFAULT_SKY_ATLAS_PREFERENCE, SkyAtlasPreference } from '../types/atlas.types' +import { DEFAULT_SKY_ATLAS_PREFERENCE, SkyAtlasPreference, skyAtlasPreferenceWithDefault } from '../types/atlas.types' import { AutoFocusPreference, autoFocusPreferenceWithDefault, DEFAULT_AUTO_FOCUS_PREFERENCE } from '../types/autofocus.type' import { CalibrationPreference, calibrationPreferenceWithDefault, DEFAULT_CALIBRATION_PREFERENCE } from '../types/calibration.types' import { Camera, CameraPreference, cameraPreferenceWithDefault, DEFAULT_CAMERA_PREFERENCE } from '../types/camera.types' @@ -83,7 +83,7 @@ export class PreferenceService { readonly home = new PreferenceData(this.storage, 'home', () => structuredClone(DEFAULT_HOME_PREFERENCE), homePreferenceWithDefault) readonly imagePreference = new PreferenceData(this.storage, 'image', () => structuredClone(DEFAULT_IMAGE_PREFERENCE), imagePreferenceWithDefault) - readonly skyAtlasPreference = new PreferenceData(this.storage, 'atlas', () => structuredClone(DEFAULT_SKY_ATLAS_PREFERENCE)) + readonly skyAtlasPreference = new PreferenceData(this.storage, 'atlas', () => structuredClone(DEFAULT_SKY_ATLAS_PREFERENCE), skyAtlasPreferenceWithDefault) readonly alignment = new PreferenceData(this.storage, 'alignment', () => structuredClone(DEFAULT_ALIGNMENT_PREFERENCE), alignmentPreferenceWithDefault) readonly calibrationPreference = new PreferenceData(this.storage, 'calibration', () => structuredClone(DEFAULT_CALIBRATION_PREFERENCE), calibrationPreferenceWithDefault) readonly sequencerPreference = new PreferenceData(this.storage, 'sequencer', () => structuredClone(DEFAULT_SEQUENCER_PREFERENCE)) diff --git a/desktop/src/shared/types/angular.types.ts b/desktop/src/shared/types/angular.types.ts index 713244b9b..054afff2d 100644 --- a/desktop/src/shared/types/angular.types.ts +++ b/desktop/src/shared/types/angular.types.ts @@ -1,4 +1,30 @@ +export type Severity = 'success' | 'info' | 'warning' | 'danger' + +export type TooltipPosition = 'right' | 'left' | 'top' | 'bottom' + export interface DropdownItem { label: string value: T } + +export function extractDateTime(date: Date) { + return [extractDate(date), extractTime(date)] +} + +function padNumber(value: number) { + return value <= 9 ? `0${value}` : `${value}` +} + +export function extractDate(date: Date) { + return `${date.getFullYear()}-${padNumber(date.getMonth())}-${padNumber(date.getDay())}` +} + +export function extractTime(date: Date, hasSeconds: boolean = true) { + const time = `${padNumber(date.getHours())}:${padNumber(date.getMinutes())}` + + if (hasSeconds) { + return `${time}:${padNumber(date.getSeconds())}` + } else { + return time + } +} diff --git a/desktop/src/shared/types/api.types.ts b/desktop/src/shared/types/api.types.ts index a1edbff8e..aea0aa242 100644 --- a/desktop/src/shared/types/api.types.ts +++ b/desktop/src/shared/types/api.types.ts @@ -1,5 +1,7 @@ import type { Device } from './device.types' +export type ApiEventType = (typeof API_EVENT_TYPES)[number] + export interface MessageEvent { eventName: string } @@ -53,5 +55,3 @@ export const API_EVENT_TYPES = [ // Auto Focus. 'AUTO_FOCUS.ELAPSED', ] as const - -export type ApiEventType = (typeof API_EVENT_TYPES)[number] diff --git a/desktop/src/shared/types/app.types.ts b/desktop/src/shared/types/app.types.ts index f2bef9531..742b3181f 100644 --- a/desktop/src/shared/types/app.types.ts +++ b/desktop/src/shared/types/app.types.ts @@ -1,8 +1,9 @@ +import type { Severity } from './angular.types' import type { MessageEvent } from './api.types' -export type Severity = 'success' | 'info' | 'warning' | 'danger' +export type InternalEventType = (typeof INTERNAL_EVENT_TYPES)[number] -export type TooltipPosition = 'right' | 'left' | 'top' | 'bottom' +export type SaveJson = OpenFile & JsonFile export interface NotificationEvent extends MessageEvent { target?: string @@ -16,28 +17,6 @@ export interface ConfirmationEvent extends MessageEvent { idempotencyKey: string } -export const INTERNAL_EVENT_TYPES = [ - 'DIRECTORY.OPEN', - 'FILE.OPEN', - 'FILE.SAVE', - 'WINDOW.OPEN', - 'WINDOW.CLOSE', - 'WINDOW.PIN', - 'WINDOW.UNPIN', - 'WINDOW.MINIMIZE', - 'WINDOW.MAXIMIZE', - 'WINDOW.RESIZE', - 'WHEEL.RENAMED', - 'LOCATION.CHANGED', - 'JSON.WRITE', - 'JSON.READ', - 'CALIBRATION.CHANGED', - 'WINDOW.FULLSCREEN', - 'ROI.SELECTED', -] as const - -export type InternalEventType = (typeof INTERNAL_EVENT_TYPES)[number] - export interface WindowPreference { modal?: boolean autoResizable?: boolean @@ -88,4 +67,22 @@ export interface JsonFile { json: T } -export interface SaveJson extends OpenFile, JsonFile {} +export const INTERNAL_EVENT_TYPES = [ + 'DIRECTORY.OPEN', + 'FILE.OPEN', + 'FILE.SAVE', + 'WINDOW.OPEN', + 'WINDOW.CLOSE', + 'WINDOW.PIN', + 'WINDOW.UNPIN', + 'WINDOW.MINIMIZE', + 'WINDOW.MAXIMIZE', + 'WINDOW.RESIZE', + 'WHEEL.RENAMED', + 'LOCATION.CHANGED', + 'JSON.WRITE', + 'JSON.READ', + 'CALIBRATION.CHANGED', + 'WINDOW.FULLSCREEN', + 'ROI.SELECTED', +] as const diff --git a/desktop/src/shared/types/atlas.types.ts b/desktop/src/shared/types/atlas.types.ts index 656afae5e..4071a0d87 100644 --- a/desktop/src/shared/types/atlas.types.ts +++ b/desktop/src/shared/types/atlas.types.ts @@ -1,14 +1,121 @@ +import type { Subscription } from 'rxjs' +import type { Severity } from './angular.types' import type { PierSide } from './mount.types' export type Angle = string | number -export interface PlanetTableItem { +export type Constellation = (typeof CONSTELLATIONS)[number] + +export type ClassificationType = (typeof CLASSIFICATION_TYPES)[number] + +export type SkyObjectType = (typeof SKY_OBJECT_TYPES)[number] + +export type MinorPlanetKind = 'ASTEROID' | 'COMET' + +export type Star = DeepSkyObject & SpectralSkyObject + +export type SatelliteGroupType = (typeof SATELLITE_GROUPS)[number] + +export type PlanetType = 'PLANET' | 'DWARF_PLANET' | 'MOON_OF_MARS' | 'MOON_OF_JUPITER' | 'MOON_OF_SATURN' | 'MOON_OF_URANUS' | 'MOON_OF_NEPTUNE' | 'MOON_OF_PLUTO' | 'ASTEROID' + +export type AltitudeDataPoint = [number, number] + +export type SatelliteSearchGroups = Record + +export enum BodyTabType { + SUN, + MOON, + PLANET, + MINOR_PLANET, + SKY_OBJECT, + SATELLITE, +} + +export interface BodyTag { + label: string + severity: Severity +} + +export interface BodyTab { + position: BodyPosition + name: string + tags: BodyTag[] +} + +export interface SunTab extends BodyTab { + image: string +} + +export type MoonTab = BodyTab + +export interface PlanetItem { name: string - type: string + type: PlanetType code: string } -export interface SearchFilter { +export interface PlanetTab extends BodyTab { + selected?: PlanetItem + readonly planets: PlanetItem[] +} + +export interface OrbitalPhysicalParameter { + name: string + description: string + value: string +} + +export interface MinorPlanetListItem { + name: string + pdes: string +} + +export interface MinorPlanet { + found: boolean + name: string + spkId: number + kind?: MinorPlanetKind + pha: boolean + neo: boolean + orbitType: string + parameters: OrbitalPhysicalParameter[] + list: MinorPlanetListItem[] +} + +export interface CloseApproach { + name: string + designation: string + dateTime: number + distance: number + absoluteMagnitude: number +} + +export interface MinorPlanetTab extends BodyTab { + tab: number + search: { + text: string + result?: MinorPlanet + } + closeApproach: { + days: number + lunarDistance: number + result: CloseApproach[] + selected?: CloseApproach + } + list: { + items: MinorPlanetListItem[] + showDialog: boolean + } +} + +export interface SkyObjectTab extends BodyTab { + search: SkyObjectSearchDialog & { + result: DeepSkyObject[] + selected?: DeepSkyObject + } +} + +export interface SkyObjectSearchFilter { text: string rightAscension: Angle declination: Angle @@ -16,10 +123,234 @@ export interface SearchFilter { constellation: Constellation | 'ALL' magnitude: [number, number] type: SkyObjectType | 'ALL' - types: (SkyObjectType | 'ALL')[] } -export const DEFAULT_SEARCH_FILTER: SearchFilter = { +export interface SkyObjectSearchDialog { + showDialog: boolean + filter: SkyObjectSearchFilter +} + +export interface SatelliteSearchFilter { + text: string + groups: SatelliteSearchGroups +} + +export interface SatelliteSearchDialog { + showDialog: boolean + filter: SatelliteSearchFilter +} + +export interface Satellite { + id: number + name: string + tle: string + groups: SatelliteGroupType[] +} + +export interface SatelliteTab extends BodyTab { + search: SatelliteSearchDialog & { + result: Satellite[] + selected?: Satellite + } +} + +export interface BodyTabRefresh { + count: number + timer?: Subscription + position: boolean + chart: boolean +} + +export interface DateTimeAndLocation { + manual: boolean + dateTime: Date + location: Location +} + +export interface Location { + id: number + name: string + latitude: number + longitude: number + elevation: number + offsetInMinutes: number +} + +export interface SkyAtlasPreference { + satellites: SatelliteSearchGroups + location: Location + fast: boolean +} + +export interface SkyAtlasInput { + tab: BodyTabType + filter?: Partial> +} + +export interface EquatorialCoordinate { + rightAscension: Angle + declination: Angle +} + +export interface EquatorialCoordinateJ2000 { + rightAscensionJ2000: Angle + declinationJ2000: Angle +} + +export interface HorizontalCoordinate { + azimuth: Angle + altitude: Angle +} + +export interface BodyPosition extends EquatorialCoordinate, EquatorialCoordinateJ2000, HorizontalCoordinate { + magnitude: number + constellation: Constellation + distance: number + distanceUnit: string + illuminated: number + elongation: number + leading: boolean +} + +export interface Twilight { + civilDusk: number[] + nauticalDusk: number[] + astronomicalDusk: number[] + night: number[] + astronomicalDawn: number[] + nauticalDawn: number[] + civilDawn: number[] +} + +export interface AstronomicalObject extends EquatorialCoordinateJ2000 { + id: number + name: string + magnitude: number +} + +export interface SpectralSkyObject { + spType: string +} + +export interface OrientedSkyObject { + majorAxis: number + minorAxis: number + orientation: number +} + +export interface DeepSkyObject extends AstronomicalObject { + type: SkyObjectType + redshift: number + parallax: number + radialVelocity: number + distance: number + pmRA: number + pmDEC: number + constellation: Constellation +} + +export interface ComputedLocation extends EquatorialCoordinate, EquatorialCoordinateJ2000, HorizontalCoordinate { + constellation: Constellation + meridianAt: string + timeLeftToMeridianFlip: string + lst: string + pierSide: PierSide +} + +export const DEFAULT_BODY_POSITION: BodyPosition = { + rightAscensionJ2000: '00h00m00s', + declinationJ2000: `+000ยฐ00'00"`, + rightAscension: '00h00m00s', + declination: `+000ยฐ00'00"`, + azimuth: `000ยฐ00'00"`, + altitude: `+00ยฐ00'00"`, + magnitude: 0, + constellation: 'AND', + distance: 0, + distanceUnit: 'ly', + illuminated: 0, + elongation: 0, + leading: false, +} + +export const DEFAULT_SUN: SunTab = { + name: 'Sun', + position: DEFAULT_BODY_POSITION, + tags: [], + image: '', +} + +export const DEFAULT_MOON: MoonTab = { + name: 'Moon', + position: DEFAULT_BODY_POSITION, + tags: [], +} + +export const DEFAULT_PLANET_ITEMS: PlanetItem[] = [ + { name: 'Mercury', type: 'PLANET', code: '199' }, + { name: 'Venus', type: 'PLANET', code: '299' }, + { name: 'Mars', type: 'PLANET', code: '499' }, + { name: 'Jupiter', type: 'PLANET', code: '599' }, + { name: 'Saturn', type: 'PLANET', code: '699' }, + { name: 'Uranus', type: 'PLANET', code: '799' }, + { name: 'Neptune', type: 'PLANET', code: '899' }, + { name: 'Pluto', type: 'DWARF_PLANET', code: '999' }, + { name: 'Phobos', type: 'MOON_OF_MARS', code: '401' }, + { name: 'Deimos', type: 'MOON_OF_MARS', code: '402' }, + { name: 'Io', type: 'MOON_OF_JUPITER', code: '501' }, + { name: 'Europa', type: 'MOON_OF_JUPITER', code: '402' }, + { name: 'Ganymede', type: 'MOON_OF_JUPITER', code: '403' }, + { name: 'Callisto', type: 'MOON_OF_JUPITER', code: '504' }, + { name: 'Mimas', type: 'MOON_OF_SATURN', code: '601' }, + { name: 'Enceladus', type: 'MOON_OF_SATURN', code: '602' }, + { name: 'Tethys', type: 'MOON_OF_SATURN', code: '603' }, + { name: 'Dione', type: 'MOON_OF_SATURN', code: '604' }, + { name: 'Rhea', type: 'MOON_OF_SATURN', code: '605' }, + { name: 'Titan', type: 'MOON_OF_SATURN', code: '606' }, + { name: 'Hyperion', type: 'MOON_OF_SATURN', code: '607' }, + { name: 'Iapetus', type: 'MOON_OF_SATURN', code: '608' }, + { name: 'Ariel', type: 'MOON_OF_URANUS', code: '701' }, + { name: 'Umbriel', type: 'MOON_OF_URANUS', code: '702' }, + { name: 'Titania', type: 'MOON_OF_URANUS', code: '703' }, + { name: 'Oberon', type: 'MOON_OF_URANUS', code: '704' }, + { name: 'Miranda', type: 'MOON_OF_URANUS', code: '705' }, + { name: 'Triton', type: 'MOON_OF_NEPTUNE', code: '801' }, + { name: 'Charon', type: 'MOON_OF_PLUTO', code: '901' }, + { name: '1 Ceres', type: 'DWARF_PLANET', code: '1;' }, + { name: '90377 Sedna', type: 'DWARF_PLANET', code: '90377;' }, + { name: '136199 Eris', type: 'DWARF_PLANET', code: '136199;' }, + { name: '2 Pallas', type: 'ASTEROID', code: '2;' }, + { name: '3 Juno', type: 'ASTEROID', code: '3;' }, + { name: '4 Vesta', type: 'ASTEROID', code: '4;' }, +] + +export const DEFAULT_PLANET: PlanetTab = { + name: '', + position: DEFAULT_BODY_POSITION, + tags: [], + planets: DEFAULT_PLANET_ITEMS, +} + +export const DEFAULT_MINOR_PLANET: MinorPlanetTab = { + tab: 0, + name: '', + position: DEFAULT_BODY_POSITION, + tags: [], + search: { + text: '', + }, + closeApproach: { + days: 7, + lunarDistance: 10, + result: [], + }, + list: { + showDialog: false, + items: [], + }, +} + +export const DEFAULT_SKY_OBJECT_SEARCH_FILTER: SkyObjectSearchFilter = { text: '', rightAscension: '00h00m00s', declination: `+000ยฐ00'00"`, @@ -27,42 +358,141 @@ export const DEFAULT_SEARCH_FILTER: SearchFilter = { constellation: 'ALL', magnitude: [-30, 30], type: 'ALL', - types: ['ALL'], } -export interface SatelliteGroupFilterItem { - group: SatelliteGroupType - enabled: boolean +export const DEFAULT_SKY_OBJECT_SEARCH_DIALOG: SkyObjectSearchDialog = { + showDialog: false, + filter: DEFAULT_SKY_OBJECT_SEARCH_FILTER, } -export interface SkyAtlasPreference { - satellites: SatelliteGroupFilterItem[] - fast: boolean +export const DEFAULT_SKY_OBJECT: SkyObjectTab = { + name: '', + search: { + ...DEFAULT_SKY_OBJECT_SEARCH_DIALOG, + result: [], + }, + position: DEFAULT_BODY_POSITION, + tags: [], } -export const DEFAULT_SKY_ATLAS_PREFERENCE: SkyAtlasPreference = { - satellites: [], - fast: false, +export const DEFAULT_SATELLITE_SEARCH_GROUPS: SatelliteSearchGroups = { + ACTIVE: false, + AMATEUR: true, + ANALYST: false, + ARGOS: false, + BEIDOU: true, + COSMOS_1408_DEBRIS: false, + COSMOS_2251_DEBRIS: false, + CUBESAT: false, + DMC: false, + EDUCATION: false, + ENGINEERING: false, + FENGYUN_1C_DEBRIS: false, + GALILEO: true, + GEO: false, + GEODETIC: false, + GLO_OPS: true, + GLOBALSTAR: false, + GNSS: true, + GOES: false, + GORIZONT: false, + GPS_OPS: true, + INTELSAT: false, + IRIDIUM_33_DEBRIS: false, + IRIDIUM_NEXT: false, + IRIDIUM: false, + LAST_30_DAYS: false, + MILITARY: false, + MOLNIYA: false, + MUSSON: false, + NNSS: false, + NOAA: false, + ONEWEB: true, + ORBCOMM: false, + OTHER_COMM: false, + OTHER: false, + PLANET: false, + RADAR: false, + RADUGA: false, + RESOURCE: false, + SARSAT: false, + SATNOGS: false, + SBAS: false, + SCIENCE: true, + SES: false, + SPIRE: false, + STARLINK: true, + STATIONS: true, + SWARM: false, + TDRSS: false, + VISUAL: true, + WEATHER: false, + X_COMM: false, } -export enum SkyAtlasTab { - SUN, - MOON, - PLANET, - MINOR_PLANET, - SKY_OBJECT, - SATELLITE, +export const DEFAULT_SATELLITE_SEARCH_FILTER: SatelliteSearchFilter = { + text: '', + groups: DEFAULT_SATELLITE_SEARCH_GROUPS, } -export interface SkyAtlasInput { - tab: SkyAtlasTab - filter?: Partial> +export const DEFAULT_SATELLITE_SEARCH_DIALOG: SatelliteSearchDialog = { + showDialog: false, + filter: DEFAULT_SATELLITE_SEARCH_FILTER, } -export interface SettingsDialog { - showDialog: boolean +export const DEFAULT_SATELLITE: SatelliteTab = { + name: '', + search: { + ...DEFAULT_SATELLITE_SEARCH_DIALOG, + result: [], + }, + position: DEFAULT_BODY_POSITION, + tags: [], +} + +export const DEFAULT_COMPUTED_LOCATION: ComputedLocation = { + constellation: 'AND', + meridianAt: '00:00', + timeLeftToMeridianFlip: '00:00', + lst: '00:00', + pierSide: 'NEITHER', + rightAscensionJ2000: '00h00m00s', + declinationJ2000: `+000ยฐ00'00"`, + rightAscension: '00h00m00s', + declination: `+000ยฐ00'00"`, + azimuth: `000ยฐ00'00"`, + altitude: `+00ยฐ00'00"`, +} + +export const DEFAULT_LOCATION: Location = { + id: 0, + name: 'Null Island', + latitude: 0, + longitude: 0, + elevation: 0, + offsetInMinutes: 0, +} + +export const DEFAULT_BODY_TAB_REFRESH: BodyTabRefresh = { + count: 0, + position: false, + chart: false, +} + +export const DEFAULT_DATE_TIME_AND_LOCATION: DateTimeAndLocation = { + manual: false, + dateTime: new Date(), + location: DEFAULT_LOCATION, } +export const DEFAULT_SKY_ATLAS_PREFERENCE: SkyAtlasPreference = { + satellites: DEFAULT_SATELLITE_SEARCH_GROUPS, + location: DEFAULT_DATE_TIME_AND_LOCATION.location, + fast: false, +} + +export const CLASSIFICATION_TYPES = ['STAR', 'SET_OF_STARS', 'INTERSTELLAR_MEDIUM', 'GALAXY', 'SET_OF_GALAXIES', 'GRAVITATION', 'SPECTRAL', 'OTHER'] as const + export const CONSTELLATIONS = [ 'AND', 'ANT', @@ -154,12 +584,6 @@ export const CONSTELLATIONS = [ 'VUL', ] as const -export type Constellation = (typeof CONSTELLATIONS)[number] - -export const CLASSIFICATION_TYPES = ['STAR', 'SET_OF_STARS', 'INTERSTELLAR_MEDIUM', 'GALAXY', 'SET_OF_GALAXIES', 'GRAVITATION', 'SPECTRAL', 'OTHER'] as const - -export type ClassificationType = (typeof CLASSIFICATION_TYPES)[number] - export const SKY_OBJECT_TYPES = [ 'ACTIVE_GALAXY_NUCLEUS', 'ALPHA2_CVN_VARIABLE', @@ -315,143 +739,6 @@ export const SKY_OBJECT_TYPES = [ 'YOUNG_STELLAR_OBJECT', ] as const -export type SkyObjectType = (typeof SKY_OBJECT_TYPES)[number] - -export interface EquatorialCoordinate { - rightAscension: Angle - declination: Angle -} - -export interface EquatorialCoordinateJ2000 { - rightAscensionJ2000: Angle - declinationJ2000: Angle -} - -export interface HorizontalCoordinate { - azimuth: Angle - altitude: Angle -} - -export interface BodyPosition extends EquatorialCoordinate, EquatorialCoordinateJ2000, HorizontalCoordinate { - magnitude: number - constellation: Constellation - distance: number - distanceUnit: string - illuminated: number - elongation: number - leading: boolean -} - -export const DEFAULT_BODY_POSITION: BodyPosition = { - rightAscensionJ2000: '00h00m00s', - declinationJ2000: `+000ยฐ00'00"`, - rightAscension: '00h00m00s', - declination: `+000ยฐ00'00"`, - azimuth: `000ยฐ00'00"`, - altitude: `+00ยฐ00'00"`, - magnitude: 0, - constellation: 'AND', - distance: 0, - distanceUnit: 'ly', - illuminated: 0, - elongation: 0, - leading: false, -} - -export interface Twilight { - civilDusk: number[] - nauticalDusk: number[] - astronomicalDusk: number[] - night: number[] - astronomicalDawn: number[] - nauticalDawn: number[] - civilDawn: number[] -} - -export type MinorPlanetKind = 'ASTEROID' | 'COMET' - -export interface MinorPlanetSearchItem { - name: string - pdes: string -} - -export interface MinorPlanet { - found: boolean - name: string - spkId: number - kind?: MinorPlanetKind - pha: boolean - neo: boolean - orbitType: string - parameters: OrbitalPhysicalParameter[] - searchItems: MinorPlanetSearchItem[] -} - -export interface OrbitalPhysicalParameter { - name: string - description: string - value: string -} - -export interface CloseApproach { - name: string - designation: string - dateTime: number - distance: number - absoluteMagnitude: number -} - -export interface AstronomicalObject extends EquatorialCoordinateJ2000 { - id: number - name: string - magnitude: number -} - -export interface SpectralSkyObject { - spType: string -} - -export type Star = DeepSkyObject & SpectralSkyObject - -export interface OrientedSkyObject { - majorAxis: number - minorAxis: number - orientation: number -} - -export interface DeepSkyObject extends AstronomicalObject { - type: SkyObjectType - redshift: number - parallax: number - radialVelocity: number - distance: number - pmRA: number - pmDEC: number - constellation: Constellation -} - -export interface ComputedLocation extends EquatorialCoordinate, EquatorialCoordinateJ2000, HorizontalCoordinate { - constellation: Constellation - meridianAt: string - timeLeftToMeridianFlip: string - lst: string - pierSide: PierSide -} - -export const DEFAULT_COMPUTED_LOCATION: ComputedLocation = { - constellation: 'AND', - meridianAt: '00:00', - timeLeftToMeridianFlip: '00:00', - lst: '00:00', - pierSide: 'NEITHER', - rightAscensionJ2000: '00h00m00s', - declinationJ2000: `+000ยฐ00'00"`, - rightAscension: '00h00m00s', - declination: `+000ยฐ00'00"`, - azimuth: `000ยฐ00'00"`, - altitude: `+00ยฐ00'00"`, -} - export const SATELLITE_GROUPS = [ 'LAST_30_DAYS', 'STATIONS', @@ -507,29 +794,54 @@ export const SATELLITE_GROUPS = [ 'OTHER', ] as const -export type SatelliteGroupType = (typeof SATELLITE_GROUPS)[number] +export function searchFilterWithDefault(filter?: Partial, source: SkyObjectSearchFilter = DEFAULT_SKY_OBJECT_SEARCH_FILTER) { + if (!filter) return structuredClone(source) + filter.rightAscension ??= source.rightAscension + filter.declination ??= source.declination + filter.radius ||= source.radius + filter.constellation ??= source.constellation + filter.magnitude ??= source.magnitude + filter.type ??= source.type + return filter as SkyObjectSearchFilter +} -export interface Satellite { - id: number - name: string - tle: string - groups: SatelliteGroupType[] +export function satelliteSearchGroupsWithDefault(groups?: Partial, source: SatelliteSearchGroups = DEFAULT_SATELLITE_SEARCH_GROUPS) { + if (!groups) return structuredClone(source) + + if ('ACTIVE' in groups) { + for (const entry of Object.entries(source)) { + const key = entry[0] as SatelliteGroupType + groups[key] ??= source[key] + } + + return groups as SatelliteSearchGroups + } else { + return structuredClone(source) + } } -export interface Location { - id: number - name: string - latitude: number - longitude: number - elevation: number - offsetInMinutes: number +export function resetSatelliteSearchGroup(groups: SatelliteSearchGroups, source: SatelliteSearchGroups = DEFAULT_SATELLITE_SEARCH_GROUPS) { + for (const entry of Object.entries(source)) { + const key = entry[0] as SatelliteGroupType + groups[key] = source[key] + } } -export const DEFAULT_LOCATION: Location = { - id: 0, - name: 'Null Island', - latitude: 0, - longitude: 0, - elevation: 0, - offsetInMinutes: 0, +export function locationWithDefault(location?: Partial, source: Location = DEFAULT_LOCATION) { + if (!location) return structuredClone(source) + location.id ??= source.id + location.name ||= source.name + location.latitude ??= source.latitude + location.longitude ??= source.longitude + location.elevation ??= source.elevation + location.offsetInMinutes ??= source.offsetInMinutes + return location as Location +} + +export function skyAtlasPreferenceWithDefault(preference?: Partial, source: SkyAtlasPreference = DEFAULT_SKY_ATLAS_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.satellites = satelliteSearchGroupsWithDefault(preference.satellites, source.satellites) + preference.location = locationWithDefault(preference.location, source.location) + preference.fast ??= source.fast + return preference as SkyAtlasPreference } diff --git a/desktop/src/shared/types/settings.types.ts b/desktop/src/shared/types/settings.types.ts index c21133100..b75a777d9 100644 --- a/desktop/src/shared/types/settings.types.ts +++ b/desktop/src/shared/types/settings.types.ts @@ -1,5 +1,5 @@ import type { Location } from './atlas.types' -import { DEFAULT_LOCATION } from './atlas.types' +import { DEFAULT_LOCATION, locationWithDefault } from './atlas.types' import type { LiveStackerSettings, LiveStackerType } from './camera.types' import { cameraCaptureNamingFormatWithDefault, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, DEFAULT_LIVE_STACKER_SETTINGS, liveStackerSettingsWithDefault, type CameraCaptureNamingFormat, type FrameType } from './camera.types' import { DEFAULT_PLATE_SOLVER_SETTINGS, plateSolverSettingsWithDefault, type PlateSolverSettings, type PlateSolverType } from './platesolver.types' @@ -15,7 +15,7 @@ export interface SettingsPreference { stacker: Record namingFormat: CameraCaptureNamingFormat locations: Location[] - location: number // selected location index + location: Location } export const DEFAULT_SETTINGS_PREFERENCE: SettingsPreference = { @@ -40,7 +40,7 @@ export const DEFAULT_SETTINGS_PREFERENCE: SettingsPreference = { }, namingFormat: DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, locations: [DEFAULT_LOCATION], - location: 0, + location: DEFAULT_LOCATION, } export function settingsPreferenceWithDefault(preference?: Partial, source: SettingsPreference = DEFAULT_SETTINGS_PREFERENCE) { @@ -65,11 +65,10 @@ export function settingsPreferenceWithDefault(preference?: Partial Date: Wed, 7 Aug 2024 13:33:56 -0300 Subject: [PATCH 093/104] [api][desktop]: Refactor Mount Remote Control --- .../nebulosa/api/mounts/MountController.kt | 6 +-- .../nebulosa/api/mounts/MountRemoteControl.kt | 6 +-- ...lType.kt => MountRemoteControlProtocol.kt} | 2 +- .../nebulosa/api/mounts/MountService.kt | 12 ++--- desktop/src/app/mount/mount.component.html | 12 ++--- desktop/src/app/mount/mount.component.ts | 51 ++++++++----------- desktop/src/app/rotator/rotator.component.ts | 4 +- .../src/shared/pipes/dropdown-options.pipe.ts | 6 +-- desktop/src/shared/pipes/enum.pipe.ts | 4 +- desktop/src/shared/services/api.service.ts | 10 ++-- desktop/src/shared/types/mount.types.ts | 22 ++++++-- 11 files changed, 69 insertions(+), 66 deletions(-) rename api/src/main/kotlin/nebulosa/api/mounts/{MountRemoteControlType.kt => MountRemoteControlProtocol.kt} (59%) diff --git a/api/src/main/kotlin/nebulosa/api/mounts/MountController.kt b/api/src/main/kotlin/nebulosa/api/mounts/MountController.kt index da3b115e4..0ee2d8a3c 100644 --- a/api/src/main/kotlin/nebulosa/api/mounts/MountController.kt +++ b/api/src/main/kotlin/nebulosa/api/mounts/MountController.kt @@ -189,15 +189,15 @@ class MountController( @PutMapping("{mount}/remote-control/start") fun remoteControlStart( mount: Mount, - @RequestParam type: MountRemoteControlType, + @RequestParam protocol: MountRemoteControlProtocol, @RequestParam(required = false, defaultValue = "0.0.0.0") host: String, @RequestParam(required = false, defaultValue = "10001") @Valid @Positive port: Int, ) { - mountService.remoteControlStart(mount, type, host, port) + mountService.remoteControlStart(mount, protocol, host, port) } @PutMapping("{mount}/remote-control/stop") - fun remoteControlStart(mount: Mount, @RequestParam type: MountRemoteControlType) { + fun remoteControlStart(mount: Mount, @RequestParam type: MountRemoteControlProtocol) { mountService.remoteControlStop(mount, type) } diff --git a/api/src/main/kotlin/nebulosa/api/mounts/MountRemoteControl.kt b/api/src/main/kotlin/nebulosa/api/mounts/MountRemoteControl.kt index 15118bcb1..377afc9e0 100644 --- a/api/src/main/kotlin/nebulosa/api/mounts/MountRemoteControl.kt +++ b/api/src/main/kotlin/nebulosa/api/mounts/MountRemoteControl.kt @@ -18,7 +18,7 @@ import java.io.Closeable import java.time.OffsetDateTime data class MountRemoteControl( - @JvmField val type: MountRemoteControlType, + @JvmField val protocol: MountRemoteControlProtocol, @field:JsonIgnore @JvmField val server: NettyServer, @JvmField val mount: Mount, ) : StellariumMountHandler, LX200MountHandler, DeviceEventHandler, Closeable { @@ -28,8 +28,8 @@ data class MountRemoteControl( @JsonIgnore private val deviceProvider = mount.sender as? INDIDeviceProvider init { - if (server is StellariumProtocolServer) { - deviceProvider?.registerDeviceEventHandler(this) + if (server is StellariumProtocolServer && deviceProvider != null) { + deviceProvider.registerDeviceEventHandler(this) server.attachMountHandler(this) } else if (server is LX200ProtocolServer) { server.attachMountHandler(this) diff --git a/api/src/main/kotlin/nebulosa/api/mounts/MountRemoteControlType.kt b/api/src/main/kotlin/nebulosa/api/mounts/MountRemoteControlProtocol.kt similarity index 59% rename from api/src/main/kotlin/nebulosa/api/mounts/MountRemoteControlType.kt rename to api/src/main/kotlin/nebulosa/api/mounts/MountRemoteControlProtocol.kt index 9641863eb..a49a51581 100644 --- a/api/src/main/kotlin/nebulosa/api/mounts/MountRemoteControlType.kt +++ b/api/src/main/kotlin/nebulosa/api/mounts/MountRemoteControlProtocol.kt @@ -1,6 +1,6 @@ package nebulosa.api.mounts -enum class MountRemoteControlType { +enum class MountRemoteControlProtocol { STELLARIUM, LX200, } diff --git a/api/src/main/kotlin/nebulosa/api/mounts/MountService.kt b/api/src/main/kotlin/nebulosa/api/mounts/MountService.kt index 36d8b6069..876e6509e 100644 --- a/api/src/main/kotlin/nebulosa/api/mounts/MountService.kt +++ b/api/src/main/kotlin/nebulosa/api/mounts/MountService.kt @@ -288,19 +288,19 @@ class MountService( } } - fun remoteControlStart(mount: Mount, type: MountRemoteControlType, host: String, port: Int) { - check(remoteControls.none { it.mount === mount && it.type == type }) { "$type ${mount.name} Remote Control is already running" } + fun remoteControlStart(mount: Mount, protocol: MountRemoteControlProtocol, host: String, port: Int) { + check(remoteControls.none { it.mount === mount && it.protocol == protocol }) { "$protocol ${mount.name} Remote Control is already running" } - val server = if (type == MountRemoteControlType.STELLARIUM) StellariumProtocolServer(host, port) + val server = if (protocol == MountRemoteControlProtocol.STELLARIUM) StellariumProtocolServer(host, port) else LX200ProtocolServer(host, port) server.run() - remoteControls.add(MountRemoteControl(type, server, mount)) + remoteControls.add(MountRemoteControl(protocol, server, mount)) } - fun remoteControlStop(mount: Mount, type: MountRemoteControlType) { - val remoteControl = remoteControls.find { it.mount === mount && it.type == type } ?: return + fun remoteControlStop(mount: Mount, type: MountRemoteControlProtocol) { + val remoteControl = remoteControls.find { it.mount === mount && it.protocol == type } ?: return remoteControl.use(remoteControls::remove) } diff --git a/desktop/src/app/mount/mount.component.html b/desktop/src/app/mount/mount.component.html index c3bcd4512..153f63b0a 100644 --- a/desktop/src/app/mount/mount.component.html +++ b/desktop/src/app/mount/mount.component.html @@ -402,13 +402,13 @@
- +
@@ -435,7 +435,7 @@
- + Use together with the - + Use together with the
() private readonly computeTargetCoordinatePublisher = new Subject() private readonly computeCoordinateSubscriptions: Subscription[] = [] private readonly moveToDirection = [false, false] - readonly ephemerisModel: SlideMenuItem[] = [ + protected tracking = false + protected trackMode: TrackMode = 'SIDEREAL' + protected slewRate?: SlewRate + protected slewingDirection?: MountSlewDirection + + protected readonly ephemerisModel: SlideMenuItem[] = [ { icon: 'mdi mdi-image', label: 'Frame', @@ -61,7 +61,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Tickable { }, ] - readonly targetCoordinateModel: SlideMenuItem[] = [ + protected readonly targetCoordinateModel: SlideMenuItem[] = [ { icon: 'mdi mdi-telescope', label: 'Go To', @@ -203,14 +203,6 @@ export class MountComponent implements AfterContentInit, OnDestroy, Tickable { protected targetCoordinateCommand = this.targetCoordinateModel[0] - protected readonly remoteControl: MountRemoteControlDialog = { - showDialog: false, - type: 'LX200', - host: '0.0.0.0', - port: 10001, - data: [], - } - constructor( private readonly app: AppComponent, private readonly api: ApiService, @@ -299,8 +291,8 @@ export class MountComponent implements AfterContentInit, OnDestroy, Tickable { ngAfterContentInit() { this.route.queryParams.subscribe(async (e) => { - const mount = JSON.parse(decodeURIComponent(e['data'] as string)) as Mount - await this.mountChanged(mount) + const data = JSON.parse(decodeURIComponent(e['data'] as string)) as Mount + await this.mountChanged(data) this.ticker.register(this, 30000) }) } @@ -343,22 +335,22 @@ export class MountComponent implements AfterContentInit, OnDestroy, Tickable { } protected async showRemoteControlDialog() { - this.remoteControl.data = await this.api.mountRemoteControlList(this.mount) + this.remoteControl.controls = await this.api.mountRemoteControlList(this.mount) this.remoteControl.showDialog = true } protected async startRemoteControl() { try { - await this.api.mountRemoteControlStart(this.mount, this.remoteControl.type, this.remoteControl.host, this.remoteControl.port) - this.remoteControl.data = await this.api.mountRemoteControlList(this.mount) + await this.api.mountRemoteControlStart(this.mount, this.remoteControl.protocol, this.remoteControl.host, this.remoteControl.port) + this.remoteControl.controls = await this.api.mountRemoteControlList(this.mount) } catch { this.primeService.message('Failed to start remote control', 'error') } } - protected async stopRemoteControl(type: MountRemoteControlType) { - await this.api.mountRemoteControlStop(this.mount, type) - this.remoteControl.data = await this.api.mountRemoteControlList(this.mount) + protected async stopRemoteControl(protocol: MountRemoteControlProtocol) { + await this.api.mountRemoteControlStop(this.mount, protocol) + this.remoteControl.controls = await this.api.mountRemoteControlList(this.mount) } protected async goTo() { @@ -389,7 +381,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Tickable { } } - protected moveTo(direction: MoveDirectionType, pressed: boolean, event?: MouseEvent) { + protected moveTo(direction: MountSlewDirection, pressed: boolean, event?: MouseEvent) { if (!event || event.button === 0) { this.slewingDirection = pressed ? direction : undefined @@ -478,8 +470,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Tickable { protected async computeTargetCoordinates() { if (this.mount.connected) { const { targetRightAscension, targetDeclination, targetCoordinateType } = this.preference - const computedLocation = await this.api.mountComputeLocation(this.mount, targetCoordinateType === 'J2000', targetRightAscension, targetDeclination, true, true, true) - this.targetComputedLocation = computedLocation + Object.assign(this.targetComputedLocation, await this.api.mountComputeLocation(this.mount, targetCoordinateType === 'J2000', targetRightAscension, targetDeclination, true, true, true)) } } diff --git a/desktop/src/app/rotator/rotator.component.ts b/desktop/src/app/rotator/rotator.component.ts index 58e39976d..51c51ad4b 100644 --- a/desktop/src/app/rotator/rotator.component.ts +++ b/desktop/src/app/rotator/rotator.component.ts @@ -46,8 +46,8 @@ export class RotatorComponent implements AfterViewInit, OnDestroy, Tickable { ngAfterViewInit() { this.route.queryParams.subscribe(async (e) => { - const rotator = JSON.parse(decodeURIComponent(e['data'] as string)) as Rotator - await this.rotatorChanged(rotator) + const data = JSON.parse(decodeURIComponent(e['data'] as string)) as Rotator + await this.rotatorChanged(data) this.ticker.register(this, 30000) }) } diff --git a/desktop/src/shared/pipes/dropdown-options.pipe.ts b/desktop/src/shared/pipes/dropdown-options.pipe.ts index f1f51b59a..254c8e578 100644 --- a/desktop/src/shared/pipes/dropdown-options.pipe.ts +++ b/desktop/src/shared/pipes/dropdown-options.pipe.ts @@ -6,7 +6,7 @@ import { ExposureMode, FrameType, LiveStackerType } from '../types/camera.types' import { GuideDirection, GuiderPlotMode, GuiderYAxisUnit } from '../types/guider.types' import { ConnectionType } from '../types/home.types' import { Bitpix, IMAGE_STATISTICS_BIT_OPTIONS, ImageChannel, ImageFormat, ImageStatisticsBitOption, SCNRProtectionMethod } from '../types/image.types' -import { MountRemoteControlType } from '../types/mount.types' +import { MountRemoteControlProtocol } from '../types/mount.types' import { PlateSolverType } from '../types/platesolver.types' import { SequenceCaptureMode } from '../types/sequencer.types' import { SettingsTabKey } from '../types/settings.types' @@ -23,7 +23,7 @@ export interface DropdownOptions { IMAGE_FORMAT: ImageFormat[] IMAGE_BITPIX: Bitpix[] IMAGE_CHANNEL: ImageChannel[] - MOUNT_REMOTE_CONTROL_TYPE: MountRemoteControlType[] + MOUNT_REMOTE_CONTROL_PROTOCOL: MountRemoteControlProtocol[] FRAME_TYPE: FrameType[] EXPOSURE_MODE: ExposureMode[] GUIDE_DIRECTION: GuideDirection[] @@ -65,7 +65,7 @@ export class DropdownOptionsPipe implements PipeTransform { return ['BYTE', 'SHORT', 'INTEGER', 'FLOAT', 'DOUBLE'] as DropdownOptions[K] case 'IMAGE_CHANNEL': return ['RED', 'GREEN', 'BLUE', 'GRAY'] as DropdownOptions[K] - case 'MOUNT_REMOTE_CONTROL_TYPE': + case 'MOUNT_REMOTE_CONTROL_PROTOCOL': return ['LX200', 'STELLARIUM'] as DropdownOptions[K] case 'FRAME_TYPE': return ['LIGHT', 'DARK', 'FLAT', 'BIAS'] as DropdownOptions[K] diff --git a/desktop/src/shared/pipes/enum.pipe.ts b/desktop/src/shared/pipes/enum.pipe.ts index d3f3ecb63..5c5e26936 100644 --- a/desktop/src/shared/pipes/enum.pipe.ts +++ b/desktop/src/shared/pipes/enum.pipe.ts @@ -6,7 +6,7 @@ import { CameraCaptureState, ExposureMode, ExposureTimeUnit, FrameType, LiveStac import { FlatWizardState } from '../types/flat-wizard.types' import { GuideDirection, GuideState, GuiderPlotMode, GuiderYAxisUnit } from '../types/guider.types' import { Bitpix, ImageChannel, SCNRProtectionMethod } from '../types/image.types' -import { MountRemoteControlType } from '../types/mount.types' +import { MountRemoteControlProtocol } from '../types/mount.types' import { PlateSolverType } from '../types/platesolver.types' import { SequenceCaptureMode, SequencerState } from '../types/sequencer.types' import { SettingsTabKey } from '../types/settings.types' @@ -36,7 +36,7 @@ export type EnumPipeKey = | LiveStackerType | GuiderPlotMode | GuiderYAxisUnit - | MountRemoteControlType + | MountRemoteControlProtocol | SequenceCaptureMode | Bitpix | StackerType diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts index 3b26e3d1d..d8001862f 100644 --- a/desktop/src/shared/services/api.service.ts +++ b/desktop/src/shared/services/api.service.ts @@ -12,7 +12,7 @@ import { HipsSurvey } from '../types/framing.types' import { GuideDirection, GuideOutput, Guider, GuiderHistoryStep, SettleInfo } from '../types/guider.types' import { ConnectionStatus, ConnectionType } from '../types/home.types' import { AnnotateImageRequest, CoordinateInterpolation, DetectedStar, FOVCamera, FOVTelescope, ImageAnnotation, ImageInfo, ImageMousePosition, ImageSaveDialog, ImageSolved, ImageTransformation } from '../types/image.types' -import { CelestialLocationType, Mount, MountRemoteControl, MountRemoteControlType, SlewRate, TrackMode } from '../types/mount.types' +import { CelestialLocationType, Mount, MountRemoteControl, MountRemoteControlProtocol, SlewRate, TrackMode } from '../types/mount.types' import { PlateSolverRequest } from '../types/platesolver.types' import { Rotator } from '../types/rotator.types' import { SequencePlan } from '../types/sequencer.types' @@ -179,8 +179,8 @@ export class ApiService { return this.http.put(`mounts/${mount.id}/point-here?${query}`) } - mountRemoteControlStart(mount: Mount, type: MountRemoteControlType, host: string, port: number) { - const query = this.http.query({ type, host, port }) + mountRemoteControlStart(mount: Mount, protocol: MountRemoteControlProtocol, host: string, port: number) { + const query = this.http.query({ protocol, host, port }) return this.http.put(`mounts/${mount.id}/remote-control/start?${query}`) } @@ -188,8 +188,8 @@ export class ApiService { return this.http.get(`mounts/${mount.id}/remote-control`) } - mountRemoteControlStop(mount: Mount, type: MountRemoteControlType) { - const query = this.http.query({ type }) + mountRemoteControlStop(mount: Mount, protocol: MountRemoteControlProtocol) { + const query = this.http.query({ protocol }) return this.http.put(`mounts/${mount.id}/remote-control/stop?${query}`) } diff --git a/desktop/src/shared/types/mount.types.ts b/desktop/src/shared/types/mount.types.ts index f37ecc686..f88e21e4b 100644 --- a/desktop/src/shared/types/mount.types.ts +++ b/desktop/src/shared/types/mount.types.ts @@ -11,9 +11,13 @@ export type TrackMode = 'SIDEREAL' | ' LUNAR' | 'SOLAR' | 'KING' | 'CUSTOM' export type CelestialLocationType = 'ZENITH' | 'NORTH_POLE' | 'SOUTH_POLE' | 'GALACTIC_CENTER' | 'MERIDIAN_EQUATOR' | 'MERIDIAN_ECLIPTIC' | 'EQUATOR_ECLIPTIC' -export type MountRemoteControlType = 'LX200' | 'STELLARIUM' +export type MountRemoteControlProtocol = 'LX200' | 'STELLARIUM' -export type MoveDirectionType = 'N' | 'S' | 'W' | 'E' | 'NW' | 'NE' | 'SW' | 'SE' +export type CardinalDirection = 'N' | 'S' | 'W' | 'E' + +export type OrdinalDirection = 'NW' | 'NE' | 'SW' | 'SE' + +export type MountSlewDirection = CardinalDirection | OrdinalDirection export interface SlewRate { name: string @@ -43,7 +47,7 @@ export interface Mount extends EquatorialCoordinate, GPS, GuideOutput, Parkable } export interface MountRemoteControl { - type: MountRemoteControlType + protocol: MountRemoteControlProtocol mount: Mount running: boolean rightAscension: Angle @@ -59,10 +63,10 @@ export interface MountRemoteControl { export interface MountRemoteControlDialog { showDialog: boolean - type: MountRemoteControlType + protocol: MountRemoteControlProtocol host: string port: number - data: MountRemoteControl[] + controls: MountRemoteControl[] } export interface MountPreference { @@ -105,6 +109,14 @@ export const DEFAULT_MOUNT: Mount = { parked: false, } +export const DEFAULT_MOUNT_REMOTE_CONTROL_DIALOG: MountRemoteControlDialog = { + showDialog: false, + protocol: 'LX200', + host: '0.0.0.0', + port: 10001, + controls: [], +} + export const DEFAULT_MOUNT_PREFERENCE: MountPreference = { targetCoordinateType: 'JNOW', targetRightAscension: '00h00m00s', From 0496264e8c22c1e4c9146865398441e5a8a205d4 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Thu, 8 Aug 2024 23:56:56 -0300 Subject: [PATCH 094/104] [api][desktop]: Refactor Sequencer --- .../api/sequencer/SequenceCaptureMode.kt | 10 - .../api/sequencer/SequencerCaptureMode.kt | 10 + .../api/sequencer/SequencerController.kt | 2 +- .../api/sequencer/SequencerExecutor.kt | 2 +- ...PlanRequest.kt => SequencerPlanRequest.kt} | 6 +- .../api/sequencer/SequencerService.kt | 2 +- .../nebulosa/api/sequencer/SequencerTask.kt | 49 +- desktop/src/app/app.component.ts | 10 +- desktop/src/app/camera/camera.component.html | 3 +- desktop/src/app/camera/camera.component.ts | 194 ++++-- .../src/app/camera/exposure-time.component.ts | 36 +- .../app/filterwheel/filterwheel.component.ts | 10 +- desktop/src/app/image/image.component.html | 18 +- desktop/src/app/indi/indi.component.ts | 2 +- .../app/sequencer/sequencer.component.html | 150 ++--- .../src/app/sequencer/sequencer.component.ts | 598 +++++++++--------- .../camera-info/camera-info.component.html | 62 +- .../camera-info/camera-info.component.scss | 28 - .../camera-info/camera-info.component.ts | 10 +- .../path-chooser/path-chooser.component.ts | 3 +- desktop/src/shared/constants.ts | 2 + .../src/shared/pipes/dropdown-options.pipe.ts | 7 +- desktop/src/shared/pipes/enum.pipe.ts | 4 +- desktop/src/shared/pipes/exposureTime.pipe.ts | 2 +- desktop/src/shared/services/api.service.ts | 8 +- .../src/shared/services/preference.service.ts | 4 +- desktop/src/shared/types/angular.types.ts | 2 +- desktop/src/shared/types/camera.types.ts | 3 + desktop/src/shared/types/image.types.ts | 16 +- desktop/src/shared/types/sequencer.types.ts | 141 ++++- desktop/src/shared/types/settings.types.ts | 8 +- desktop/src/styles.scss | 8 + 32 files changed, 816 insertions(+), 594 deletions(-) delete mode 100644 api/src/main/kotlin/nebulosa/api/sequencer/SequenceCaptureMode.kt create mode 100644 api/src/main/kotlin/nebulosa/api/sequencer/SequencerCaptureMode.kt rename api/src/main/kotlin/nebulosa/api/sequencer/{SequencePlanRequest.kt => SequencerPlanRequest.kt} (84%) delete mode 100644 desktop/src/shared/components/camera-info/camera-info.component.scss diff --git a/api/src/main/kotlin/nebulosa/api/sequencer/SequenceCaptureMode.kt b/api/src/main/kotlin/nebulosa/api/sequencer/SequenceCaptureMode.kt deleted file mode 100644 index d58b34657..000000000 --- a/api/src/main/kotlin/nebulosa/api/sequencer/SequenceCaptureMode.kt +++ /dev/null @@ -1,10 +0,0 @@ -package nebulosa.api.sequencer - -enum class SequenceCaptureMode { - INTERLEAVED, - - /** - * Processes each sequence entry in full before advancing to the next sequence entry. - */ - FULLY, -} diff --git a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerCaptureMode.kt b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerCaptureMode.kt new file mode 100644 index 000000000..f865aae4a --- /dev/null +++ b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerCaptureMode.kt @@ -0,0 +1,10 @@ +package nebulosa.api.sequencer + +enum class SequencerCaptureMode { + INTERLEAVED, + + /** + * Processes each sequence in full before advancing to the next sequence. + */ + FULLY, +} diff --git a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerController.kt b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerController.kt index 4ffc3620f..d8d0478dd 100644 --- a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerController.kt +++ b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerController.kt @@ -18,7 +18,7 @@ class SequencerController( fun start( camera: Camera, mount: Mount?, wheel: FilterWheel?, focuser: Focuser?, rotator: Rotator?, - @RequestBody @Valid body: SequencePlanRequest, + @RequestBody @Valid body: SequencerPlanRequest, ) = sequencerService.start(camera, body, mount, wheel, focuser, rotator) @PutMapping("{camera}/stop") diff --git a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerExecutor.kt b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerExecutor.kt index e19e973dd..efd19c02c 100644 --- a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerExecutor.kt +++ b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerExecutor.kt @@ -54,7 +54,7 @@ class SequencerExecutor( } fun execute( - camera: Camera, request: SequencePlanRequest, + camera: Camera, request: SequencerPlanRequest, mount: Mount? = null, wheel: FilterWheel? = null, focuser: Focuser? = null, rotator: Rotator? = null, ) { check(camera.connected) { "${camera.name} Camera is not connected" } diff --git a/api/src/main/kotlin/nebulosa/api/sequencer/SequencePlanRequest.kt b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerPlanRequest.kt similarity index 84% rename from api/src/main/kotlin/nebulosa/api/sequencer/SequencePlanRequest.kt rename to api/src/main/kotlin/nebulosa/api/sequencer/SequencerPlanRequest.kt index 6aa50874a..3313353e8 100644 --- a/api/src/main/kotlin/nebulosa/api/sequencer/SequencePlanRequest.kt +++ b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerPlanRequest.kt @@ -13,12 +13,12 @@ import java.nio.file.Path import java.time.Duration import java.time.temporal.ChronoUnit -data class SequencePlanRequest( +data class SequencerPlanRequest( @JvmField @field:DurationUnit(ChronoUnit.SECONDS) @field:DurationMin(seconds = 0) @field:DurationMax(minutes = 60) val initialDelay: Duration = Duration.ZERO, - @JvmField val captureMode: SequenceCaptureMode = SequenceCaptureMode.INTERLEAVED, + @JvmField val captureMode: SequencerCaptureMode = SequencerCaptureMode.INTERLEAVED, @JvmField val autoSubFolderMode: AutoSubFolderMode = AutoSubFolderMode.OFF, @JvmField val savePath: Path? = null, - @JvmField @field:NotEmpty val entries: List = emptyList(), + @JvmField @field:NotEmpty val sequences: List = emptyList(), @JvmField @field:Valid val dither: DitherAfterExposureRequest = DitherAfterExposureRequest.DISABLED, @JvmField @field:Valid val autoFocus: AutoFocusAfterConditions = AutoFocusAfterConditions.DISABLED, @JvmField val namingFormat: CameraCaptureNamingFormat = CameraCaptureNamingFormat.DEFAULT, diff --git a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerService.kt b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerService.kt index b3b154d9f..1672a18d7 100644 --- a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerService.kt +++ b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerService.kt @@ -18,7 +18,7 @@ class SequencerService( @Synchronized fun start( - camera: Camera, request: SequencePlanRequest, + camera: Camera, request: SequencerPlanRequest, mount: Mount?, wheel: FilterWheel?, focuser: Focuser?, rotator: Rotator?, ) { val savePath = request.savePath diff --git a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerTask.kt b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerTask.kt index 90c20fa8d..31f1d2c37 100644 --- a/api/src/main/kotlin/nebulosa/api/sequencer/SequencerTask.kt +++ b/api/src/main/kotlin/nebulosa/api/sequencer/SequencerTask.kt @@ -35,7 +35,7 @@ import java.util.concurrent.atomic.AtomicReference data class SequencerTask( @JvmField val camera: Camera, - @JvmField val plan: SequencePlanRequest, + @JvmField val plan: SequencerPlanRequest, @JvmField val guider: Guider? = null, @JvmField val mount: Mount? = null, @JvmField val wheel: FilterWheel? = null, @@ -45,7 +45,7 @@ data class SequencerTask( private val calibrationFrameProvider: CalibrationFrameProvider? = null, ) : AbstractTask(), Consumer, CameraEventAware, WheelEventAware, PauseListener { - private val usedEntries = plan.entries.filter { it.enabled } + private val sequences = plan.sequences.filter { it.enabled } private val initialDelayTask = DelayTask(plan.initialDelay) @@ -63,7 +63,7 @@ data class SequencerTask( @Volatile private var progress = 0.0 init { - require(usedEntries.isNotEmpty()) { "no entries found" } + require(sequences.isNotEmpty()) { "no entries found" } initialDelayTask.subscribe(this) tasks.add(initialDelayTask) @@ -75,12 +75,12 @@ data class SequencerTask( namingFormat = plan.namingFormat, ) - if (plan.captureMode == SequenceCaptureMode.FULLY || usedEntries.size == 1) { - for (i in usedEntries.indices) { - val request = mapRequest(usedEntries[i]) + if (plan.captureMode == SequencerCaptureMode.FULLY || sequences.size == 1) { + for (i in sequences.indices) { + val request = mapRequest(sequences[i]) // ID. - tasks.add(SequencerIdTask(plan.entries.indexOfFirst { it === usedEntries[i] } + 1)) + tasks.add(SequencerIdTask(plan.sequences.indexOfFirst { it === sequences[i] } + 1)) // FILTER WHEEL. request.wheelMoveTask()?.also(tasks::add) @@ -94,23 +94,22 @@ data class SequencerTask( cameraCaptureTask.subscribe(this) estimatedCaptureTime += cameraCaptureTask.estimatedCaptureTime - tasks.add(SequenceCaptureModeCameraCaptureTask(cameraCaptureTask, SequenceCaptureMode.FULLY, i)) + tasks.add(SequenceCaptureModeCameraCaptureTask(cameraCaptureTask, SequencerCaptureMode.FULLY, i)) } } else { - val sequenceIdTasks = usedEntries.map { req -> SequencerIdTask(plan.entries.indexOfFirst { it === req } + 1) } - val requests = usedEntries.map { mapRequest(it) } - val cameraCaptureTasks = requests - .mapIndexed { i, req -> - val task = CameraCaptureTask( - camera, req, guider, - i > 0, executor, calibrationFrameProvider, - mount, wheel, focuser, rotator - ) - - SequenceCaptureModeCameraCaptureTask(task, SequenceCaptureMode.INTERLEAVED, i) - } + val sequenceIdTasks = sequences.map { req -> SequencerIdTask(plan.sequences.indexOfFirst { it === req } + 1) } + val requests = sequences.map { mapRequest(it) } + val cameraCaptureTasks = requests.mapIndexed { i, req -> + val task = CameraCaptureTask( + camera, req, guider, + i > 0, executor, calibrationFrameProvider, + mount, wheel, focuser, rotator + ) + + SequenceCaptureModeCameraCaptureTask(task, SequencerCaptureMode.INTERLEAVED, i) + } val wheelMoveTasks = requests.map { it.wheelMoveTask() } - val count = IntArray(requests.size) { usedEntries[it].exposureAmount } + val count = IntArray(requests.size) { sequences[it].exposureAmount } for ((cameraCaptureTask) in cameraCaptureTasks) { cameraCaptureTask.subscribe(this) @@ -118,14 +117,14 @@ data class SequencerTask( } while (count.sum() > 0) { - for (i in usedEntries.indices) { + for (i in sequences.indices) { if (count[i] > 0) { tasks.add(sequenceIdTasks[i]) wheelMoveTasks[i]?.also(tasks::add) val task = cameraCaptureTasks[i] - if (count[i] == usedEntries[i].exposureAmount) { + if (count[i] == sequences[i].exposureAmount) { tasks.add(InitializeCameraCaptureTask(task.task)) } @@ -273,12 +272,12 @@ data class SequencerTask( private data class SequenceCaptureModeCameraCaptureTask( @JvmField val task: CameraCaptureTask, - @JvmField val mode: SequenceCaptureMode, + @JvmField val mode: SequencerCaptureMode, @JvmField val index: Int, ) : Task { override fun execute(cancellationToken: CancellationToken) { - if (mode == SequenceCaptureMode.FULLY) { + if (mode == SequencerCaptureMode.FULLY) { task.initialize(cancellationToken) task.executeInLoop(cancellationToken) task.finalize(cancellationToken) diff --git a/desktop/src/app/app.component.ts b/desktop/src/app/app.component.ts index 2673cefce..1fbfd8a75 100644 --- a/desktop/src/app/app.component.ts +++ b/desktop/src/app/app.component.ts @@ -13,9 +13,11 @@ export class AppComponent implements OnDestroy { readonly maximizable = !!window.preference.resizable readonly modal = window.preference.modal ?? false readonly topMenu: MenuItem[] = [] + subTitle? = '' pinned = false showTopBar = true + beforeClose?: () => boolean | Promise private readonly resizeObserver?: ResizeObserver @@ -83,7 +85,11 @@ export class AppComponent implements OnDestroy { return this.electron.maximizeWindow() } - close(data?: unknown) { - return this.electron.closeWindow(data) + async close(data?: unknown, force: boolean = false) { + if (!this.beforeClose || (await this.beforeClose()) || force) { + return await this.electron.closeWindow(data) + } else { + return undefined + } } } diff --git a/desktop/src/app/camera/camera.component.html b/desktop/src/app/camera/camera.component.html index 2dfafe08c..f14507963 100644 --- a/desktop/src/app/camera/camera.component.html +++ b/desktop/src/app/camera/camera.component.html @@ -184,6 +184,7 @@ [canExposureTimeUnit]="canExposureTimeUnit" [min]="camera.exposureMin" [max]="camera.exposureMax" + [normalized]="mode !== 'CAPTURE'" (exposureTimeChange)="savePreference()" (unitChange)="savePreference()" class="w-full" /> @@ -468,7 +469,7 @@ diff --git a/desktop/src/app/camera/camera.component.ts b/desktop/src/app/camera/camera.component.ts index dd129a542..99f7e6255 100644 --- a/desktop/src/app/camera/camera.component.ts +++ b/desktop/src/app/camera/camera.component.ts @@ -22,7 +22,7 @@ import { FrameType, updateCameraStartCaptureFromCamera, } from '../../shared/types/camera.types' -import { Device } from '../../shared/types/device.types' +import { Device, DeviceType } from '../../shared/types/device.types' import { Focuser } from '../../shared/types/focuser.types' import { Mount } from '../../shared/types/mount.types' import { Rotator } from '../../shared/types/rotator.types' @@ -182,6 +182,10 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { return this.mode !== 'CAPTURE' } + get currentWheelFilter() { + return this.preference.wheel?.names[this.preference.wheel.position - 1] + } + constructor( private readonly app: AppComponent, private readonly api: ApiService, @@ -220,7 +224,7 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { }) electronService.on('MOUNT.UPDATED', (event) => { - if (event.device.id === this.preference.mount?.id) { + if (this.mode === 'CAPTURE' && event.device.id === this.preference.mount?.id) { ngZone.run(() => { if (this.preference.mount) { Object.assign(this.preference.mount, event.device) @@ -229,8 +233,24 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { } }) + electronService.on('MOUNT.ATTACHED', () => { + if (this.mode === 'CAPTURE') { + void ngZone.run(() => { + return this.loadEquipment('MOUNT') + }) + } + }) + + electronService.on('MOUNT.DETACHED', () => { + if (this.mode === 'CAPTURE') { + void ngZone.run(() => { + return this.loadEquipment('MOUNT') + }) + } + }) + electronService.on('WHEEL.UPDATED', (event) => { - if (event.device.id === this.preference.wheel?.id) { + if (this.mode === 'CAPTURE' && event.device.id === this.preference.wheel?.id) { ngZone.run(() => { if (this.preference.wheel) { Object.assign(this.preference.wheel, event.device) @@ -239,8 +259,24 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { } }) + electronService.on('WHEEL.ATTACHED', () => { + if (this.mode === 'CAPTURE') { + void ngZone.run(() => { + return this.loadEquipment('WHEEL') + }) + } + }) + + electronService.on('WHEEL.DETACHED', () => { + if (this.mode === 'CAPTURE') { + void ngZone.run(() => { + return this.loadEquipment('WHEEL') + }) + } + }) + electronService.on('FOCUSER.UPDATED', (event) => { - if (event.device.id === this.preference.focuser?.id) { + if (this.mode === 'CAPTURE' && event.device.id === this.preference.focuser?.id) { ngZone.run(() => { if (this.preference.focuser) { Object.assign(this.preference.focuser, event.device) @@ -249,8 +285,24 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { } }) + electronService.on('FOCUSER.ATTACHED', () => { + if (this.mode === 'CAPTURE') { + void ngZone.run(() => { + return this.loadEquipment('FOCUSER') + }) + } + }) + + electronService.on('FOCUSER.DETACHED', () => { + if (this.mode === 'CAPTURE') { + void ngZone.run(() => { + return this.loadEquipment('FOCUSER') + }) + } + }) + electronService.on('ROTATOR.UPDATED', (event) => { - if (event.device.id === this.preference.rotator?.id) { + if (this.mode === 'CAPTURE' && event.device.id === this.preference.rotator?.id) { ngZone.run(() => { if (this.preference.rotator) { Object.assign(this.preference.rotator, event.device) @@ -259,8 +311,24 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { } }) - electronService.on('CALIBRATION.CHANGED', async () => { - await ngZone.run(() => this.loadCalibrationGroups()) + electronService.on('ROTATOR.ATTACHED', () => { + if (this.mode === 'CAPTURE') { + void ngZone.run(() => { + return this.loadEquipment('ROTATOR') + }) + } + }) + + electronService.on('ROTATOR.DETACHED', () => { + if (this.mode === 'CAPTURE') { + void ngZone.run(() => { + return this.loadEquipment('ROTATOR') + }) + } + }) + + electronService.on('CALIBRATION.CHANGED', () => { + void ngZone.run(() => this.loadCalibrationGroups()) }) electronService.on('ROI.SELECTED', (event) => { @@ -359,15 +427,15 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { this.updateSubTitle() } - private async loadEquipment() { - const makeMenuItem = (selected: boolean, command: () => void, device?: Device) => { + private async loadEquipment(type?: DeviceType) { + const makeMenuItem = (selected: boolean, command: () => Promise | void, device?: Device) => { return { icon: device ? 'mdi mdi-connection' : 'mdi mdi-close', label: device?.name ?? 'None', selected, slideMenu: [], - command: (event: MenuItemCommandEvent) => { - command() + command: async (event: MenuItemCommandEvent) => { + await command() this.savePreference() event.parentItem?.slideMenu?.forEach((item) => (item.selected = item === event.item)) }, @@ -378,62 +446,102 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { // MOUNT - const mounts = await this.api.mounts() - this.preference.mount = mounts.find((e) => e.name === this.preference.mount?.name) + if (!type || type === 'MOUNT') { + menu[0].slideMenu.length = 0 - const makeMountItem = (mount?: Mount) => { - return makeMenuItem(this.preference.mount?.name === mount?.name, () => (this.preference.mount = mount), mount) - } + const mounts = await this.api.mounts() + this.preference.mount = mounts.find((e) => e.name === this.preference.mount?.name) - menu[0].slideMenu.push(makeMountItem()) + const makeMountItem = (mount?: Mount) => { + return makeMenuItem( + this.preference.mount?.name === mount?.name, + async () => { + this.preference.mount = mount && (await this.api.mount(mount.id)) + }, + mount, + ) + } - for (const mount of mounts) { - menu[0].slideMenu.push(makeMountItem(mount)) + menu[0].slideMenu.push(makeMountItem()) + + for (const mount of mounts) { + menu[0].slideMenu.push(makeMountItem(mount)) + } } // WHEEL - const wheels = await this.api.wheels() - this.preference.wheel = wheels.find((e) => e.name === this.preference.wheel?.name) + if (!type || type === 'WHEEL') { + menu[1].slideMenu.length = 0 - const makeWheelItem = (wheel?: Wheel) => { - return makeMenuItem(this.preference.wheel?.name === wheel?.name, () => (this.preference.wheel = wheel), wheel) - } + const wheels = await this.api.wheels() + this.preference.wheel = wheels.find((e) => e.name === this.preference.wheel?.name) - menu[1].slideMenu.push(makeWheelItem()) + const makeWheelItem = (wheel?: Wheel) => { + return makeMenuItem( + this.preference.wheel?.name === wheel?.name, + async () => { + this.preference.wheel = wheel && (await this.api.wheel(wheel.id)) + }, + wheel, + ) + } - for (const wheel of wheels) { - menu[1].slideMenu.push(makeWheelItem(wheel)) + menu[1].slideMenu.push(makeWheelItem()) + + for (const wheel of wheels) { + menu[1].slideMenu.push(makeWheelItem(wheel)) + } } // FOCUSER - const focusers = await this.api.focusers() - this.preference.focuser = focusers.find((e) => e.name === this.preference.focuser?.name) + if (!type || type === 'FOCUSER') { + menu[2].slideMenu.length = 0 - const makeFocuserItem = (focuser?: Focuser) => { - return makeMenuItem(this.preference.focuser?.name === focuser?.name, () => (this.preference.focuser = focuser), focuser) - } + const focusers = await this.api.focusers() + this.preference.focuser = focusers.find((e) => e.name === this.preference.focuser?.name) - menu[2].slideMenu.push(makeFocuserItem()) + const makeFocuserItem = (focuser?: Focuser) => { + return makeMenuItem( + this.preference.focuser?.name === focuser?.name, + async () => { + this.preference.focuser = focuser && (await this.api.focuser(focuser.id)) + }, + focuser, + ) + } + + menu[2].slideMenu.push(makeFocuserItem()) - for (const focuser of focusers) { - menu[2].slideMenu.push(makeFocuserItem(focuser)) + for (const focuser of focusers) { + menu[2].slideMenu.push(makeFocuserItem(focuser)) + } } // ROTATOR - const rotators = await this.api.rotators() - this.preference.rotator = rotators.find((e) => e.name === this.preference.rotator?.name) + if (!type || type === 'ROTATOR') { + menu[3].slideMenu.length = 0 - const makeRotatorItem = (rotator?: Rotator) => { - return makeMenuItem(this.preference.rotator?.name === rotator?.name, () => (this.preference.rotator = rotator), rotator) - } + const rotators = await this.api.rotators() + this.preference.rotator = rotators.find((e) => e.name === this.preference.rotator?.name) - menu[3].slideMenu.push(makeRotatorItem()) + const makeRotatorItem = (rotator?: Rotator) => { + return makeMenuItem( + this.preference.rotator?.name === rotator?.name, + async () => { + this.preference.rotator = rotator && (await this.api.rotator(rotator.id)) + }, + rotator, + ) + } + + menu[3].slideMenu.push(makeRotatorItem()) - for (const rotator of rotators) { - menu[3].slideMenu.push(makeRotatorItem(rotator)) + for (const rotator of rotators) { + menu[3].slideMenu.push(makeRotatorItem(rotator)) + } } } diff --git a/desktop/src/app/camera/exposure-time.component.ts b/desktop/src/app/camera/exposure-time.component.ts index 5fc16707d..d1ab3ecb8 100644 --- a/desktop/src/app/camera/exposure-time.component.ts +++ b/desktop/src/app/camera/exposure-time.component.ts @@ -10,13 +10,13 @@ import { ExposureTimeUnit } from '../../shared/types/camera.types' }) export class ExposureTimeComponent implements AfterViewInit, OnChanges { @Input({ required: true }) - protected readonly exposureTime: number = 0 + protected exposureTime: number = 0 @Output() readonly exposureTimeChange = new EventEmitter() @Input() - protected readonly unit: ExposureTimeUnit = 'MICROSECOND' + protected unit: ExposureTimeUnit = 'MICROSECOND' @Output() readonly unitChange = new EventEmitter() @@ -75,6 +75,8 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { }, ] + private exposureTimeInMicroseconds = 0 + ngOnChanges(changes: SimpleChanges) { for (const key in changes) { const change = changes[key] @@ -86,32 +88,33 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { this.exposureTimeUnitChanged(change.currentValue) break case 'exposureTime': - this.exposureTimeChanged(change.currentValue, 'MICROSECOND') + this.exposureTimeChanged(change.currentValue, 'MICROSECOND', this.normalized && this.exposureTimeInMicroseconds !== change.currentValue) break case 'min': case 'max': this.exposureTimeMinMaxChanged() break + case 'normalized': + this.normalize(this.exposureTime) + break } } } ngAfterViewInit() { - if (!this.normalize(this.exposureTime)) { - this.updateExposureTime(this.current.exposureTime, this.unit, this.unit) - } + this.updateExposureTime(this.current.exposureTime, this.unit, this.unit) } protected exposureTimeUnitChanged(value: ExposureTimeUnit) { - this.updateExposureTime(this.current.exposureTime, value, this.unit) + this.updateExposureTime(this.current.exposureTime, value, this.unit, false) } - protected exposureTimeChanged(value: number, from: ExposureTimeUnit = this.unit) { - this.updateExposureTime(value, this.unit, from) + protected exposureTimeChanged(value: number, from: ExposureTimeUnit = this.unit, normalize: boolean = false) { + this.updateExposureTime(value, this.unit, from, normalize) } protected exposureTimeMinMaxChanged() { - this.updateExposureTime(this.current.exposureTime, this.unit, this.unit) + this.updateExposureTime(this.current.exposureTime, this.unit, this.unit, false) } protected exposureTimeUnitWheeled(event: WheelEvent) { @@ -131,7 +134,7 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { } } - private updateExposureTime(value: number, unit: ExposureTimeUnit, from: ExposureTimeUnit) { + private updateExposureTime(value: number, unit: ExposureTimeUnit, from: ExposureTimeUnit, normalize: boolean = this.normalized) { const a = ExposureTimeComponent.exposureUnitFactor(from) const b = ExposureTimeComponent.exposureUnitFactor(unit) @@ -143,11 +146,20 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { const exposureTimeInMicroseconds = Math.trunc((this.current.exposureTime * 60000000) / b) + if (normalize) { + if (this.normalize(exposureTimeInMicroseconds)) { + return + } + } + if (this.exposureTime !== exposureTimeInMicroseconds) { + this.exposureTime = exposureTimeInMicroseconds + this.exposureTimeInMicroseconds = exposureTimeInMicroseconds this.exposureTimeChange.emit(exposureTimeInMicroseconds) } if (this.unit !== unit) { + this.unit = unit this.unitChange.emit(unit) } } @@ -169,7 +181,7 @@ export class ExposureTimeComponent implements AfterViewInit, OnChanges { // exposureTime is multiple of time. if (k === Math.floor(k)) { - this.updateExposureTime(exposureTime, unit, 'MICROSECOND') + this.updateExposureTime(exposureTime, unit, 'MICROSECOND', false) return true } } diff --git a/desktop/src/app/filterwheel/filterwheel.component.ts b/desktop/src/app/filterwheel/filterwheel.component.ts index fa98dfac6..3155597fc 100644 --- a/desktop/src/app/filterwheel/filterwheel.component.ts +++ b/desktop/src/app/filterwheel/filterwheel.component.ts @@ -351,13 +351,8 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab if (this.moving) return - const preference = this.preferenceService.wheel(this.wheel).get() - const filters = makeFilter(this.wheel, this.filters, preference.shutterPosition) - - if (filters !== this.filters) { - this.filters = filters - this.filter = filters[(this.filter?.position ?? this.position) - 1] ?? filters[0] - } + this.filters = makeFilter(this.wheel, this.filters, this.preference.shutterPosition) + this.filter = this.filters[(this.filter?.position ?? this.position) - 1] ?? this.filters[0] this.updateFocusOffset() } @@ -365,7 +360,6 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab private loadPreference() { if (this.mode === 'CAPTURE' && this.wheel.name) { Object.assign(this.preference, this.preferenceService.wheel(this.wheel).get()) - this.filters = makeFilter(this.wheel, this.filters, this.preference.shutterPosition) } } diff --git a/desktop/src/app/image/image.component.html b/desktop/src/app/image/image.component.html index 6f1c38e48..e0908e86d 100644 --- a/desktop/src/app/image/image.component.html +++ b/desktop/src/app/image/image.component.html @@ -142,7 +142,7 @@
Stars & DSOs
Minor Planets
@@ -186,7 +187,7 @@
+ @if (annotation.request.minorPlanetsMagLimit >= 20 || annotation.request.includeMinorPlanetsWithoutMagnitude) { +
+ + Can take a long time +
+ }

Minor planets Annotation uses the diff --git a/desktop/src/app/indi/indi.component.ts b/desktop/src/app/indi/indi.component.ts index b718a8b59..298d19fa7 100644 --- a/desktop/src/app/indi/indi.component.ts +++ b/desktop/src/app/indi/indi.component.ts @@ -81,7 +81,7 @@ export class INDIComponent implements AfterViewInit, OnDestroy { } }) - this.devices = [...(await this.api.cameras()), ...(await this.api.mounts()), ...(await this.api.focusers()), ...(await this.api.wheels())].sort(deviceComparator) + this.devices = [...(await this.api.cameras()), ...(await this.api.mounts()), ...(await this.api.focusers()), ...(await this.api.wheels()), ...(await this.api.rotators())].sort(deviceComparator) if (this.devices.length) { this.device = this.devices[0] diff --git a/desktop/src/app/sequencer/sequencer.component.html b/desktop/src/app/sequencer/sequencer.component.html index c6ddd1e9e..13ddc495a 100644 --- a/desktop/src/app/sequencer/sequencer.component.html +++ b/desktop/src/app/sequencer/sequencer.component.html @@ -18,7 +18,7 @@ locale="en" styleClass="p-inputtext-sm border-0" [allowEmpty]="false" - (ngModelChange)="savePlan()" + (ngModelChange)="savePreference()" spinnableNumber /> @@ -27,12 +27,12 @@ + (ngModelChange)="savePreference()" />

@@ -40,7 +40,7 @@ @@ -62,7 +62,7 @@ key="sequencer.savePath" [directory]="true" [(path)]="plan.savePath" - (pathChange)="savePlan()" + (pathChange)="savePreference()" class="w-full" />
@@ -76,7 +76,7 @@ [binary]="true" [disabled]="running" [(ngModel)]="plan.dither.enabled" - (ngModelChange)="savePlan()" /> + (ngModelChange)="savePreference()" />
@@ -86,7 +86,7 @@ [disabled]="running || !plan.dither.enabled" label="RA only" [(ngModel)]="plan.dither.raOnly" - (ngModelChange)="savePlan()" /> + (ngModelChange)="savePreference()" />
@@ -100,7 +100,7 @@ [step]="0.1" locale="en" [minFractionDigits]="1" - (ngModelChange)="savePlan()" + (ngModelChange)="savePreference()" spinnableNumber /> @@ -115,7 +115,7 @@ [max]="1000" [(ngModel)]="plan.dither.afterExposures" [step]="1" - (ngModelChange)="savePlan()" + (ngModelChange)="savePreference()" spinnableNumber /> @@ -131,7 +131,7 @@ [binary]="true" [disabled]="running" [(ngModel)]="plan.autoFocus.enabled" - (ngModelChange)="savePlan()" /> + (ngModelChange)="savePreference()" />
@@ -140,19 +140,19 @@ [disabled]="running || !plan.autoFocus.enabled" label="On start" [(ngModel)]="plan.autoFocus.onStart" - (ngModelChange)="savePlan()" /> + (ngModelChange)="savePreference()" /> + (ngModelChange)="savePreference()" />
+ (ngModelChange)="savePreference()" /> @@ -172,7 +172,7 @@ [binary]="true" [disabled]="running || !plan.autoFocus.enabled" [(ngModel)]="plan.autoFocus.afterExposuresEnabled" - (ngModelChange)="savePlan()" /> + (ngModelChange)="savePreference()" /> @@ -192,7 +192,7 @@ [binary]="true" [disabled]="running || !plan.autoFocus.enabled" [(ngModel)]="plan.autoFocus.afterTemperatureChangeEnabled" - (ngModelChange)="savePlan()" /> + (ngModelChange)="savePreference()" /> @@ -212,7 +212,7 @@ [binary]="true" [disabled]="running || !plan.autoFocus.enabled" [(ngModel)]="plan.autoFocus.afterHFDIncreaseEnabled" - (ngModelChange)="savePlan()" /> + (ngModelChange)="savePreference()" /> @@ -239,7 +239,7 @@ pInputText class="p-inputtext-sm border-0" [(ngModel)]="plan.namingFormat.light" - (ngModelChange)="savePlan()" /> + (ngModelChange)="savePreference()" /> + (ngModelChange)="savePreference()" /> + (ngModelChange)="savePreference()" /> + (ngModelChange)="savePreference()" />
@@ -382,7 +382,7 @@ cdkDropList (cdkDropListDropped)="drop($event)">
@@ -393,36 +393,36 @@
- + (onClick)="showCameraDialog(sequence)" size="small" /> -->
+ (click)="showSequenceMenu(sequence, entryMenu)" /> + (onClick)="deleteSequence(sequence, i)" /> + (onClick)="duplicateSequence(sequence, i)" /> + [(ngModel)]="sequence.enabled" + (ngModelChange)="savePreference()" />
+ [info]="sequence" + [wheel]="plan.wheel" + [canRemoveFilter]="sequence.enabled" + (filterRemoved)="filterRemoved(sequence)" />
@@ -481,7 +483,7 @@ [text]="true" /> } @else if (!running) {
@@ -530,96 +532,84 @@ [text]="true" icon="mdi mdi-checkbox-marked" label="Select All" - (onClick)="updateAllAvailableEntryPropertiesToApply(true)" /> + (onClick)="selectSequenceProperty(true)" /> + (onClick)="selectSequenceProperty(false)" />
+ [(ngModel)]="property.properties.EXPOSURE_TIME" />
+ [(ngModel)]="property.properties.EXPOSURE_AMOUNT" />
+ [(ngModel)]="property.properties.EXPOSURE_DELAY" />
+ [(ngModel)]="property.properties.FRAME_TYPE" />
+ [(ngModel)]="property.properties.X" />
+ [(ngModel)]="property.properties.Y" />
+ [(ngModel)]="property.properties.WIDTH" />
+ [(ngModel)]="property.properties.HEIGHT" />
+ [(ngModel)]="property.properties.BIN" />
+ [(ngModel)]="property.properties.FRAME_FORMAT" />
+ [(ngModel)]="property.properties.GAIN" />
+ [(ngModel)]="property.properties.OFFSET" />
@@ -628,11 +618,11 @@ icon="mdi mdi-check" label="Apply" size="small" - (onClick)="applyCameraStartCaptureToEntries()" /> + (onClick)="copySequencePropertyToSequencies()" />
diff --git a/desktop/src/app/sequencer/sequencer.component.ts b/desktop/src/app/sequencer/sequencer.component.ts index 8ff97e04c..74fa18ca3 100644 --- a/desktop/src/app/sequencer/sequencer.component.ts +++ b/desktop/src/app/sequencer/sequencer.component.ts @@ -1,8 +1,9 @@ import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop' import { AfterContentInit, Component, HostListener, NgZone, OnDestroy, QueryList, ViewChildren, ViewEncapsulation } from '@angular/core' +import { dirname } from 'path' import { CameraExposureComponent } from '../../shared/components/camera-exposure/camera-exposure.component' import { DialogMenuComponent } from '../../shared/components/dialog-menu/dialog-menu.component' -import { SlideMenuItem } from '../../shared/components/menu-item/menu-item.component' +import { MenuItem, SlideMenuItem } from '../../shared/components/menu-item/menu-item.component' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' @@ -10,21 +11,18 @@ import { PreferenceService } from '../../shared/services/preference.service' import { PrimeService } from '../../shared/services/prime.service' import { Tickable, Ticker } from '../../shared/services/ticker.service' import { JsonFile } from '../../shared/types/app.types' -import { Camera, CameraCaptureEvent, CameraStartCapture, DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, FrameType, updateCameraStartCaptureFromCamera } from '../../shared/types/camera.types' +import { Camera, cameraCaptureNamingFormatWithDefault, FrameType, updateCameraStartCaptureFromCamera } from '../../shared/types/camera.types' import { Focuser } from '../../shared/types/focuser.types' import { Mount } from '../../shared/types/mount.types' import { Rotator } from '../../shared/types/rotator.types' -import { DEFAULT_SEQUENCE_PLAN, SEQUENCE_ENTRY_PROPERTIES, SequenceCaptureMode, SequenceEntryProperty, SequencePlan, SequencerEvent } from '../../shared/types/sequencer.types' +import { DEFAULT_SEQUENCE, DEFAULT_SEQUENCE_PROPERTY_DIALOG, DEFAULT_SEQUENCER_PLAN, DEFAULT_SEQUENCER_PREFERENCE, Sequence, SequenceProperty, SequencerEvent, SequencerPlan } from '../../shared/types/sequencer.types' import { resetCameraCaptureNamingFormat } from '../../shared/types/settings.types' import { Wheel } from '../../shared/types/wheel.types' import { deviceComparator } from '../../shared/utils/comparators' -import { Undefinable } from '../../shared/utils/types' import { AppComponent } from '../app.component' import { CameraComponent } from '../camera/camera.component' import { FilterWheelComponent } from '../filterwheel/filterwheel.component' -export const SEQUENCER_SAVED_PATH_KEY = 'sequencer.savedPath' - @Component({ selector: 'neb-sequencer', templateUrl: './sequencer.component.html', @@ -32,33 +30,27 @@ export const SEQUENCER_SAVED_PATH_KEY = 'sequencer.savedPath' encapsulation: ViewEncapsulation.None, }) export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable { - cameras: Camera[] = [] - mounts: Mount[] = [] - wheels: Wheel[] = [] - focusers: Focuser[] = [] - rotators: Rotator[] = [] - - camera?: Camera - mount?: Mount - wheel?: Wheel - focuser?: Focuser - rotator?: Rotator - - readonly captureModes: SequenceCaptureMode[] = ['FULLY', 'INTERLEAVED'] - readonly plan = structuredClone(DEFAULT_SEQUENCE_PLAN) - - private entryToApply?: CameraStartCapture - private entryToApplyCount: [number, number] = [0, 0] - readonly availableEntryPropertiesToApply = new Map() - showEntryPropertiesToApplyDialog = false - readonly entryMenuModel: SlideMenuItem[] = [ + protected cameras: Camera[] = [] + protected mounts: Mount[] = [] + protected wheels: Wheel[] = [] + protected focusers: Focuser[] = [] + protected rotators: Rotator[] = [] + + protected readonly property = structuredClone(DEFAULT_SEQUENCE_PROPERTY_DIALOG) + protected readonly preference = structuredClone(DEFAULT_SEQUENCER_PREFERENCE) + protected plan = this.preference.plan + protected event?: SequencerEvent + protected running = false + + // NOTE: Remove the "plan.sequences.length <= 1" on layout if add more options + protected readonly sequenceModel: SlideMenuItem[] = [ { icon: 'mdi mdi-content-copy', label: 'Apply to all', slideMenu: [], command: () => { - this.entryToApplyCount = [-1000, 1000] - this.showEntryPropertiesToApplyDialog = true + this.property.count = [-1000, 1000] + this.property.showDialog = true }, }, { @@ -66,8 +58,8 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable label: 'Apply to all above', slideMenu: [], command: () => { - this.entryToApplyCount = [-1000, 0] - this.showEntryPropertiesToApplyDialog = true + this.property.count = [-1000, 0] + this.property.showDialog = true }, }, { @@ -75,8 +67,8 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable label: 'Apply to above', slideMenu: [], command: () => { - this.entryToApplyCount = [-1, 0] - this.showEntryPropertiesToApplyDialog = true + this.property.count = [-1, 0] + this.property.showDialog = true }, }, { @@ -84,8 +76,8 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable label: 'Apply to below', slideMenu: [], command: () => { - this.entryToApplyCount = [1, 0] - this.showEntryPropertiesToApplyDialog = true + this.property.count = [1, 0] + this.property.showDialog = true }, }, { @@ -93,104 +85,103 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable label: 'Apply to all below', slideMenu: [], command: () => { - this.entryToApplyCount = [1000, 0] - this.showEntryPropertiesToApplyDialog = true + this.property.count = [1000, 0] + this.property.showDialog = true }, }, ] - readonly sequenceEvents: CameraCaptureEvent[] = [] + private readonly createNewMenuItem: MenuItem = { + icon: 'mdi mdi-plus', + label: 'Create new', + command: () => { + this.preference.loadPath = undefined + this.savePreference() + + this.app.subTitle = undefined + this.saveMenuItem.visible = false + this.saveMenuItem.disabled = true + + if (!this.loadPlan(structuredClone(DEFAULT_SEQUENCER_PLAN))) { + this.add() + } + }, + } + + private readonly saveMenuItem: MenuItem = { + icon: 'mdi mdi-content-save', + label: 'Save', + visible: false, + command: () => this.savePlanToJson(false), + } + + private readonly saveAsMenuItem: MenuItem = { + icon: 'mdi mdi-content-save-edit', + label: 'Save as', + command: () => this.savePlanToJson(true), + } - event?: SequencerEvent - running = false + private readonly loadMenuItem: MenuItem = { + icon: 'mdi mdi-folder-open', + label: 'Load', + command: async () => { + const defaultPath = this.preference.loadPath ? dirname(this.preference.loadPath) : undefined + const file = await this.electronService.openJson({ defaultPath }) + + if (file !== false) { + this.loadPlanFromJson(file) + } + }, + } @ViewChildren('cameraExposure') private readonly cameraExposures!: QueryList get canStart() { - return !!this.camera && this.camera.connected && !!this.plan.entries.find((e) => e.enabled) + return !!this.plan.camera?.connected && !!this.plan.sequences.find((e) => e.enabled) } get pausingOrPaused() { return this.event?.state === 'PAUSING' || this.event?.state === 'PAUSED' } - get savedPath() { - return this.app.subTitle - } - - set savedPath(value: Undefinable) { - this.app.subTitle = value - } - constructor( private readonly app: AppComponent, private readonly api: ApiService, - private readonly browserWindow: BrowserWindowService, - private readonly electron: ElectronService, - private readonly preference: PreferenceService, - private readonly prime: PrimeService, + private readonly browserWindowService: BrowserWindowService, + private readonly electronService: ElectronService, + private readonly preferenceService: PreferenceService, + private readonly primeService: PrimeService, private readonly ticker: Ticker, ngZone: NgZone, ) { app.title = 'Sequencer' - app.topMenu.push({ - icon: 'mdi mdi-plus', - label: 'Create new', - command: () => { - this.updateSavedPath() + app.topMenu.push(this.createNewMenuItem) + app.topMenu.push(this.saveMenuItem) + app.topMenu.push(this.saveAsMenuItem) + app.topMenu.push(this.loadMenuItem) - Object.assign(this.plan, structuredClone(DEFAULT_SEQUENCE_PLAN)) - this.add() - }, - }) - app.topMenu.push({ - icon: 'mdi mdi-content-save', - label: 'Save', - command: async () => { - const file = await electron.saveJson({ path: this.savedPath, json: this.plan }) - - if (file !== false) { - this.afterSavedJsonFile(file) - } - }, - }) - app.topMenu.push({ - icon: 'mdi mdi-content-save-edit', - label: 'Save as', - command: async () => { - const file = await electron.saveJson({ json: this.plan }) - - if (file !== false) { - this.afterSavedJsonFile(file) - } - }, - }) - app.topMenu.push({ - icon: 'mdi mdi-folder-open', - label: 'Load', - command: async () => { - const file = await electron.openJson() - - if (file !== false) { - this.loadSavedJsonFile(file) - } - }, - }) + app.beforeClose = async () => { + if (!this.saveMenuItem.disabled) { + return !(await primeService.confirm('Are you sure you want to close the window? Please make sure to save before exiting to avoid losing any important changes.')) + } else { + return true + } + } - electron.on('CAMERA.UPDATED', (event) => { + electronService.on('CAMERA.UPDATED', (event) => { const camera = this.cameras.find((e) => e.id === event.device.id) if (camera) { ngZone.run(() => { Object.assign(camera, event.device) - this.updateEntriesFromCamera(this.camera) + this.updateSequencesFromCamera(camera) }) } }) - electron.on('MOUNT.UPDATED', (event) => { + electronService.on('MOUNT.UPDATED', (event) => { const mount = this.mounts.find((e) => e.id === event.device.id) if (mount) { @@ -200,7 +191,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable } }) - electron.on('WHEEL.UPDATED', (event) => { + electronService.on('WHEEL.UPDATED', (event) => { const wheel = this.wheels.find((e) => e.id === event.device.id) if (wheel) { @@ -210,7 +201,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable } }) - electron.on('FOCUSER.UPDATED', (event) => { + electronService.on('FOCUSER.UPDATED', (event) => { const focuser = this.focusers.find((e) => e.id === event.device.id) if (focuser) { @@ -220,7 +211,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable } }) - electron.on('ROTATOR.UPDATED', (event) => { + electronService.on('ROTATOR.UPDATED', (event) => { const rotator = this.rotators.find((e) => e.id === event.device.id) if (rotator) { @@ -230,7 +221,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable } }) - electron.on('SEQUENCER.ELAPSED', (event) => { + electronService.on('SEQUENCER.ELAPSED', (event) => { ngZone.run(() => { if (this.running !== event.remainingTime > 0) { this.enableOrDisableTopbarMenu(event.remainingTime <= 0) @@ -247,10 +238,6 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable } }) }) - - for (const p of SEQUENCE_ENTRY_PROPERTIES) { - this.availableEntryPropertiesToApply.set(p, true) - } } async ngAfterContentInit() { @@ -262,9 +249,9 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable this.focusers = (await this.api.focusers()).sort(deviceComparator) this.rotators = (await this.api.rotators()).sort(deviceComparator) - await this.loadSavedJsonFileFromPathOrAddDefault() + this.loadPreference() - // this.route.queryParams.subscribe(e => { }) + await this.loadPlanFromPath() } @HostListener('window:unload') @@ -273,141 +260,128 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable } async tick() { - if (this.camera?.id) await this.api.cameraListen(this.camera) - if (this.mount?.id) await this.api.mountListen(this.mount) - if (this.focuser?.id) await this.api.focuserListen(this.focuser) - if (this.wheel?.id) await this.api.wheelListen(this.wheel) - if (this.rotator?.id) await this.api.rotatorListen(this.rotator) + if (this.plan.camera?.id) await this.api.cameraListen(this.plan.camera) + if (this.plan.mount?.id) await this.api.mountListen(this.plan.mount) + if (this.plan.focuser?.id) await this.api.focuserListen(this.plan.focuser) + if (this.plan.wheel?.id) await this.api.wheelListen(this.plan.wheel) + if (this.plan.rotator?.id) await this.api.rotatorListen(this.plan.rotator) } private enableOrDisableTopbarMenu(enable: boolean) { this.app.topMenu.forEach((e) => (e.disabled = !enable)) } - add() { - const camera = this.camera ?? (this.cameras[0] as Undefinable) - // const wheel = this.wheel ?? this.wheels[0] - // const focuser = this.focuser ?? this.focusers[0] - // const rotator = this.rotator ?? this.rotators[0] + protected add() { + const camera = this.plan.camera - this.plan.entries.push({ - enabled: true, - exposureTime: 1000000, - exposureAmount: 1, - exposureDelay: 0, + const sequence: Sequence = { + ...structuredClone(DEFAULT_SEQUENCE), x: camera?.minX ?? 0, y: camera?.minY ?? 0, width: camera?.maxWidth ?? 0, height: camera?.maxHeight ?? 0, - frameType: 'LIGHT', - binX: 1, - binY: 1, - gain: 0, - offset: 0, frameFormat: camera?.frameFormats[0], - autoSave: true, - autoSubFolderMode: 'OFF', - filterPosition: 0, - shutterPosition: 0, - focusOffset: 0, - dither: { - enabled: false, - amount: 0, - raOnly: false, - afterExposures: 0, - }, - liveStacking: { - enabled: false, - type: 'SIRIL', - executablePath: '', - use32Bits: false, - slot: 1, - }, - namingFormat: this.plan.namingFormat, - }) + } - this.savePlan() - } + if (camera?.connected) { + updateCameraStartCaptureFromCamera(sequence, camera) + } - drop(event: CdkDragDrop) { - moveItemInArray(this.plan.entries, event.previousIndex, event.currentIndex) + this.plan.sequences.push(sequence) + + this.savePreference() } - private afterSavedJsonFile(file: JsonFile) { - if (file.path) { - this.updateSavedPath(file.path) + protected drop(event: CdkDragDrop) { + if (event.previousIndex !== event.currentIndex) { + moveItemInArray(this.plan.sequences, event.previousIndex, event.currentIndex) + this.savePreference() } } - private loadSavedJsonFile(file: JsonFile) { - if (this.loadPlan(file.json)) { - this.afterSavedJsonFile(file) - } else { - this.prime.message(`No entry found for the saved Sequence at: ${file.path}`, 'warn') - + private loadPlanFromJson(file: JsonFile) { + if (!this.loadPlan(file.json)) { + this.primeService.message(`No sequence found`, 'warn') this.add() } - } - private async loadSavedJsonFileFromPathOrAddDefault() { - const sequencerPreference = this.preference.sequencerPreference.get() + this.preference.loadPath = file.path + this.savePreference() + + this.app.subTitle = file.path + this.saveMenuItem.visible = !!file.path + this.saveMenuItem.disabled = true + } - if (sequencerPreference.savedPath) { - const file = await this.electron.readJson(sequencerPreference.savedPath) + private async loadPlanFromPath() { + if (this.preference.loadPath) { + const file = await this.electronService.readJson(this.preference.loadPath) - if (file !== false) { - this.loadSavedJsonFile(file) + if (file !== false && file.path) { + this.loadPlanFromJson(file) return } - this.prime.message(`Failed to load the saved Sequence at: ${sequencerPreference.savedPath}`, 'error') + this.primeService.message(`Failed to load the file`, 'error') - sequencerPreference.savedPath = undefined - this.preference.sequencerPreference.set(sequencerPreference) + this.preference.loadPath = undefined + this.savePreference() } - if (!this.loadPlan()) { + this.saveMenuItem.visible = false + + if (!this.loadPlan(this.plan)) { this.add() } } - private updateSavedPath(savedPath?: string) { - this.savedPath = savedPath - const sequencerPreference = this.preference.sequencerPreference.get() - sequencerPreference.savedPath = savedPath - this.preference.sequencerPreference.set(sequencerPreference) - } + private loadPlan(plan: SequencerPlan) { + if (this.plan !== plan) { + Object.assign(this.plan, plan) + } - private loadPlan(plan?: SequencePlan) { - const sequencerPreference = this.preference.sequencerPreference.get() + this.plan.camera = this.cameras.find((e) => e.id === plan.camera?.id) + this.plan.mount = this.mounts.find((e) => e.id === plan.mount?.id) + this.plan.wheel = this.wheels.find((e) => e.id === plan.wheel?.id) + this.plan.focuser = this.focusers.find((e) => e.id === plan.focuser?.id) + this.plan.rotator = this.rotators.find((e) => e.id === plan.rotator?.id) - plan ??= sequencerPreference.plan + const settings = this.preferenceService.settings.get() + cameraCaptureNamingFormatWithDefault(this.plan.namingFormat, settings.namingFormat) - if (this.plan !== plan) { - Object.assign(this.plan, structuredClone(plan)) - } + return this.plan.sequences.length + } - this.camera = this.cameras.find((e) => e.id === this.plan.camera) ?? this.cameras[0] - this.mount = this.mounts.find((e) => e.id === this.plan.mount) ?? this.mounts[0] - this.wheel = this.wheels.find((e) => e.id === this.plan.wheel) ?? this.wheels[0] - this.focuser = this.focusers.find((e) => e.id === this.plan.focuser) ?? this.focusers[0] - this.rotator = this.rotators.find((e) => e.id === this.plan.rotator) ?? this.rotators[0] + private async savePlanToJson(createNew: boolean) { + const path = createNew ? undefined : this.preference.loadPath + const file = await this.electronService.saveJson({ json: this.plan, path }) - const settings = this.preference.settings.get() - this.plan.namingFormat.light ??= settings.namingFormat.light || DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.light - this.plan.namingFormat.dark ??= settings.namingFormat.dark || DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.dark - this.plan.namingFormat.flat ??= settings.namingFormat.flat || DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.flat - this.plan.namingFormat.bias ??= settings.namingFormat.bias || DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT.bias + if (file !== false) { + this.preference.loadPath = file.path + this.savePreference() - return this.plan.entries.length + this.app.subTitle = file.path + this.saveMenuItem.disabled = true + } } - resetCameraCaptureNamingFormat(type: FrameType) { - resetCameraCaptureNamingFormat(type, this.plan.namingFormat, this.preference.settings.get().namingFormat) - this.savePlan() + protected resetCameraCaptureNamingFormat(type?: FrameType) { + const settings = this.preferenceService.settings.get() + const cameraNamingFormat = this.plan.camera?.id ? this.preferenceService.camera(this.plan.camera).get().request.namingFormat : settings.namingFormat + + if (type) { + resetCameraCaptureNamingFormat(type, this.plan.namingFormat, cameraNamingFormat) + } else { + resetCameraCaptureNamingFormat('LIGHT', this.plan.namingFormat, cameraNamingFormat) + resetCameraCaptureNamingFormat('DARK', this.plan.namingFormat, cameraNamingFormat) + resetCameraCaptureNamingFormat('FLAT', this.plan.namingFormat, cameraNamingFormat) + resetCameraCaptureNamingFormat('BIAS', this.plan.namingFormat, cameraNamingFormat) + } + + this.savePreference() } - toggleAutoSubFolder() { + protected toggleAutoSubFolder() { if (!this.running) { switch (this.plan.autoSubFolderMode) { case 'OFF': @@ -421,175 +395,197 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable break } - this.savePlan() + this.savePreference() } } - async showCameraDialog(entry: CameraStartCapture) { - if (this.camera && (await CameraComponent.showAsDialog(this.browserWindow, 'SEQUENCER', this.camera, entry))) { - this.savePlan() + protected async showCameraDialog(sequence: Sequence) { + if (this.plan.camera && (await CameraComponent.showAsDialog(this.browserWindowService, 'SEQUENCER', this.plan.camera, sequence))) { + this.savePreference() } } - async showWheelDialog(entry: CameraStartCapture) { - if (this.wheel && (await FilterWheelComponent.showAsDialog(this.browserWindow, 'SEQUENCER', this.wheel, entry))) { - this.savePlan() + protected async showWheelDialog(sequence: Sequence) { + if (this.plan.wheel && (await FilterWheelComponent.showAsDialog(this.browserWindowService, 'SEQUENCER', this.plan.wheel, sequence))) { + this.savePreference() } } - async cameraChanged() { - await this.tick() - - this.updateEntriesFromCamera(this.camera) - } - - private updateEntriesFromCamera(camera?: Camera) { + private updateSequencesFromCamera(camera?: Camera) { if (camera?.connected) { - for (const entry of this.plan.entries) { - updateCameraStartCaptureFromCamera(entry, camera) + for (const sequence of this.plan.sequences) { + updateCameraStartCaptureFromCamera(sequence, camera) } } } - mountChanged() { - return this.tick() + protected async cameraChanged() { + if (this.plan.camera) { + await this.api.cameraListen(this.plan.camera) + this.updateSequencesFromCamera(this.plan.camera) + } + + this.savePreference() } - focuserChanged() { - return this.tick() + protected async mountChanged() { + if (this.plan.mount) { + await this.api.mountListen(this.plan.mount) + } + + this.savePreference() } - wheelChanged() { - return this.tick() + protected async focuserChanged() { + if (this.plan.focuser) { + await this.api.focuserListen(this.plan.focuser) + } + + this.savePreference() } - rotatorChanged() { - return this.tick() + protected async wheelChanged() { + if (this.plan.wheel) { + await this.api.wheelListen(this.plan.wheel) + } + + this.savePreference() } - savePlan() { - const sequencerPreference = this.preference.sequencerPreference.get() - sequencerPreference.savedPath = this.savedPath - this.plan.camera = this.camera?.id - this.plan.mount = this.mount?.id - this.plan.wheel = this.wheel?.id - this.plan.focuser = this.focuser?.id - this.plan.rotator = this.rotator?.id - Object.assign(sequencerPreference.plan, this.plan) - this.preference.sequencerPreference.set(sequencerPreference) + protected async rotatorChanged() { + if (this.plan.rotator) { + await this.api.rotatorListen(this.plan.rotator) + } + + this.savePreference() } - showEntryMenu(entry: CameraStartCapture, dialogMenu: DialogMenuComponent) { - this.entryToApply = entry - const index = this.plan.entries.indexOf(entry) + protected showSequenceMenu(sequence: Sequence, dialogMenu: DialogMenuComponent) { + this.property.sequence = sequence - this.entryMenuModel.forEach((e) => (e.visible = true)) + const index = this.plan.sequences.indexOf(sequence) + const lastIndex = this.plan.sequences.length - 1 - if (index === 0 || this.plan.entries.length === 1) { - // Hides all above and above. - this.entryMenuModel[1].visible = false - this.entryMenuModel[2].visible = false - } else if (index === 1) { - // Hides all above. - this.entryMenuModel[1].visible = false - } + this.sequenceModel[1].visible = index >= 2 // ALL ABOBE + this.sequenceModel[2].visible = index >= 1 // ABOBE + this.sequenceModel[3].visible = index < lastIndex // BELOW + this.sequenceModel[4].visible = index < lastIndex - 1 // ALL BELOW + this.sequenceModel[0].visible = this.sequenceModel[2].visible && this.sequenceModel[3].visible - if (index === this.plan.entries.length - 1 || this.plan.entries.length === 1) { - // Hides below and all below. - this.entryMenuModel[3].visible = false - this.entryMenuModel[4].visible = false - } else if (index === this.plan.entries.length - 2) { - // Hides all below. - this.entryMenuModel[4].visible = false + if (this.sequenceModel.find((e) => e.visible)) { + dialogMenu.show() } - - dialogMenu.show() } - updateAllAvailableEntryPropertiesToApply(selected: boolean) { - for (const p of SEQUENCE_ENTRY_PROPERTIES) { - this.availableEntryPropertiesToApply.set(p, selected) + protected selectSequenceProperty(selected: boolean) { + for (const [key] of Object.entries(this.property.properties)) { + this.property.properties[key as SequenceProperty] = selected } } - applyCameraStartCaptureToEntries() { - const source = this.entryToApply + protected copySequencePropertyToSequencies() { + const source = this.property.sequence + if (!source) return - const index = this.plan.entries.indexOf(source) - for (let count of this.entryToApplyCount) { + const index = this.plan.sequences.indexOf(source) + + for (const count of this.property.count) { if (index < 0 || count === 0) continue const below = Math.sign(count) - count = Math.abs(count) - - for (let i = 1; i <= count; i++) { + for (let i = 1; i <= Math.abs(count); i++) { const pos = index + i * below - if (pos >= 0 && pos < this.plan.entries.length) { - const dest = this.plan.entries[pos] - - if (!dest.enabled) continue - - if (this.availableEntryPropertiesToApply.get('EXPOSURE_TIME')) dest.exposureTime = source.exposureTime - if (this.availableEntryPropertiesToApply.get('EXPOSURE_AMOUNT')) dest.exposureAmount = source.exposureAmount - if (this.availableEntryPropertiesToApply.get('EXPOSURE_DELAY')) dest.exposureDelay = source.exposureDelay - if (this.availableEntryPropertiesToApply.get('FRAME_TYPE')) dest.frameType = source.frameType - if (this.availableEntryPropertiesToApply.get('X')) dest.x = source.x - if (this.availableEntryPropertiesToApply.get('Y')) dest.y = source.y - if (this.availableEntryPropertiesToApply.get('WIDTH')) dest.width = source.width - if (this.availableEntryPropertiesToApply.get('HEIGHT')) dest.height = source.height - if (this.availableEntryPropertiesToApply.get('BIN')) dest.binX = source.binX - if (this.availableEntryPropertiesToApply.get('BIN')) dest.binY = source.binY - if (this.availableEntryPropertiesToApply.get('FRAME_FORMAT')) dest.frameFormat = source.frameFormat - if (this.availableEntryPropertiesToApply.get('GAIN')) dest.gain = source.gain - if (this.availableEntryPropertiesToApply.get('OFFSET')) dest.offset = source.offset + if (pos >= 0 && pos < this.plan.sequences.length) { + const dest = this.plan.sequences[pos] + + if (!dest.enabled || dest === source) continue + + if (this.property.properties.EXPOSURE_TIME) dest.exposureTime = source.exposureTime + if (this.property.properties.EXPOSURE_AMOUNT) dest.exposureAmount = source.exposureAmount + if (this.property.properties.EXPOSURE_DELAY) dest.exposureDelay = source.exposureDelay + if (this.property.properties.FRAME_TYPE) dest.frameType = source.frameType + if (this.property.properties.X) dest.x = source.x + if (this.property.properties.Y) dest.y = source.y + if (this.property.properties.WIDTH) dest.width = source.width + if (this.property.properties.HEIGHT) dest.height = source.height + if (this.property.properties.BIN) dest.binX = source.binX + if (this.property.properties.BIN) dest.binY = source.binY + if (this.property.properties.FRAME_FORMAT) dest.frameFormat = source.frameFormat + if (this.property.properties.GAIN) dest.gain = source.gain + if (this.property.properties.OFFSET) dest.offset = source.offset } else { break } } } - this.savePlan() + this.savePreference() - this.showEntryPropertiesToApplyDialog = false + this.property.showDialog = false } - deleteEntry(entry: CameraStartCapture, index: number) { - if (entry === this.plan.entries[index]) { - this.plan.entries.splice(index, 1) - this.savePlan() + protected deleteSequence(sequence: Sequence, index: number) { + if (sequence === this.plan.sequences[index]) { + this.plan.sequences.splice(index, 1) + this.savePreference() } } - duplicateEntry(entry: CameraStartCapture, index: number) { - this.plan.entries.splice(index + 1, 0, structuredClone(entry)) - this.savePlan() + protected duplicateSequence(sequence: Sequence, index: number) { + this.plan.sequences.splice(index + 1, 0, structuredClone(sequence)) + this.savePreference() } - async start() { - if (this.camera) { + protected filterRemoved(sequence: Sequence) { + sequence.filterPosition = 0 + this.savePreference() + } + + protected async start() { + if (this.plan.camera) { for (let i = 0; i < this.cameraExposures.length; i++) { this.cameraExposures.get(i)?.reset() } - this.savePlan() + await this.browserWindowService.openCameraImage(this.plan.camera, 'SEQUENCER') + await this.api.sequencerStart(this.plan.camera, this.plan) + } + } - await this.browserWindow.openCameraImage(this.camera, 'SEQUENCER') - await this.api.sequencerStart(this.camera, this.plan) + protected async pause() { + if (this.plan.camera) { + await this.api.sequencerPause(this.plan.camera) } } - pause() { - return this.api.sequencerPause(this.camera!) + protected async unpause() { + if (this.plan.camera) { + await this.api.sequencerUnpause(this.plan.camera) + } } - unpause() { - return this.api.sequencerUnpause(this.camera!) + protected async stop() { + if (this.plan.camera) { + await this.api.sequencerStop(this.plan.camera) + } } - stop() { - return this.api.sequencerStop(this.camera!) + private loadPreference() { + Object.assign(this.preference, this.preferenceService.sequencerPreference.get()) + this.plan = this.preference.plan + this.property.properties = this.preference.properties + + this.loadPlan(this.plan) + } + + protected savePreference() { + this.preferenceService.sequencerPreference.set(this.preference) + + if (this.preference.loadPath) { + this.saveMenuItem.disabled = false + } } } diff --git a/desktop/src/shared/components/camera-info/camera-info.component.html b/desktop/src/shared/components/camera-info/camera-info.component.html index bd1ffe2ed..3444ae02c 100644 --- a/desktop/src/shared/components/camera-info/camera-info.component.html +++ b/desktop/src/shared/components/camera-info/camera-info.component.html @@ -1,56 +1,64 @@
- {{ info.frameType }} - + class="flex flex-column align-items-center"> + + {{ info.frameType }}
- {{ info.exposureAmount || 'โˆž' }} / {{ info.exposureTime | exposureTime }} - + class="flex flex-column align-items-center"> + + {{ info.exposureAmount || 'โˆž' }} / {{ info.exposureTime | exposureTime }}
- {{ info.exposureDelay * 1000000 | exposureTime }} - + class="flex flex-column align-items-center"> + + {{ info.exposureDelay * 1000000 | exposureTime }}
- {{ info.x }} {{ info.y }} {{ info.width }} {{ info.height }} - + class="flex flex-column align-items-center"> + + {{ info.x }} {{ info.y }} {{ info.width }} {{ info.height }}
- {{ info.binX }}x{{ info.binY }} - + class="flex flex-column align-items-center"> + + {{ info.binX }}x{{ info.binY }}
- {{ info.gain }} - + class="flex flex-column align-items-center"> + + {{ info.gain }}
- {{ info.offset }} - + class="flex flex-column align-items-center"> + + {{ info.offset }}
- {{ info.frameFormat }} - + class="flex flex-column align-items-center"> + + {{ info.frameFormat }}
- {{ filter }} - + class="flex flex-row gap-1 align-items-center"> +
+ + {{ filter }} +
+
diff --git a/desktop/src/shared/components/camera-info/camera-info.component.scss b/desktop/src/shared/components/camera-info/camera-info.component.scss deleted file mode 100644 index a608020ad..000000000 --- a/desktop/src/shared/components/camera-info/camera-info.component.scss +++ /dev/null @@ -1,28 +0,0 @@ -.tag { - position: relative; - display: flex; - align-items: end; - border-radius: 4px; - - span { - display: block; - text-align: center; - margin-top: 9px; - font-size: 0.875rem !important; - } - - label { - border-radius: 2px; - font-size: 9px !important; - font-weight: bold; - top: -0.5rem !important; - background-color: #151515d0; - padding: 2px 4px; - position: absolute; - pointer-events: none; - left: 50%; - transform: translate(-50%, 0%); - display: block; - width: max-content; - } -} diff --git a/desktop/src/shared/components/camera-info/camera-info.component.ts b/desktop/src/shared/components/camera-info/camera-info.component.ts index 4e62ec9c4..c3472e027 100644 --- a/desktop/src/shared/components/camera-info/camera-info.component.ts +++ b/desktop/src/shared/components/camera-info/camera-info.component.ts @@ -1,11 +1,11 @@ -import { Component, Input } from '@angular/core' +import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core' import { CameraStartCapture } from '../../types/camera.types' import { Wheel } from '../../types/wheel.types' @Component({ selector: 'neb-camera-info', templateUrl: './camera-info.component.html', - styleUrls: ['./camera-info.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class CameraInfoComponent { @Input({ required: true }) @@ -20,6 +20,12 @@ export class CameraInfoComponent { @Input() protected readonly hasExposure: boolean = true + @Input() + protected readonly canRemoveFilter = false + + @Output() + protected readonly filterRemoved = new EventEmitter() + get hasFilter() { return !!this.wheel && !!this.info.filterPosition && this.wheel.connected } diff --git a/desktop/src/shared/components/path-chooser/path-chooser.component.ts b/desktop/src/shared/components/path-chooser/path-chooser.component.ts index 4191b402f..8371df8cb 100644 --- a/desktop/src/shared/components/path-chooser/path-chooser.component.ts +++ b/desktop/src/shared/components/path-chooser/path-chooser.component.ts @@ -26,7 +26,7 @@ export class PathChooserComponent { protected readonly directory!: boolean @Input() - protected readonly path?: string + protected path?: string @Output() readonly pathChange = new EventEmitter() @@ -41,6 +41,7 @@ export class PathChooserComponent { const path = await (this.directory ? this.electron.openDirectory({ defaultPath }) : this.electron.openFile({ defaultPath })) if (path) { + this.path = path this.pathChange.emit(path) localStorage.setItem(key, path) } diff --git a/desktop/src/shared/constants.ts b/desktop/src/shared/constants.ts index 744d74377..cf7016eb0 100644 --- a/desktop/src/shared/constants.ts +++ b/desktop/src/shared/constants.ts @@ -7,11 +7,13 @@ export const TWO_DIGITS_FORMATTER = new Intl.NumberFormat('en-US', { minimumFractionDigits: 0, maximumFractionDigits: 0, }) + export const THREE_DIGITS_FORMATTER = new Intl.NumberFormat('en-US', { minimumIntegerDigits: 3, minimumFractionDigits: 0, maximumFractionDigits: 0, }) + export const ONE_DECIMAL_PLACE_FORMATTER = new Intl.NumberFormat('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1, diff --git a/desktop/src/shared/pipes/dropdown-options.pipe.ts b/desktop/src/shared/pipes/dropdown-options.pipe.ts index 254c8e578..4055016d2 100644 --- a/desktop/src/shared/pipes/dropdown-options.pipe.ts +++ b/desktop/src/shared/pipes/dropdown-options.pipe.ts @@ -8,7 +8,7 @@ import { ConnectionType } from '../types/home.types' import { Bitpix, IMAGE_STATISTICS_BIT_OPTIONS, ImageChannel, ImageFormat, ImageStatisticsBitOption, SCNRProtectionMethod } from '../types/image.types' import { MountRemoteControlProtocol } from '../types/mount.types' import { PlateSolverType } from '../types/platesolver.types' -import { SequenceCaptureMode } from '../types/sequencer.types' +import { SequencerCaptureMode } from '../types/sequencer.types' import { SettingsTabKey } from '../types/settings.types' import { StackerGroupType, StackerType } from '../types/stacker.types' import { StarDetectorType } from '../types/stardetector.types' @@ -32,7 +32,7 @@ export interface DropdownOptions { HEMISPHERE: Hemisphere[] GUIDER_PLOT_MODE: GuiderPlotMode[] GUIDER_Y_AXIS_UNIT: GuiderYAxisUnit[] - SEQUENCE_CAPTURE_MODE: SequenceCaptureMode[] + SEQUENCE_CAPTURE_MODE: SequencerCaptureMode[] STACKER: StackerType[] SETTINGS_TAB: SettingsTabKey[] STACKER_GROUP_TYPE: StackerGroupType[] @@ -41,6 +41,7 @@ export interface DropdownOptions { SATELLITE_GROUP_TYPE: SatelliteGroupType[] CONSTELLATION: Constellation[] SKY_OBJECT_TYPE: SkyObjectType[] + SEQUENCER_CAPTURE_MODE: SequencerCaptureMode[] } @Pipe({ name: 'dropdownOptions' }) @@ -101,6 +102,8 @@ export class DropdownOptionsPipe implements PipeTransform { return CONSTELLATIONS as unknown as DropdownOptions[K] case 'SKY_OBJECT_TYPE': return SKY_OBJECT_TYPES as unknown as DropdownOptions[K] + case 'SEQUENCER_CAPTURE_MODE': + return ['FULLY', 'INTERLEAVED'] as DropdownOptions[K] } return [] diff --git a/desktop/src/shared/pipes/enum.pipe.ts b/desktop/src/shared/pipes/enum.pipe.ts index 5c5e26936..a2d2822b8 100644 --- a/desktop/src/shared/pipes/enum.pipe.ts +++ b/desktop/src/shared/pipes/enum.pipe.ts @@ -8,7 +8,7 @@ import { GuideDirection, GuideState, GuiderPlotMode, GuiderYAxisUnit } from '../ import { Bitpix, ImageChannel, SCNRProtectionMethod } from '../types/image.types' import { MountRemoteControlProtocol } from '../types/mount.types' import { PlateSolverType } from '../types/platesolver.types' -import { SequenceCaptureMode, SequencerState } from '../types/sequencer.types' +import { SequencerCaptureMode, SequencerState } from '../types/sequencer.types' import { SettingsTabKey } from '../types/settings.types' import { StackerGroupType, StackerType } from '../types/stacker.types' import { StarDetectorType } from '../types/stardetector.types' @@ -37,7 +37,7 @@ export type EnumPipeKey = | GuiderPlotMode | GuiderYAxisUnit | MountRemoteControlProtocol - | SequenceCaptureMode + | SequencerCaptureMode | Bitpix | StackerType | StackerGroupType diff --git a/desktop/src/shared/pipes/exposureTime.pipe.ts b/desktop/src/shared/pipes/exposureTime.pipe.ts index 210175fae..a97fdfcb6 100644 --- a/desktop/src/shared/pipes/exposureTime.pipe.ts +++ b/desktop/src/shared/pipes/exposureTime.pipe.ts @@ -38,7 +38,7 @@ const secondFormatter = formatter(TWO_DIGITS_FORMATTER, 's') function format(value: number, factors: [number, number], formatters: [UnitFormatter, UnitFormatter]) { const a = value / factors[0] const b = (a - Math.trunc(a)) * factors[1] - return `${formatters[0](Math.trunc(a))}${formatters[1](Math.trunc(b))}` + return `${formatters[0](a)}${formatters[1](b)}` } function hours(value: number) { diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts index d8001862f..4dc734514 100644 --- a/desktop/src/shared/services/api.service.ts +++ b/desktop/src/shared/services/api.service.ts @@ -15,7 +15,7 @@ import { AnnotateImageRequest, CoordinateInterpolation, DetectedStar, FOVCamera, import { CelestialLocationType, Mount, MountRemoteControl, MountRemoteControlProtocol, SlewRate, TrackMode } from '../types/mount.types' import { PlateSolverRequest } from '../types/platesolver.types' import { Rotator } from '../types/rotator.types' -import { SequencePlan } from '../types/sequencer.types' +import { SequencerPlan } from '../types/sequencer.types' import { AnalyzedTarget, StackingRequest } from '../types/stacker.types' import { StarDetectionRequest } from '../types/stardetector.types' import { Wheel } from '../types/wheel.types' @@ -633,9 +633,9 @@ export class ApiService { // SEQUENCER - sequencerStart(camera: Camera, plan: SequencePlan) { - const body: SequencePlan = { ...plan, mount: undefined, camera: undefined, wheel: undefined, focuser: undefined } - const query = this.http.query({ mount: plan.mount, focuser: plan.focuser, wheel: plan.wheel }) + sequencerStart(camera: Camera, plan: SequencerPlan) { + const body: SequencerPlan = { ...plan, mount: undefined, camera: undefined, wheel: undefined, focuser: undefined, rotator: undefined } + const query = this.http.query({ mount: plan.mount?.id, focuser: plan.focuser?.id, wheel: plan.wheel?.id, rotator: plan.rotator?.id }) return this.http.put(`sequencer/${camera.id}/start?${query}`, body) } diff --git a/desktop/src/shared/services/preference.service.ts b/desktop/src/shared/services/preference.service.ts index 1d91e565a..739bf6b3b 100644 --- a/desktop/src/shared/services/preference.service.ts +++ b/desktop/src/shared/services/preference.service.ts @@ -12,7 +12,7 @@ import { DEFAULT_HOME_PREFERENCE, HomePreference, homePreferenceWithDefault } fr import { DEFAULT_IMAGE_PREFERENCE, ImagePreference, imagePreferenceWithDefault } from '../types/image.types' import { DEFAULT_MOUNT_PREFERENCE, Mount, MountPreference, mountPreferenceWithDefault } from '../types/mount.types' import { DEFAULT_ROTATOR_PREFERENCE, Rotator, RotatorPreference, rotatorPreferenceWithDefault } from '../types/rotator.types' -import { DEFAULT_SEQUENCER_PREFERENCE, SequencerPreference } from '../types/sequencer.types' +import { DEFAULT_SEQUENCER_PREFERENCE, SequencerPreference, sequencerPreferenceWithDefault } from '../types/sequencer.types' import { DEFAULT_SETTINGS_PREFERENCE, SettingsPreference, settingsPreferenceWithDefault } from '../types/settings.types' import { DEFAULT_STACKER_PREFERENCE, StackerPreference, stackerPreferenceWithDefault } from '../types/stacker.types' import { DEFAULT_WHEEL_PREFERENCE, Wheel, WheelPreference, wheelPreferenceWithDefault } from '../types/wheel.types' @@ -86,7 +86,7 @@ export class PreferenceService { readonly skyAtlasPreference = new PreferenceData(this.storage, 'atlas', () => structuredClone(DEFAULT_SKY_ATLAS_PREFERENCE), skyAtlasPreferenceWithDefault) readonly alignment = new PreferenceData(this.storage, 'alignment', () => structuredClone(DEFAULT_ALIGNMENT_PREFERENCE), alignmentPreferenceWithDefault) readonly calibrationPreference = new PreferenceData(this.storage, 'calibration', () => structuredClone(DEFAULT_CALIBRATION_PREFERENCE), calibrationPreferenceWithDefault) - readonly sequencerPreference = new PreferenceData(this.storage, 'sequencer', () => structuredClone(DEFAULT_SEQUENCER_PREFERENCE)) + readonly sequencerPreference = new PreferenceData(this.storage, 'sequencer', () => structuredClone(DEFAULT_SEQUENCER_PREFERENCE), sequencerPreferenceWithDefault) readonly stacker = new PreferenceData(this.storage, 'stacker', () => structuredClone(DEFAULT_STACKER_PREFERENCE), stackerPreferenceWithDefault) readonly guider = new PreferenceData(this.storage, 'guider', () => structuredClone(DEFAULT_GUIDER_PREFERENCE), guiderPreferenceWithDefault) readonly framing = new PreferenceData(this.storage, 'framing', () => structuredClone(DEFAULT_FRAMING_PREFERENCE), framingPreferenceWithDefault) diff --git a/desktop/src/shared/types/angular.types.ts b/desktop/src/shared/types/angular.types.ts index 054afff2d..7abbd0d26 100644 --- a/desktop/src/shared/types/angular.types.ts +++ b/desktop/src/shared/types/angular.types.ts @@ -16,7 +16,7 @@ function padNumber(value: number) { } export function extractDate(date: Date) { - return `${date.getFullYear()}-${padNumber(date.getMonth())}-${padNumber(date.getDay())}` + return `${date.getFullYear()}-${padNumber(date.getMonth() + 1)}-${padNumber(date.getDate())}` } export function extractTime(date: Date, hasSeconds: boolean = true) { diff --git a/desktop/src/shared/types/camera.types.ts b/desktop/src/shared/types/camera.types.ts index b59246e2b..2bdebb1c8 100644 --- a/desktop/src/shared/types/camera.types.ts +++ b/desktop/src/shared/types/camera.types.ts @@ -277,6 +277,8 @@ export const CAMERA_CAPTURE_NAMING_FORMAT_DARK = '[camera]_[type]_[width]_[heigh export const CAMERA_CAPTURE_NAMING_FORMAT_FLAT = '[camera]_[type]_[filter]_[width]_[height]_[bin]' export const CAMERA_CAPTURE_NAMING_FORMAT_BIAS = '[camera]_[type]_[width]_[height]_[bin]_[gain]' +export const EMPTY_CAMERA_CAPTURE_NAMING_FORMAT: CameraCaptureNamingFormat = {} + export const DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT: CameraCaptureNamingFormat = { light: CAMERA_CAPTURE_NAMING_FORMAT_LIGHT, dark: CAMERA_CAPTURE_NAMING_FORMAT_DARK, @@ -372,6 +374,7 @@ export function updateCameraStartCaptureFromCamera(request: CameraStartCapture, if (camera.gainMax) request.gain = Math.max(camera.gainMin, Math.min(request.gain, camera.gainMax)) if (camera.offsetMax) request.offset = Math.max(camera.offsetMin, Math.min(request.offset, camera.offsetMax)) if (camera.frameFormats.length && (!request.frameFormat || !camera.frameFormats.includes(request.frameFormat))) request.frameFormat = camera.frameFormats[0] + if (camera.exposureMin > 1 && camera.exposureMax > camera.exposureMin) request.exposureTime = Math.max(camera.exposureMin, Math.min(request.exposureTime, camera.exposureMax)) } export function cameraPreferenceWithDefault(preference?: Partial, source: CameraPreference = DEFAULT_CAMERA_PREFERENCE) { diff --git a/desktop/src/shared/types/image.types.ts b/desktop/src/shared/types/image.types.ts index 4f7a15348..5fbf79c7e 100644 --- a/desktop/src/shared/types/image.types.ts +++ b/desktop/src/shared/types/image.types.ts @@ -254,8 +254,8 @@ export interface ImageTransformation { } export interface AnnotateImageRequest { - useStarsAndDSOs: boolean - useMinorPlanets: boolean + starsAndDSOs: boolean + minorPlanets: boolean minorPlanetsMagLimit: number includeMinorPlanetsWithoutMagnitude: boolean useSimbad: boolean @@ -438,10 +438,10 @@ export const DEFAULT_STAR_DETECTOR_DIALOG: StarDetectorDialog = { } export const DEFAULT_ANNOTATE_IMAGE_REQUEST: AnnotateImageRequest = { - useStarsAndDSOs: true, - useMinorPlanets: false, - minorPlanetsMagLimit: 18.0, - includeMinorPlanetsWithoutMagnitude: true, + starsAndDSOs: true, + minorPlanets: false, + minorPlanetsMagLimit: 15.0, + includeMinorPlanetsWithoutMagnitude: false, useSimbad: false, } @@ -555,8 +555,8 @@ export function imageStretchWithDefault(stretch?: Partial, source: export function annotateImageRequestWithDefault(request?: Partial, source: AnnotateImageRequest = DEFAULT_ANNOTATE_IMAGE_REQUEST) { if (!request) return structuredClone(source) - request.useStarsAndDSOs ??= source.useStarsAndDSOs - request.useMinorPlanets ??= source.useMinorPlanets + request.starsAndDSOs ??= source.starsAndDSOs + request.minorPlanets ??= source.minorPlanets request.minorPlanetsMagLimit ??= source.minorPlanetsMagLimit request.includeMinorPlanetsWithoutMagnitude ??= source.includeMinorPlanetsWithoutMagnitude request.useSimbad ??= source.useSimbad diff --git a/desktop/src/shared/types/sequencer.types.ts b/desktop/src/shared/types/sequencer.types.ts index 48f85619f..c92cd986b 100644 --- a/desktop/src/shared/types/sequencer.types.ts +++ b/desktop/src/shared/types/sequencer.types.ts @@ -1,12 +1,31 @@ -import { DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, DEFAULT_DITHER, type AutoSubFolderMode, type CameraCaptureEvent, type CameraCaptureNamingFormat, type CameraStartCapture, type Dither } from './camera.types' +import type { Camera } from './camera.types' +import { + cameraCaptureNamingFormatWithDefault, + DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, + DEFAULT_CAMERA_START_CAPTURE, + DEFAULT_DITHER, + ditherWithDefault, + EMPTY_CAMERA_CAPTURE_NAMING_FORMAT, + type AutoSubFolderMode, + type CameraCaptureEvent, + type CameraCaptureNamingFormat, + type CameraStartCapture, + type Dither, +} from './camera.types' +import type { Focuser } from './focuser.types' +import type { Mount } from './mount.types' +import type { Rotator } from './rotator.types' +import type { Wheel } from './wheel.types' -export type SequenceCaptureMode = 'FULLY' | 'INTERLEAVED' +export type Sequence = CameraStartCapture + +export type SequencerCaptureMode = 'FULLY' | 'INTERLEAVED' export type SequencerState = 'IDLE' | 'PAUSING' | 'PAUSED' | 'RUNNING' -export const SEQUENCE_ENTRY_PROPERTIES = ['EXPOSURE_TIME', 'EXPOSURE_AMOUNT', 'EXPOSURE_DELAY', 'FRAME_TYPE', 'X', 'Y', 'WIDTH', 'HEIGHT', 'BIN', 'FRAME_FORMAT', 'GAIN', 'OFFSET'] as const +export type SequenceProperty = 'EXPOSURE_TIME' | 'EXPOSURE_AMOUNT' | 'EXPOSURE_DELAY' | 'FRAME_TYPE' | 'X' | 'Y' | 'WIDTH' | 'HEIGHT' | 'BIN' | 'FRAME_FORMAT' | 'GAIN' | 'OFFSET' -export type SequenceEntryProperty = (typeof SEQUENCE_ENTRY_PROPERTIES)[number] +export type SequenceProperties = Record export interface AutoFocusAfterConditions { enabled: boolean @@ -22,20 +41,20 @@ export interface AutoFocusAfterConditions { afterHFDIncreaseEnabled: boolean } -export interface SequencePlan { +export interface SequencerPlan { initialDelay: number - captureMode: SequenceCaptureMode + captureMode: SequencerCaptureMode autoSubFolderMode: AutoSubFolderMode savePath?: string - entries: CameraStartCapture[] + sequences: Sequence[] dither: Dither autoFocus: AutoFocusAfterConditions namingFormat: CameraCaptureNamingFormat - camera?: string - mount?: string - wheel?: string - focuser?: string - rotator?: string + camera?: Camera + mount?: Mount + wheel?: Wheel + focuser?: Focuser + rotator?: Rotator } export interface SequencerEvent extends MessageEvent { @@ -47,9 +66,17 @@ export interface SequencerEvent extends MessageEvent { state: SequencerState } +export interface SequencePropertyDialog { + showDialog: boolean + sequence?: Sequence + count: [number, number] + properties: SequenceProperties +} + export interface SequencerPreference { - savedPath?: string - plan: SequencePlan + loadPath?: string + plan: SequencerPlan + properties: SequenceProperties } export const DEFAULT_AUTO_FOCUS_AFTER_CONDITIONS: AutoFocusAfterConditions = { @@ -66,16 +93,96 @@ export const DEFAULT_AUTO_FOCUS_AFTER_CONDITIONS: AutoFocusAfterConditions = { afterHFDIncreaseEnabled: false, } -export const DEFAULT_SEQUENCE_PLAN: SequencePlan = { +export const DEFAULT_SEQUENCE: Sequence = { + ...DEFAULT_CAMERA_START_CAPTURE, + autoSave: true, + autoSubFolderMode: 'OFF', + filterPosition: 0, + shutterPosition: 0, + focusOffset: 0, + namingFormat: EMPTY_CAMERA_CAPTURE_NAMING_FORMAT, +} + +export const DEFAULT_SEQUENCER_PLAN: SequencerPlan = { initialDelay: 0, captureMode: 'FULLY', autoSubFolderMode: 'OFF', - entries: [], dither: DEFAULT_DITHER, autoFocus: DEFAULT_AUTO_FOCUS_AFTER_CONDITIONS, namingFormat: DEFAULT_CAMERA_CAPTURE_NAMING_FORMAT, + sequences: [], +} + +export const DEFAULT_SEQUENCE_PROPERTIES: SequenceProperties = { + EXPOSURE_TIME: true, + EXPOSURE_AMOUNT: true, + EXPOSURE_DELAY: true, + FRAME_TYPE: true, + X: true, + Y: true, + WIDTH: true, + HEIGHT: true, + BIN: true, + FRAME_FORMAT: true, + GAIN: true, + OFFSET: true, +} + +export const DEFAULT_SEQUENCE_PROPERTY_DIALOG: SequencePropertyDialog = { + showDialog: false, + count: [0, 0], + properties: DEFAULT_SEQUENCE_PROPERTIES, } export const DEFAULT_SEQUENCER_PREFERENCE: SequencerPreference = { - plan: structuredClone(DEFAULT_SEQUENCE_PLAN), + plan: DEFAULT_SEQUENCER_PLAN, + properties: DEFAULT_SEQUENCE_PROPERTY_DIALOG.properties, +} + +export function autoFocusAfterConditionsWithDefault(conditions?: Partial, source: AutoFocusAfterConditions = DEFAULT_AUTO_FOCUS_AFTER_CONDITIONS) { + if (!conditions) return structuredClone(source) + conditions.enabled ??= source.enabled + conditions.onStart ??= source.onStart + conditions.onFilterChange ??= source.onFilterChange + conditions.afterElapsedTime ??= source.afterElapsedTime + conditions.afterElapsedTimeEnabled ??= source.afterElapsedTimeEnabled + conditions.afterExposures ??= source.afterExposures + conditions.afterExposuresEnabled ??= source.afterExposuresEnabled + conditions.afterTemperatureChange ??= source.afterTemperatureChange + conditions.afterTemperatureChangeEnabled ??= source.afterTemperatureChangeEnabled + conditions.afterHFDIncrease ??= source.afterHFDIncrease + conditions.afterHFDIncreaseEnabled ??= source.afterHFDIncreaseEnabled + return conditions as AutoFocusAfterConditions +} + +export function sequencePropertiesWithDefault(properties?: Partial, source: SequenceProperties = DEFAULT_SEQUENCE_PROPERTIES) { + if (!properties) return structuredClone(source) + + for (const entry of Object.entries(source)) { + const key = entry[0] as SequenceProperty + properties[key] ??= source[key] + } + + return properties as SequenceProperties +} + +export function sequencerPlanWithDefault(plan?: Partial, source: SequencerPlan = DEFAULT_SEQUENCER_PLAN) { + if (!plan) return structuredClone(source) + plan.initialDelay ??= source.initialDelay + plan.captureMode ||= source.captureMode + plan.autoSubFolderMode ||= source.autoSubFolderMode + plan.savePath ||= source.savePath + plan.sequences ??= source.sequences + plan.dither = ditherWithDefault(plan.dither, source.dither) + plan.autoFocus = autoFocusAfterConditionsWithDefault(plan.autoFocus, source.autoFocus) + plan.namingFormat = cameraCaptureNamingFormatWithDefault(plan.namingFormat, source.namingFormat) + return plan as SequencerPlan +} + +export function sequencerPreferenceWithDefault(preference?: Partial, source: SequencerPreference = DEFAULT_SEQUENCER_PREFERENCE) { + if (!preference) return structuredClone(source) + preference.loadPath ||= source.loadPath + preference.plan = sequencerPlanWithDefault(preference.plan, source.plan) + preference.properties = sequencePropertiesWithDefault(preference.properties, source.properties) + return preference as SequencerPreference } diff --git a/desktop/src/shared/types/settings.types.ts b/desktop/src/shared/types/settings.types.ts index b75a777d9..f7956d1a9 100644 --- a/desktop/src/shared/types/settings.types.ts +++ b/desktop/src/shared/types/settings.types.ts @@ -77,16 +77,16 @@ export function settingsPreferenceWithDefault(preference?: Partial Date: Fri, 9 Aug 2024 12:57:45 -0300 Subject: [PATCH 095/104] [desktop]: Refactor --- .../app/alignment/alignment.component.html | 2 +- .../src/app/alignment/alignment.component.ts | 6 +- desktop/src/app/app.component.ts | 27 ++++---- desktop/src/app/atlas/atlas.component.ts | 20 +++--- desktop/src/app/camera/camera.component.ts | 8 +-- .../app/filterwheel/filterwheel.component.ts | 20 +++--- .../app/flat-wizard/flat-wizard.component.ts | 8 +-- desktop/src/app/framing/framing.component.ts | 7 +-- desktop/src/app/home/home.component.html | 4 +- desktop/src/app/home/home.component.ts | 44 ++++++------- desktop/src/app/image/image.component.html | 62 +++++++++++-------- desktop/src/app/image/image.component.ts | 36 ++++++++--- desktop/src/app/indi/indi.component.ts | 4 +- .../property/indi-property.component.scss | 2 +- .../indi/property/indi-property.component.ts | 3 +- desktop/src/app/mount/mount.component.ts | 6 +- .../src/app/sequencer/sequencer.component.ts | 15 ++--- .../src/app/settings/settings.component.ts | 3 +- .../device-chooser.component.scss | 0 .../device-chooser.component.ts | 4 +- .../device-list-menu.component.ts | 6 +- .../histogram/histogram.component.scss | 8 --- .../histogram/histogram.component.ts | 4 +- .../components/location/location.dialog.ts | 4 +- .../menu-item/menu-item.component.scss | 0 .../menu-item/menu-item.component.ts | 4 +- .../components/moon/moon.component.html | 2 +- .../components/moon/moon.component.scss | 4 -- .../shared/components/moon/moon.component.ts | 4 +- .../path-chooser/path-chooser.component.ts | 4 +- .../slide-menu/slide-menu.component.scss | 0 .../slide-menu/slide-menu.component.ts | 4 +- .../shared/dialogs/confirm/confirm.dialog.ts | 8 +-- .../interceptors/confirmation.interceptor.ts | 6 +- .../interceptors/location.interceptor.ts | 6 +- .../{prime.service.ts => angular.service.ts} | 10 +-- desktop/src/shared/services/api.service.ts | 4 +- .../shared/services/browser-window.service.ts | 6 +- .../shared/services/confirmation.service.ts | 6 +- .../src/shared/services/electron.service.ts | 34 +++++----- desktop/src/shared/services/http.service.ts | 6 +- 41 files changed, 215 insertions(+), 196 deletions(-) delete mode 100644 desktop/src/shared/components/device-chooser/device-chooser.component.scss delete mode 100644 desktop/src/shared/components/histogram/histogram.component.scss delete mode 100644 desktop/src/shared/components/menu-item/menu-item.component.scss delete mode 100644 desktop/src/shared/components/moon/moon.component.scss delete mode 100644 desktop/src/shared/components/slide-menu/slide-menu.component.scss rename desktop/src/shared/services/{prime.service.ts => angular.service.ts} (80%) diff --git a/desktop/src/app/alignment/alignment.component.html b/desktop/src/app/alignment/alignment.component.html index 8f4e687c1..3be7dfd3c 100644 --- a/desktop/src/app/alignment/alignment.component.html +++ b/desktop/src/app/alignment/alignment.component.html @@ -41,7 +41,7 @@ [info]="status" />
, ) { console.info('APP_CONFIG', APP_CONFIG) - if (electron.isElectron) { + if (electronService.isElectron) { console.info('Run in electron', window.preference) } else { console.info('Run in browser', window.preference) @@ -49,7 +49,7 @@ export class AppComponent implements OnDestroy { const height = entries[0].target.clientHeight if (height) { - void this.electron.resizeWindow(height) + void this.electronService.resizeWindow(height) } }) @@ -58,36 +58,37 @@ export class AppComponent implements OnDestroy { this.resizeObserver = undefined } - electron.on('CONFIRMATION', (event) => { - if (confirmation.has(event.idempotencyKey)) { + electronService.on('CONFIRMATION', (event) => { + if (confirmationService.has(event.idempotencyKey)) { void ngZone.run(() => { - return confirmation.processConfirmationEvent(event) + return confirmationService.processConfirmationEvent(event) }) } }) } + @HostListener('window:unload') ngOnDestroy() { this.resizeObserver?.disconnect() } pin() { this.pinned = !this.pinned - if (this.pinned) return this.electron.pinWindow() - else return this.electron.unpinWindow() + if (this.pinned) return this.electronService.pinWindow() + else return this.electronService.unpinWindow() } minimize() { - return this.electron.minimizeWindow() + return this.electronService.minimizeWindow() } maximize() { - return this.electron.maximizeWindow() + return this.electronService.maximizeWindow() } async close(data?: unknown, force: boolean = false) { if (!this.beforeClose || (await this.beforeClose()) || force) { - return await this.electron.closeWindow(data) + return await this.electronService.closeWindow(data) } else { return undefined } diff --git a/desktop/src/app/atlas/atlas.component.ts b/desktop/src/app/atlas/atlas.component.ts index cdcbe3554..dbcf90086 100644 --- a/desktop/src/app/atlas/atlas.component.ts +++ b/desktop/src/app/atlas/atlas.component.ts @@ -9,12 +9,11 @@ import { timer } from 'rxjs' import { DeviceListMenuComponent } from '../../shared/components/device-list-menu/device-list-menu.component' import { SlideMenuItem } from '../../shared/components/menu-item/menu-item.component' import { ONE_DECIMAL_PLACE_FORMATTER, TWO_DIGITS_FORMATTER } from '../../shared/constants' -import { SkyObjectPipe } from '../../shared/pipes/skyObject.pipe' +import { AngularService } from '../../shared/services/angular.service' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' -import { PrimeService } from '../../shared/services/prime.service' import { extractDate, extractTime } from '../../shared/types/angular.types' import { AltitudeDataPoint, @@ -351,10 +350,9 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, private readonly api: ApiService, private readonly browserWindowService: BrowserWindowService, private readonly route: ActivatedRoute, - electron: ElectronService, + electronService: ElectronService, private readonly preferenceService: PreferenceService, - private readonly skyObjectPipe: SkyObjectPipe, - private readonly primeService: PrimeService, + private readonly angularService: AngularService, ngZone: NgZone, ) { app.title = 'Sky Atlas' @@ -367,7 +365,7 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, }, }) - electron.on('LOCATION.CHANGED', (location) => { + electronService.on('LOCATION.CHANGED', (location) => { ngZone.run(() => { this.loadLocations() @@ -377,11 +375,9 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, }) }) - electron.on('DATA.CHANGED', async (event) => { + electronService.on('DATA.CHANGED', async (event) => { await this.loadTabFromData(event) }) - - // TODO: Refresh graph and twilight if hours past 12 (noon) } ngOnInit() { @@ -487,7 +483,7 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, this.minorPlanet.closeApproach.result = await this.api.closeApproachesOfMinorPlanets(this.minorPlanet.closeApproach.days, this.minorPlanet.closeApproach.lunarDistance, this.dateTimeAndLocation.dateTime) if (!this.minorPlanet.closeApproach.result.length) { - this.primeService.message('No close approaches found for the given days and lunar distance', 'warn') + this.angularService.message('No close approaches found for the given days and lunar distance', 'warn') } } finally { this.refresh.position = false @@ -504,7 +500,7 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, protected async skyObjectChanged() { if (this.skyObject.search.selected) { - this.skyObject.name = this.skyObjectPipe.transform(this.skyObject.search.selected, 'name') ?? '-' + this.skyObject.name = this.skyObject.search.selected.name await this.refreshTab(false, true) } } @@ -799,7 +795,7 @@ export class AtlasComponent implements OnInit, AfterContentInit, AfterViewInit, } private async executeMount(action: (mount: Mount) => void | Promise) { - if (await this.primeService.confirm('Are you sure that you want to proceed?')) { + if (await this.angularService.confirm('Are you sure that you want to proceed?')) { return false } diff --git a/desktop/src/app/camera/camera.component.ts b/desktop/src/app/camera/camera.component.ts index 99f7e6255..2362f69bb 100644 --- a/desktop/src/app/camera/camera.component.ts +++ b/desktop/src/app/camera/camera.component.ts @@ -350,7 +350,7 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { const data = JSON.parse(decodeURIComponent(e['data'] as string)) as unknown if (this.app.modal) { - await this.loadCameraStartCaptureOnDialogMode(data as CameraDialogInput) + await this.loadCameraStartCaptureForDialogMode(data as CameraDialogInput) } else { await this.cameraChanged(data as Camera) } @@ -379,7 +379,7 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { } } - private async loadCameraStartCaptureOnDialogMode(data?: CameraDialogInput) { + private async loadCameraStartCaptureForDialogMode(data?: CameraDialogInput) { if (data) { this.mode = data.mode await this.cameraChanged(data.camera) @@ -756,8 +756,8 @@ export class CameraComponent implements AfterContentInit, OnDestroy, Tickable { } } - static async showAsDialog(window: BrowserWindowService, mode: CameraMode, camera: Camera, request: CameraStartCapture) { - const result = await window.openCameraDialog({ mode, camera, request }) + static async showAsDialog(service: BrowserWindowService, mode: CameraMode, camera: Camera, request: CameraStartCapture) { + const result = await service.openCameraDialog({ mode, camera, request }) if (result) { Object.assign(request, result) diff --git a/desktop/src/app/filterwheel/filterwheel.component.ts b/desktop/src/app/filterwheel/filterwheel.component.ts index 3155597fc..1cc4c9bbf 100644 --- a/desktop/src/app/filterwheel/filterwheel.component.ts +++ b/desktop/src/app/filterwheel/filterwheel.component.ts @@ -36,6 +36,9 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab protected mode: WheelMode = 'CAPTURE' + private readonly filterPublisher = new Subject() + private readonly filterSubscription?: Subscription + get canShowInfo() { return this.mode === 'CAPTURE' } @@ -56,9 +59,6 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab return this.filters[this.position - 1] } - private readonly filterChangePublisher = new Subject() - private readonly filterChangeSubscription?: Subscription - constructor( private readonly app: AppComponent, private readonly api: ApiService, @@ -112,7 +112,7 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab } }) - this.filterChangeSubscription = this.filterChangePublisher.pipe(debounceTime(1500)).subscribe(async (filter) => { + this.filterSubscription = this.filterPublisher.pipe(debounceTime(1500)).subscribe(async (filter) => { const names = this.filters.map((e) => e.name) await this.api.wheelSync(this.wheel, names) await this.electronService.send('WHEEL.RENAMED', { wheel: this.wheel, filter }) @@ -173,7 +173,7 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab const data = JSON.parse(decodeURIComponent(e['data'] as string)) as unknown if (this.app.modal) { - await this.loadWheelStartCaptureOnDialogMode(data as WheelDialogInput) + await this.loadCameraStartCaptureForDialogMode(data as WheelDialogInput) } else { await this.wheelChanged(data as Wheel) } @@ -192,7 +192,7 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab @HostListener('window:unload') ngOnDestroy() { this.ticker.unregister(this) - this.filterChangeSubscription?.unsubscribe() + this.filterSubscription?.unsubscribe() } async tick() { @@ -200,7 +200,7 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab if (this.focuser?.id) await this.api.focuserListen(this.focuser) } - private async loadWheelStartCaptureOnDialogMode(data?: WheelDialogInput) { + private async loadCameraStartCaptureForDialogMode(data?: WheelDialogInput) { if (data) { this.mode = data.mode await this.wheelChanged(data.wheel) @@ -307,7 +307,7 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab protected filterNameChanged(filter: Filter) { if (filter.name) { - this.filterChangePublisher.next(structuredClone(filter)) + this.filterPublisher.next(structuredClone(filter)) } } @@ -380,8 +380,8 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab return this.app.close(this.makeCameraStartCapture()) } - static async showAsDialog(window: BrowserWindowService, mode: WheelMode, wheel: Wheel, request: CameraStartCapture) { - const result = await window.openWheelDialog({ mode, wheel, request }) + static async showAsDialog(service: BrowserWindowService, mode: WheelMode, wheel: Wheel, request: CameraStartCapture) { + const result = await service.openWheelDialog({ mode, wheel, request }) if (result) { Object.assign(request, result) diff --git a/desktop/src/app/flat-wizard/flat-wizard.component.ts b/desktop/src/app/flat-wizard/flat-wizard.component.ts index c7f754327..9be7b2260 100644 --- a/desktop/src/app/flat-wizard/flat-wizard.component.ts +++ b/desktop/src/app/flat-wizard/flat-wizard.component.ts @@ -1,10 +1,10 @@ import { AfterViewInit, Component, HostListener, NgZone, OnDestroy, ViewChild } from '@angular/core' import { CameraExposureComponent } from '../../shared/components/camera-exposure/camera-exposure.component' +import { AngularService } from '../../shared/services/angular.service' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' -import { PrimeService } from '../../shared/services/prime.service' import { Tickable, Ticker } from '../../shared/services/ticker.service' import { Camera, DEFAULT_CAMERA, updateCameraStartCaptureFromCamera } from '../../shared/types/camera.types' import { DEFAULT_FLAT_WIZARD_PREFERENCE } from '../../shared/types/flat-wizard.types' @@ -48,7 +48,7 @@ export class FlatWizardComponent implements AfterViewInit, OnDestroy, Tickable { private readonly api: ApiService, electronService: ElectronService, private readonly browserWindowService: BrowserWindowService, - private readonly primeService: PrimeService, + private readonly angularService: AngularService, private readonly preferenceService: PreferenceService, private readonly ticker: Ticker, ngZone: NgZone, @@ -62,10 +62,10 @@ export class FlatWizardComponent implements AfterViewInit, OnDestroy, Tickable { this.cameraExposure.handleCameraCaptureEvent(event.capture, true) } else if (event.state === 'CAPTURED') { this.running = false - this.primeService.message(`Flat frame captured`) + this.angularService.message('Flat frame captured') } else if (event.state === 'FAILED') { this.running = false - this.primeService.message(`Failed to find an optimal exposure time from given parameters`, 'error') + this.angularService.message('Failed to find an optimal exposure time from given parameters', 'error') } }) }) diff --git a/desktop/src/app/framing/framing.component.ts b/desktop/src/app/framing/framing.component.ts index 9dc33726c..d01f82a70 100644 --- a/desktop/src/app/framing/framing.component.ts +++ b/desktop/src/app/framing/framing.component.ts @@ -1,10 +1,10 @@ import { AfterViewInit, Component, HostListener, NgZone, OnDestroy } from '@angular/core' import { ActivatedRoute } from '@angular/router' +import { AngularService } from '../../shared/services/angular.service' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' -import { PrimeService } from '../../shared/services/prime.service' import { DEFAULT_FRAMING_PREFERENCE, HipsSurvey, LoadFraming } from '../../shared/types/framing.types' import { AppComponent } from '../app.component' @@ -15,7 +15,6 @@ import { AppComponent } from '../app.component' export class FramingComponent implements AfterViewInit, OnDestroy { protected readonly preference = structuredClone(DEFAULT_FRAMING_PREFERENCE) protected hipsSurveys: HipsSurvey[] = [] - protected loading = false private frameId = '' @@ -27,7 +26,7 @@ export class FramingComponent implements AfterViewInit, OnDestroy { private readonly browserWindowService: BrowserWindowService, private readonly electronService: ElectronService, private readonly preferenceService: PreferenceService, - private readonly primeService: PrimeService, + private readonly angularService: AngularService, ngZone: NgZone, ) { app.title = 'Framing' @@ -87,7 +86,7 @@ export class FramingComponent implements AfterViewInit, OnDestroy { } catch (e) { console.error(e) - this.primeService.message('Failed to retrieve the image', 'error') + this.angularService.message('Failed to retrieve the image', 'error') } finally { this.loading = false } diff --git a/desktop/src/app/home/home.component.html b/desktop/src/app/home/home.component.html index 6dbb5e008..960215797 100644 --- a/desktop/src/app/home/home.component.html +++ b/desktop/src/app/home/home.component.html @@ -287,11 +287,11 @@
diff --git a/desktop/src/app/home/home.component.ts b/desktop/src/app/home/home.component.ts index 24ad324c9..5bb19a589 100644 --- a/desktop/src/app/home/home.component.ts +++ b/desktop/src/app/home/home.component.ts @@ -3,11 +3,11 @@ import { dirname } from 'path' import { DeviceChooserComponent } from '../../shared/components/device-chooser/device-chooser.component' import { DeviceConnectionCommandEvent, DeviceListMenuComponent } from '../../shared/components/device-list-menu/device-list-menu.component' import { MenuItem, SlideMenuItem } from '../../shared/components/menu-item/menu-item.component' +import { AngularService } from '../../shared/services/angular.service' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' -import { PrimeService } from '../../shared/services/prime.service' import { Camera, isCamera } from '../../shared/types/camera.types' import { Device, DeviceType } from '../../shared/types/device.types' import { Focuser, isFocuser } from '../../shared/types/focuser.types' @@ -40,7 +40,7 @@ export class HomeComponent implements AfterContentInit { protected domes: Camera[] = [] protected switches: Camera[] = [] - protected currentPage = 0 + protected page = 0 protected readonly deviceModel: MenuItem[] = [] @@ -55,6 +55,22 @@ export class HomeComponent implements AfterContentInit { }, ] + protected readonly deviceMenuToolbarBuilder = (device: Device): MenuItem[] => { + if (isCamera(device)) { + return [ + { + icon: 'mdi mdi-image', + label: 'View Image', + command: () => { + return this.browserWindowService.openCameraImage(device) + }, + }, + ] + } else { + return [] + } + } + @ViewChild('deviceMenu') private readonly deviceMenu!: DeviceListMenuComponent @@ -122,28 +138,12 @@ export class HomeComponent implements AfterContentInit { return this.connection?.type === 'ALPACA' && this.hasDevices } - protected readonly deviceMenuToolbarBuilder = (device: Device): MenuItem[] => { - if (isCamera(device)) { - return [ - { - icon: 'mdi mdi-image', - label: 'View Image', - command: () => { - return this.browserWindowService.openCameraImage(device) - }, - }, - ] - } else { - return [] - } - } - constructor( app: AppComponent, private readonly electronService: ElectronService, private readonly browserWindowService: BrowserWindowService, private readonly api: ApiService, - private readonly primeService: PrimeService, + private readonly angularService: AngularService, private readonly preferenceService: PreferenceService, ngZone: NgZone, ) { @@ -356,7 +356,7 @@ export class HomeComponent implements AfterContentInit { } catch (e) { console.error(e) - this.primeService.message('Connection failed', 'error') + this.angularService.message('Connection failed', 'error') } finally { await this.updateConnection() } @@ -555,13 +555,13 @@ export class HomeComponent implements AfterContentInit { } } - this.currentPage = page + this.page = page event.stopImmediatePropagation() } protected scrollTo(event: Event, page: number) { - this.currentPage = page + this.page = page this.scrollToPage(page) event.stopImmediatePropagation() } diff --git a/desktop/src/app/image/image.component.html b/desktop/src/app/image/image.component.html index e0908e86d..3bec82bfe 100644 --- a/desktop/src/app/image/image.component.html +++ b/desktop/src/app/image/image.component.html @@ -1054,7 +1054,9 @@
@@ -1069,6 +1071,7 @@ styleClass="p-inputtext-sm border-0" [showButtons]="true" [(ngModel)]="fov.selected.focalLength" + (ngModelChange)="saveFOV()" spinnableNumber /> @@ -1079,6 +1082,7 @@ styleClass="p-inputtext-sm border-0" [showButtons]="true" [(ngModel)]="fov.selected.aperture" + (ngModelChange)="saveFOV()" spinnableNumber /> @@ -1101,6 +1105,7 @@ [min]="1" [max]="9999" [(ngModel)]="fov.selected.cameraSize.width" + (ngModelChange)="saveFOV()" spinnableNumber /> @@ -1113,6 +1118,7 @@ [min]="1" [max]="9999" [(ngModel)]="fov.selected.cameraSize.height" + (ngModelChange)="saveFOV()" spinnableNumber /> @@ -1128,6 +1134,7 @@ [minFractionDigits]="0" [maxFractionDigits]="2" [(ngModel)]="fov.selected.pixelSize.width" + (ngModelChange)="saveFOV()" locale="en" spinnableNumber /> @@ -1144,12 +1151,13 @@ [minFractionDigits]="0" [maxFractionDigits]="2" [(ngModel)]="fov.selected.pixelSize.height" + (ngModelChange)="saveFOV()" locale="en" spinnableNumber />
-
+
@@ -1173,6 +1182,7 @@ [min]="1" [max]="5" [(ngModel)]="fov.selected.bin" + (ngModelChange)="saveFOV()" spinnableNumber /> @@ -1188,79 +1198,81 @@ [minFractionDigits]="0" [maxFractionDigits]="2" [(ngModel)]="fov.rotation" + (ngModelChange)="saveFOV(false)" locale="en" spinnableNumber />
--> -
+
+ style="max-height: 112px"> @for (item of fov.fovs; track $index) {
+ class="flex align-items-center gap-2 border-left-3 p-2 border-round cursor-pointer" + [class.bg-blue-900]="fov.selected === item" + [style.border-color]="item.color" + (click)="selectFOV(item)">
+ [(ngModel)]="item.enabled" + (onChange)="$event.originalEvent?.stopImmediatePropagation()" />
-
+
+ value="FL: {{ item.focalLength }} mm" /> + value="AP: {{ item.aperture }} mm" /> + value="RES: {{ item.cameraSize.width }}x{{ item.cameraSize.height }}" /> + value="PS: {{ item.pixelSize.width }}x{{ item.pixelSize.height }} ยตm" /> + value="MULT: {{ item.barlowReducer.toFixed(2) }}x" /> + value="BIN: {{ item.bin }}" /> + value="ANGLE: {{ item.rotation }}ยฐ" /> @if (item.computed) { + value="F/{{ item.computed.focalRatio.toFixed(1) }}" /> + value="SCALE: {{ item.computed.cameraResolution.width.toFixed(2) }}"x{{ item.computed.cameraResolution.height.toFixed(2) }}"" /> + value="FOV: {{ item.computed.fieldSize.width.toFixed(2) }}ยฐx{{ item.computed.fieldSize.height.toFixed(2) }}ยฐ" /> }
- + pTooltip="Remove" + tooltipPosition="bottom" + (onClick)="deleteFOV(item); $event.stopImmediatePropagation()" />
} diff --git a/desktop/src/app/image/image.component.ts b/desktop/src/app/image/image.component.ts index 6e96e0ed0..ca3e8607e 100644 --- a/desktop/src/app/image/image.component.ts +++ b/desktop/src/app/image/image.component.ts @@ -9,15 +9,16 @@ import { DeviceListMenuComponent } from '../../shared/components/device-list-men import { HistogramComponent } from '../../shared/components/histogram/histogram.component' import { MenuItem } from '../../shared/components/menu-item/menu-item.component' import { SEPARATOR_MENU_ITEM } from '../../shared/constants' +import { AngularService } from '../../shared/services/angular.service' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' -import { PrimeService } from '../../shared/services/prime.service' import { EquatorialCoordinateJ2000 } from '../../shared/types/atlas.types' import { Camera } from '../../shared/types/camera.types' import { AstronomicalObjectDialog, + DEFAULT_FOV, DEFAULT_IMAGE_ANNOTATION_DIALOG, DEFAULT_IMAGE_CALIBRATION, DEFAULT_IMAGE_DATA, @@ -391,7 +392,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { private readonly electronService: ElectronService, private readonly browserWindowService: BrowserWindowService, private readonly preferenceService: PreferenceService, - private readonly primeService: PrimeService, + private readonly angularService: AngularService, ngZone: NgZone, ) { app.title = 'Image' @@ -441,7 +442,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { label: 'Settings', command: () => { this.settings.showDialog = true - } + }, }) electronService.on('CAMERA.CAPTURE_ELAPSED', async (event) => { @@ -1210,8 +1211,23 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } } - editFOV(fov: FOV) { - this.fov.selected = fov + private removeSelectedFOV() { + this.fov.selected = structuredClone(DEFAULT_FOV) + } + + protected selectFOV(fov: FOV) { + if (this.fov.selected === fov) { + this.removeSelectedFOV() + } else { + this.fov.selected = fov + } + } + + protected saveFOV(compute: boolean = true) { + // Edited. + if (this.fov.fovs.includes(this.fov.selected) && (!compute || this.computeFOV(this.fov.selected))) { + this.savePreference() + } } private computeFOV(fov: FOV) { @@ -1252,12 +1268,16 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } } - deleteFOV(fov: FOV) { + protected deleteFOV(fov: FOV) { const index = this.fov.fovs.indexOf(fov) if (index >= 0) { this.fov.fovs.splice(index, 1) this.savePreference() + + if (this.fov.selected === this.fov.fovs[index]) { + this.removeSelectedFOV() + } } } @@ -1285,7 +1305,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } private async executeCamera(action: (camera: Camera) => void | Promise, showConfirmation: boolean = true) { - if (showConfirmation && (await this.primeService.confirm('Are you sure that you want to proceed?'))) { + if (showConfirmation && (await this.angularService.confirm('Are you sure that you want to proceed?'))) { return false } @@ -1307,7 +1327,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } private async executeMount(action: (mount: Mount) => void | Promise, showConfirmation: boolean = true) { - if (showConfirmation && (await this.primeService.confirm('Are you sure that you want to proceed?'))) { + if (showConfirmation && (await this.angularService.confirm('Are you sure that you want to proceed?'))) { return false } diff --git a/desktop/src/app/indi/indi.component.ts b/desktop/src/app/indi/indi.component.ts index 298d19fa7..f528be883 100644 --- a/desktop/src/app/indi/indi.component.ts +++ b/desktop/src/app/indi/indi.component.ts @@ -96,7 +96,7 @@ export class INDIComponent implements AfterViewInit, OnDestroy { } } - async deviceChanged(device: Device) { + protected async deviceChanged(device: Device) { if (this.device) { await this.api.indiUnlisten(this.device) } @@ -108,7 +108,7 @@ export class INDIComponent implements AfterViewInit, OnDestroy { this.messages = await this.api.indiLog(device) } - changeGroup(group: string) { + protected changeGroup(group: string) { this.showLog = false this.group = group } diff --git a/desktop/src/app/indi/property/indi-property.component.scss b/desktop/src/app/indi/property/indi-property.component.scss index 33a3607f1..3c6597153 100644 --- a/desktop/src/app/indi/property/indi-property.component.scss +++ b/desktop/src/app/indi/property/indi-property.component.scss @@ -1,4 +1,4 @@ -:host { +neb-indi-property { background: rgba(0, 0, 0, 0.1); border-radius: 8px; display: block; diff --git a/desktop/src/app/indi/property/indi-property.component.ts b/desktop/src/app/indi/property/indi-property.component.ts index 87e58f06a..7ccde2aa4 100644 --- a/desktop/src/app/indi/property/indi-property.component.ts +++ b/desktop/src/app/indi/property/indi-property.component.ts @@ -1,10 +1,11 @@ -import { AfterContentInit, Component, EventEmitter, Input, Output } from '@angular/core' +import { AfterContentInit, Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core' import { INDIProperty, INDIPropertyItem, INDISendProperty, INDISendPropertyItem } from '../../../shared/types/device.types' @Component({ selector: 'neb-indi-property', templateUrl: './indi-property.component.html', styleUrls: ['./indi-property.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class INDIPropertyComponent implements AfterContentInit { @Input({ required: true }) diff --git a/desktop/src/app/mount/mount.component.ts b/desktop/src/app/mount/mount.component.ts index d6e372aad..1707f0d14 100644 --- a/desktop/src/app/mount/mount.component.ts +++ b/desktop/src/app/mount/mount.component.ts @@ -4,11 +4,11 @@ import hotkeys from 'hotkeys-js' import { Subject, Subscription, interval, throttleTime } from 'rxjs' import { SlideMenuItem } from '../../shared/components/menu-item/menu-item.component' import { SEPARATOR_MENU_ITEM } from '../../shared/constants' +import { AngularService } from '../../shared/services/angular.service' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' -import { PrimeService } from '../../shared/services/prime.service' import { Tickable, Ticker } from '../../shared/services/ticker.service' import { BodyTabType, ComputedLocation, DEFAULT_COMPUTED_LOCATION } from '../../shared/types/atlas.types' import { DEFAULT_MOUNT, DEFAULT_MOUNT_PREFERENCE, DEFAULT_MOUNT_REMOTE_CONTROL_DIALOG, Mount, MountRemoteControlProtocol, MountSlewDirection, SlewRate, TrackMode } from '../../shared/types/mount.types' @@ -210,7 +210,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Tickable { electronService: ElectronService, private readonly preferenceService: PreferenceService, private readonly route: ActivatedRoute, - private readonly primeService: PrimeService, + private readonly angularService: AngularService, private readonly ticker: Ticker, ngZone: NgZone, ) { @@ -344,7 +344,7 @@ export class MountComponent implements AfterContentInit, OnDestroy, Tickable { await this.api.mountRemoteControlStart(this.mount, this.remoteControl.protocol, this.remoteControl.host, this.remoteControl.port) this.remoteControl.controls = await this.api.mountRemoteControlList(this.mount) } catch { - this.primeService.message('Failed to start remote control', 'error') + this.angularService.message('Failed to start remote control', 'error') } } diff --git a/desktop/src/app/sequencer/sequencer.component.ts b/desktop/src/app/sequencer/sequencer.component.ts index 74fa18ca3..c1a92261b 100644 --- a/desktop/src/app/sequencer/sequencer.component.ts +++ b/desktop/src/app/sequencer/sequencer.component.ts @@ -4,11 +4,11 @@ import { dirname } from 'path' import { CameraExposureComponent } from '../../shared/components/camera-exposure/camera-exposure.component' import { DialogMenuComponent } from '../../shared/components/dialog-menu/dialog-menu.component' import { MenuItem, SlideMenuItem } from '../../shared/components/menu-item/menu-item.component' +import { AngularService } from '../../shared/services/angular.service' import { ApiService } from '../../shared/services/api.service' import { BrowserWindowService } from '../../shared/services/browser-window.service' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' -import { PrimeService } from '../../shared/services/prime.service' import { Tickable, Ticker } from '../../shared/services/ticker.service' import { JsonFile } from '../../shared/types/app.types' import { Camera, cameraCaptureNamingFormatWithDefault, FrameType, updateCameraStartCaptureFromCamera } from '../../shared/types/camera.types' @@ -151,7 +151,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable private readonly browserWindowService: BrowserWindowService, private readonly electronService: ElectronService, private readonly preferenceService: PreferenceService, - private readonly primeService: PrimeService, + private readonly angularService: AngularService, private readonly ticker: Ticker, ngZone: NgZone, ) { @@ -164,7 +164,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable app.beforeClose = async () => { if (!this.saveMenuItem.disabled) { - return !(await primeService.confirm('Are you sure you want to close the window? Please make sure to save before exiting to avoid losing any important changes.')) + return !(await angularService.confirm('Are you sure you want to close the window? Please make sure to save before exiting to avoid losing any important changes.')) } else { return true } @@ -267,8 +267,9 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable if (this.plan.rotator?.id) await this.api.rotatorListen(this.plan.rotator) } - private enableOrDisableTopbarMenu(enable: boolean) { - this.app.topMenu.forEach((e) => (e.disabled = !enable)) + private enableOrDisableTopbarMenu(enabled: boolean) { + this.createNewMenuItem.disabled = !enabled + this.loadMenuItem.disabled = !enabled } protected add() { @@ -301,7 +302,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable private loadPlanFromJson(file: JsonFile) { if (!this.loadPlan(file.json)) { - this.primeService.message(`No sequence found`, 'warn') + this.angularService.message('No sequence found', 'warn') this.add() } @@ -322,7 +323,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Tickable return } - this.primeService.message(`Failed to load the file`, 'error') + this.angularService.message('Failed to load the file', 'error') this.preference.loadPath = undefined this.savePreference() diff --git a/desktop/src/app/settings/settings.component.ts b/desktop/src/app/settings/settings.component.ts index 7dd07b6c1..4cf58566a 100644 --- a/desktop/src/app/settings/settings.component.ts +++ b/desktop/src/app/settings/settings.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, OnDestroy } from '@angular/core' +import { AfterViewInit, Component, HostListener, OnDestroy } from '@angular/core' import { debounceTime, Subject, Subscription } from 'rxjs' import { ElectronService } from '../../shared/services/electron.service' import { PreferenceService } from '../../shared/services/preference.service' @@ -59,6 +59,7 @@ export class SettingsComponent implements AfterViewInit, OnDestroy { this.loadPreference() } + @HostListener('window:unload') ngOnDestroy() { this.locationChangeSubscription?.unsubscribe() } diff --git a/desktop/src/shared/components/device-chooser/device-chooser.component.scss b/desktop/src/shared/components/device-chooser/device-chooser.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/shared/components/device-chooser/device-chooser.component.ts b/desktop/src/shared/components/device-chooser/device-chooser.component.ts index a2b835954..c77fa36f4 100644 --- a/desktop/src/shared/components/device-chooser/device-chooser.component.ts +++ b/desktop/src/shared/components/device-chooser/device-chooser.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core' +import { Component, EventEmitter, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core' import { ApiService } from '../../services/api.service' import { Device } from '../../types/device.types' import { Undefinable } from '../../utils/types' @@ -8,7 +8,7 @@ import { MenuItem } from '../menu-item/menu-item.component' @Component({ selector: 'neb-device-chooser', templateUrl: './device-chooser.component.html', - styleUrls: ['./device-chooser.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class DeviceChooserComponent { @Input({ required: true }) diff --git a/desktop/src/shared/components/device-list-menu/device-list-menu.component.ts b/desktop/src/shared/components/device-list-menu/device-list-menu.component.ts index ce6d0db6b..5d879ee0e 100644 --- a/desktop/src/shared/components/device-list-menu/device-list-menu.component.ts +++ b/desktop/src/shared/components/device-list-menu/device-list-menu.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core' import { SEPARATOR_MENU_ITEM } from '../../constants' -import { PrimeService } from '../../services/prime.service' +import { AngularService } from '../../services/angular.service' import { isGuideHead } from '../../types/camera.types' import { Device } from '../../types/device.types' import { deviceComparator } from '../../utils/comparators' @@ -47,7 +47,7 @@ export class DeviceListMenuComponent { @ViewChild('menu') private readonly menu!: DialogMenuComponent - constructor(private readonly prime: PrimeService) {} + constructor(private readonly angularService: AngularService) {} show(devices: T[], selected?: NoInfer, header?: string) { const model: SlideMenuItem[] = [] @@ -57,7 +57,7 @@ export class DeviceListMenuComponent { return new Promise>((resolve) => { if (devices.length <= 0) { resolve(undefined) - this.prime.message('Please connect your equipment first!', 'warn') + this.angularService.message('Please connect your equipment first!', 'warn') return } diff --git a/desktop/src/shared/components/histogram/histogram.component.scss b/desktop/src/shared/components/histogram/histogram.component.scss deleted file mode 100644 index a5051dfe6..000000000 --- a/desktop/src/shared/components/histogram/histogram.component.scss +++ /dev/null @@ -1,8 +0,0 @@ -:host { - position: relative; -} - -.minX, -.maxX { - bottom: -12px; -} diff --git a/desktop/src/shared/components/histogram/histogram.component.ts b/desktop/src/shared/components/histogram/histogram.component.ts index 1b78ff066..742910ff7 100644 --- a/desktop/src/shared/components/histogram/histogram.component.ts +++ b/desktop/src/shared/components/histogram/histogram.component.ts @@ -1,9 +1,9 @@ -import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core' +import { AfterViewInit, Component, ElementRef, ViewChild, ViewEncapsulation } from '@angular/core' @Component({ selector: 'neb-histogram', templateUrl: './histogram.component.html', - styleUrls: ['./histogram.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class HistogramComponent implements AfterViewInit { @ViewChild('canvas') diff --git a/desktop/src/shared/components/location/location.dialog.ts b/desktop/src/shared/components/location/location.dialog.ts index 166e7d5d3..90a7ebef0 100644 --- a/desktop/src/shared/components/location/location.dialog.ts +++ b/desktop/src/shared/components/location/location.dialog.ts @@ -9,7 +9,7 @@ import { MapComponent } from '../map/map.component' }) export class LocationComponent implements AfterViewInit { @ViewChild('map') - private readonly map!: MapComponent + private readonly map?: MapComponent @Input() readonly location!: Location @@ -31,7 +31,7 @@ export class LocationComponent implements AfterViewInit { } ngAfterViewInit() { - this.map.refresh() + this.map?.refresh() } save() { diff --git a/desktop/src/shared/components/menu-item/menu-item.component.scss b/desktop/src/shared/components/menu-item/menu-item.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/shared/components/menu-item/menu-item.component.ts b/desktop/src/shared/components/menu-item/menu-item.component.ts index 3f08f8ad8..d980aff44 100644 --- a/desktop/src/shared/components/menu-item/menu-item.component.ts +++ b/desktop/src/shared/components/menu-item/menu-item.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core' +import { Component, Input, ViewEncapsulation } from '@angular/core' import { CheckboxChangeEvent } from 'primeng/checkbox' import { InputSwitchChangeEvent } from 'primeng/inputswitch' import { Severity, TooltipPosition } from '../../types/angular.types' @@ -56,7 +56,7 @@ export interface SlideMenuItem extends MenuItem { @Component({ selector: 'neb-menu-item', templateUrl: './menu-item.component.html', - styleUrls: ['./menu-item.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class MenuItemComponent { @Input({ required: true }) diff --git a/desktop/src/shared/components/moon/moon.component.html b/desktop/src/shared/components/moon/moon.component.html index 70136bde4..960765765 100644 --- a/desktop/src/shared/components/moon/moon.component.html +++ b/desktop/src/shared/components/moon/moon.component.html @@ -2,4 +2,4 @@ #moon [height]="height" [width]="width" - style="filter: brightness(1.5)"> + style="filter: brightness(1.5); background-repeat: no-repeat; background-position: center"> diff --git a/desktop/src/shared/components/moon/moon.component.scss b/desktop/src/shared/components/moon/moon.component.scss deleted file mode 100644 index 184d65ea9..000000000 --- a/desktop/src/shared/components/moon/moon.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -canvas { - background-repeat: no-repeat; - background-position: center; -} diff --git a/desktop/src/shared/components/moon/moon.component.ts b/desktop/src/shared/components/moon/moon.component.ts index 382e2c69d..16f13b385 100644 --- a/desktop/src/shared/components/moon/moon.component.ts +++ b/desktop/src/shared/components/moon/moon.component.ts @@ -1,9 +1,9 @@ -import { AfterViewInit, Component, ElementRef, Input, OnChanges, ViewChild } from '@angular/core' +import { AfterViewInit, Component, ElementRef, Input, OnChanges, ViewChild, ViewEncapsulation } from '@angular/core' @Component({ selector: 'neb-moon', templateUrl: './moon.component.html', - styleUrls: ['./moon.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class MoonComponent implements AfterViewInit, OnChanges { @Input() diff --git a/desktop/src/shared/components/path-chooser/path-chooser.component.ts b/desktop/src/shared/components/path-chooser/path-chooser.component.ts index 8371df8cb..92b525181 100644 --- a/desktop/src/shared/components/path-chooser/path-chooser.component.ts +++ b/desktop/src/shared/components/path-chooser/path-chooser.component.ts @@ -31,14 +31,14 @@ export class PathChooserComponent { @Output() readonly pathChange = new EventEmitter() - constructor(private readonly electron: ElectronService) {} + constructor(private readonly electronService: ElectronService) {} protected async choosePath() { const key = `pathChooser.${this.key}.defaultPath` const lastPath = localStorage.getItem(key) || undefined const defaultPath = lastPath && !this.directory ? dirname(lastPath) : lastPath - const path = await (this.directory ? this.electron.openDirectory({ defaultPath }) : this.electron.openFile({ defaultPath })) + const path = await (this.directory ? this.electronService.openDirectory({ defaultPath }) : this.electronService.openFile({ defaultPath })) if (path) { this.path = path diff --git a/desktop/src/shared/components/slide-menu/slide-menu.component.scss b/desktop/src/shared/components/slide-menu/slide-menu.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/desktop/src/shared/components/slide-menu/slide-menu.component.ts b/desktop/src/shared/components/slide-menu/slide-menu.component.ts index a180c25cc..838e60a04 100644 --- a/desktop/src/shared/components/slide-menu/slide-menu.component.ts +++ b/desktop/src/shared/components/slide-menu/slide-menu.component.ts @@ -1,11 +1,11 @@ -import { Component, ElementRef, EventEmitter, Input, OnInit, Output, TemplateRef } from '@angular/core' +import { Component, ElementRef, EventEmitter, Input, OnInit, Output, TemplateRef, ViewEncapsulation } from '@angular/core' import { Nullable } from '../../utils/types' import { MenuItemCommandEvent, SlideMenuItem } from '../menu-item/menu-item.component' @Component({ selector: 'neb-slide-menu', templateUrl: './slide-menu.component.html', - styleUrls: ['./slide-menu.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class SlideMenuComponent implements OnInit { @Input({ required: true }) diff --git a/desktop/src/shared/dialogs/confirm/confirm.dialog.ts b/desktop/src/shared/dialogs/confirm/confirm.dialog.ts index 9a60a74ca..0f65686bd 100644 --- a/desktop/src/shared/dialogs/confirm/confirm.dialog.ts +++ b/desktop/src/shared/dialogs/confirm/confirm.dialog.ts @@ -1,10 +1,10 @@ import { Component } from '@angular/core' import { ConfirmEventType, Confirmation } from 'primeng/api' import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog' -import { PrimeService } from '../../services/prime.service' +import { AngularService } from '../../services/angular.service' @Component({ - templateUrl: './confirm.dialog.html' + templateUrl: './confirm.dialog.html', }) export class ConfirmDialog { readonly header: string @@ -26,8 +26,8 @@ export class ConfirmDialog { this.dialogRef.close(ConfirmEventType.ACCEPT) } - static async open(prime: PrimeService, message: string) { + static async open(service: AngularService, message: string) { const data: Confirmation = { message } - return (await prime.open(ConfirmDialog, { header: 'Confirmation', data, style: { maxWidth: '320px' } })) ?? ConfirmEventType.CANCEL + return (await service.open(ConfirmDialog, { header: 'Confirmation', data, style: { maxWidth: '320px' } })) ?? ConfirmEventType.CANCEL } } diff --git a/desktop/src/shared/interceptors/confirmation.interceptor.ts b/desktop/src/shared/interceptors/confirmation.interceptor.ts index 30f476127..ec5be3093 100644 --- a/desktop/src/shared/interceptors/confirmation.interceptor.ts +++ b/desktop/src/shared/interceptors/confirmation.interceptor.ts @@ -6,7 +6,7 @@ import { IdempotencyKeyInterceptor } from './idempotency-key.interceptor' @Injectable({ providedIn: 'root' }) export class ConfirmationInterceptor implements HttpInterceptor { - constructor(private readonly confirmation: ConfirmationService) {} + constructor(private readonly confirmationService: ConfirmationService) {} intercept(req: HttpRequest, next: HttpHandler): Observable> { const hasConfirmation = req.urlWithParams.includes('hasConfirmation') @@ -15,7 +15,7 @@ export class ConfirmationInterceptor implements HttpInterceptor { const idempotencyKey = req.headers.get(IdempotencyKeyInterceptor.HEADER_KEY) if (idempotencyKey) { - this.confirmation.register(idempotencyKey) + this.confirmationService.register(idempotencyKey) } const res = next.handle(req) @@ -23,7 +23,7 @@ export class ConfirmationInterceptor implements HttpInterceptor { if (idempotencyKey) { return res.pipe( finalize(() => { - this.confirmation.unregister(idempotencyKey) + this.confirmationService.unregister(idempotencyKey) }), ) } diff --git a/desktop/src/shared/interceptors/location.interceptor.ts b/desktop/src/shared/interceptors/location.interceptor.ts index b8ef3715b..8e2af3dbc 100644 --- a/desktop/src/shared/interceptors/location.interceptor.ts +++ b/desktop/src/shared/interceptors/location.interceptor.ts @@ -7,7 +7,7 @@ import { PreferenceService } from '../services/preference.service' export class LocationInterceptor implements HttpInterceptor { static readonly HEADER_KEY = 'X-Location' - constructor(private readonly preference: PreferenceService) {} + constructor(private readonly preferenceService: PreferenceService) {} intercept(req: HttpRequest, next: HttpHandler): Observable> { if (req.urlWithParams.includes('hasLocation')) { @@ -15,7 +15,7 @@ export class LocationInterceptor implements HttpInterceptor { const hasLocation = params.get('hasLocation') if (!hasLocation || hasLocation === 'true') { - const location = this.preference.settings.get().location + const location = this.preferenceService.settings.get().location req = req.clone({ headers: req.headers.set(LocationInterceptor.HEADER_KEY, JSON.stringify(location)), @@ -24,7 +24,7 @@ export class LocationInterceptor implements HttpInterceptor { const id = parseInt(hasLocation) if (id) { - const locations = this.preference.settings.get().locations + const locations = this.preferenceService.settings.get().locations const location = locations.find((e) => e.id === id) if (location) { diff --git a/desktop/src/shared/services/prime.service.ts b/desktop/src/shared/services/angular.service.ts similarity index 80% rename from desktop/src/shared/services/prime.service.ts rename to desktop/src/shared/services/angular.service.ts index 3d450f9e7..43e5e5ab1 100644 --- a/desktop/src/shared/services/prime.service.ts +++ b/desktop/src/shared/services/angular.service.ts @@ -5,14 +5,14 @@ import { ConfirmDialog } from '../dialogs/confirm/confirm.dialog' import { Undefinable } from '../utils/types' @Injectable({ providedIn: 'root' }) -export class PrimeService { +export class AngularService { constructor( - private readonly dialog: DialogService, - private readonly messager: MessageService, + private readonly dialogService: DialogService, + private readonly messageService: MessageService, ) {} open(componentType: Type, config: DynamicDialogConfig) { - const ref = this.dialog.open(componentType, { + const ref = this.dialogService.open(componentType, { ...config, duplicate: true, draggable: config.draggable ?? true, @@ -41,6 +41,6 @@ export class PrimeService { } message(text: string, severity: 'info' | 'warn' | 'error' | 'success' = 'success') { - this.messager.add({ severity, detail: text, life: 8500 }) + this.messageService.add({ severity, detail: text, life: 8500 }) } } diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts index 4dc734514..1278d9cab 100644 --- a/desktop/src/shared/services/api.service.ts +++ b/desktop/src/shared/services/api.service.ts @@ -24,12 +24,12 @@ import { HttpService } from './http.service' @Injectable({ providedIn: 'root' }) export class ApiService { - constructor(private readonly http: HttpService) {} - get baseUrl() { return this.http.baseUrl } + constructor(private readonly http: HttpService) {} + // CONNECTION connect(host: string, port: number, type: ConnectionType) { diff --git a/desktop/src/shared/services/browser-window.service.ts b/desktop/src/shared/services/browser-window.service.ts index ff3724398..2ff5fa757 100644 --- a/desktop/src/shared/services/browser-window.service.ts +++ b/desktop/src/shared/services/browser-window.service.ts @@ -14,16 +14,16 @@ import { ElectronService } from './electron.service' @Injectable({ providedIn: 'root' }) export class BrowserWindowService { - constructor(private readonly electron: ElectronService) {} + constructor(private readonly electronService: ElectronService) {} openWindow(open: OpenWindow): Promise { open.preference.modal = false - return this.electron.ipcRenderer.invoke('WINDOW.OPEN', { ...open, windowId: window.id }) + return this.electronService.ipcRenderer.invoke('WINDOW.OPEN', { ...open, windowId: window.id }) } openModal(open: OpenWindow): Promise> { open.preference.modal = true - return this.electron.ipcRenderer.invoke('WINDOW.OPEN', { ...open, windowId: window.id }) + return this.electronService.ipcRenderer.invoke('WINDOW.OPEN', { ...open, windowId: window.id }) } openMount(data: Mount, preference: WindowPreference = {}) { diff --git a/desktop/src/shared/services/confirmation.service.ts b/desktop/src/shared/services/confirmation.service.ts index 45918bfb5..55b4c0b12 100644 --- a/desktop/src/shared/services/confirmation.service.ts +++ b/desktop/src/shared/services/confirmation.service.ts @@ -1,15 +1,15 @@ import { Injectable } from '@angular/core' import { ConfirmEventType } from 'primeng/api' import { ConfirmationEvent } from '../types/app.types' +import { AngularService } from './angular.service' import { ApiService } from './api.service' -import { PrimeService } from './prime.service' @Injectable({ providedIn: 'root' }) export class ConfirmationService { private readonly keys = new Map() constructor( - private readonly prime: PrimeService, + private readonly angularService: AngularService, private readonly api: ApiService, ) {} @@ -26,7 +26,7 @@ export class ConfirmationService { } async processConfirmationEvent(event: ConfirmationEvent) { - const response = await this.prime.confirm(event.message) + const response = await this.angularService.confirm(event.message) await this.api.confirm(event.idempotencyKey, response === ConfirmEventType.ACCEPT) this.unregister(event.idempotencyKey) } diff --git a/desktop/src/shared/services/electron.service.ts b/desktop/src/shared/services/electron.service.ts index aa8012ddb..bf88acc10 100644 --- a/desktop/src/shared/services/electron.service.ts +++ b/desktop/src/shared/services/electron.service.ts @@ -24,13 +24,20 @@ import { Rotator } from '../types/rotator.types' import { SequencerEvent } from '../types/sequencer.types' import { Wheel, WheelRenamed } from '../types/wheel.types' -export const IMAGE_FILE_FILTER: Electron.FileFilter[] = [ +export const OPEN_IMAGE_FILE_FILTER: Electron.FileFilter[] = [ { name: 'All', extensions: ['fits', 'fit', 'xisf'] }, { name: 'FITS', extensions: ['fits', 'fit'] }, { name: 'XISF', extensions: ['xisf'] }, ] -interface EventMappedType { +export const SAVE_IMAGE_FILE_FILTER: Electron.FileFilter[] = [ + { name: 'All', extensions: ['fits', 'fit', 'xisf', 'png', 'jpg', 'jpeg'] }, + { name: 'FITS', extensions: ['fits', 'fit'] }, + { name: 'XISF', extensions: ['xisf'] }, + { name: 'Image', extensions: ['png', 'jpg', 'jpeg'] }, +] + +export interface EventTypes { NOTIFICATION: NotificationEvent CONFIRMATION: ConfirmationEvent 'DEVICE.PROPERTY_CHANGED': INDIMessageEvent @@ -87,10 +94,10 @@ interface EventMappedType { @Injectable({ providedIn: 'root' }) export class ElectronService { - ipcRenderer!: typeof ipcRenderer - webFrame!: typeof webFrame - childProcess!: typeof childProcess - fs!: typeof fs + readonly ipcRenderer!: typeof ipcRenderer + private readonly webFrame!: typeof webFrame + private readonly childProcess!: typeof childProcess + private readonly fs!: typeof fs constructor() { if (this.isElectron) { @@ -121,11 +128,11 @@ export class ElectronService { return !!(window && window.process?.type) } - send(channel: K, data?: EventMappedType[K]) { + send(channel: K, data?: EventTypes[K]) { return this.ipcRenderer.invoke(channel, data) } - on(channel: K, listener: (arg: EventMappedType[K]) => void) { + on(channel: K, listener: (arg: EventTypes[K]) => void) { this.ipcRenderer.on(channel, (_, arg) => { listener(arg) }) @@ -147,7 +154,7 @@ export class ElectronService { return this.openFile({ ...data, windowId: data?.windowId ?? window.id, - filters: IMAGE_FILE_FILTER, + filters: OPEN_IMAGE_FILE_FILTER, }) } @@ -155,7 +162,7 @@ export class ElectronService { return this.openFiles({ ...data, windowId: data?.windowId ?? window.id, - filters: IMAGE_FILE_FILTER, + filters: OPEN_IMAGE_FILE_FILTER, }) } @@ -163,12 +170,7 @@ export class ElectronService { return this.saveFile({ ...data, windowId: data?.windowId ?? window.id, - filters: [ - { name: 'All', extensions: ['fits', 'fit', 'xisf', 'png', 'jpg', 'jpeg'] }, - { name: 'FITS', extensions: ['fits', 'fit'] }, - { name: 'XISF', extensions: ['xisf'] }, - { name: 'Image', extensions: ['png', 'jpg', 'jpeg'] }, - ], + filters: SAVE_IMAGE_FILE_FILTER, }) } diff --git a/desktop/src/shared/services/http.service.ts b/desktop/src/shared/services/http.service.ts index d6310aaa7..e3bcfc3ec 100644 --- a/desktop/src/shared/services/http.service.ts +++ b/desktop/src/shared/services/http.service.ts @@ -7,11 +7,9 @@ export type QueryParamType = Nullable | QueryParamTyp @Injectable({ providedIn: 'root' }) export class HttpService { - constructor(private readonly http: HttpClient) {} + readonly baseUrl = `http://${window.apiHost}:${window.apiPort}` - get baseUrl() { - return `http://${window.apiHost}:${window.apiPort}` - } + constructor(private readonly http: HttpClient) {} get(path: string) { return firstValueFrom(this.http.get(`${this.baseUrl}/${path}`)) From 109d02281e1370a4cb4e537e83d0e72fdb114b50 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Fri, 9 Aug 2024 18:14:39 -0300 Subject: [PATCH 096/104] [api]: Fix PixInsight Live Stacker --- .../livestacker/PixInsightLiveStacker.kt | 9 ++-- .../test/kotlin/PixInsightAutoStackerTest.kt | 8 +--- .../test/kotlin/PixInsightLiveStackerTest.kt | 45 +++++++++++++++++++ .../test/kotlin/PixInsightPlateSolverTest.kt | 8 +--- .../src/test/kotlin/PixInsightScriptTest.kt | 2 +- .../src/test/kotlin/PixInsightStackerTest.kt | 8 +--- .../test/kotlin/PixInsightStarDetectorTest.kt | 6 +-- 7 files changed, 55 insertions(+), 31 deletions(-) create mode 100644 nebulosa-pixinsight/src/test/kotlin/PixInsightLiveStackerTest.kt diff --git a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt index 2d010cdb2..47219c118 100644 --- a/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt +++ b/nebulosa-pixinsight/src/main/kotlin/nebulosa/pixinsight/livestacker/PixInsightLiveStacker.kt @@ -9,7 +9,6 @@ import nebulosa.pixinsight.script.PixInsightStartup import nebulosa.pixinsight.stacker.PixInsightStacker import java.nio.file.Path import java.util.concurrent.atomic.AtomicBoolean -import kotlin.io.path.copyTo import kotlin.io.path.deleteIfExists data class PixInsightLiveStacker( @@ -34,7 +33,7 @@ data class PixInsightLiveStacker( @Volatile private var stackCount = 0 private val stacker = PixInsightStacker(runner, workingDirectory, slot) - private val referencePath = Path.of("$workingDirectory", "reference.fits") + private val referencePath = Path.of("$workingDirectory", "reference.xisf") private val calibratedPath = Path.of("$workingDirectory", "calibrated.xisf") private val alignedPath = Path.of("$workingDirectory", "aligned.xisf") private val stackedPath = Path.of("$workingDirectory", "stacked.fits") @@ -46,7 +45,7 @@ data class PixInsightLiveStacker( try { check(PixInsightStartup(slot).use { it.runSync(runner).success }) } catch (e: Throwable) { - throw IllegalStateException("unable to start PixInsight") + throw IllegalStateException("unable to start PixInsight", e) } } @@ -81,8 +80,8 @@ data class PixInsightLiveStacker( stackCount++ } } else { - targetPath.copyTo(referencePath, true) - targetPath.copyTo(stackedPath, true) + stacker.saveAs(targetPath, referencePath) + stacker.saveAs(targetPath, stackedPath) LOG.info("live stacking started. target={}, reference={}, stacked={}", targetPath, referencePath, stackedPath) stackCount = 1 } diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightAutoStackerTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightAutoStackerTest.kt index f3590870d..75fc0736a 100644 --- a/nebulosa-pixinsight/src/test/kotlin/PixInsightAutoStackerTest.kt +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightAutoStackerTest.kt @@ -1,13 +1,12 @@ +import PixInsightScriptTest.Companion.RUNNER import PixInsightScriptTest.Companion.openAsImage import io.kotest.matchers.booleans.shouldBeTrue import io.kotest.matchers.shouldBe import nebulosa.image.algorithms.transformation.AutoScreenTransformFunction -import nebulosa.pixinsight.script.PixInsightScriptRunner import nebulosa.pixinsight.stacker.PixInsightAutoStacker import nebulosa.test.* import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test -import java.nio.file.Path @NonGitHubOnly class PixInsightAutoStackerTest : AbstractTest() { @@ -38,9 +37,4 @@ class PixInsightAutoStackerTest : AbstractTest() { outputPath.openAsImage().transform(AutoScreenTransformFunction) .save("pi-calibrated-auto-stacked").second shouldBe "" } - - companion object { - - @JvmStatic private val RUNNER = PixInsightScriptRunner(Path.of("PixInsight")) - } } diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightLiveStackerTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightLiveStackerTest.kt new file mode 100644 index 000000000..7c968728f --- /dev/null +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightLiveStackerTest.kt @@ -0,0 +1,45 @@ +import PixInsightScriptTest.Companion.RUNNER +import PixInsightScriptTest.Companion.openAsImage +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import nebulosa.image.algorithms.transformation.AutoScreenTransformFunction +import nebulosa.pixinsight.livestacker.PixInsightLiveStacker +import nebulosa.test.AbstractTest +import nebulosa.test.NonGitHubOnly +import nebulosa.test.PI_01_LIGHT +import nebulosa.test.PI_02_LIGHT +import nebulosa.test.PI_03_LIGHT +import nebulosa.test.PI_04_LIGHT +import nebulosa.test.PI_05_LIGHT +import nebulosa.test.PI_06_LIGHT +import nebulosa.test.PI_07_LIGHT +import nebulosa.test.PI_08_LIGHT +import nebulosa.test.save +import org.junit.jupiter.api.Test +import java.nio.file.Path + +@NonGitHubOnly +class PixInsightLiveStackerTest : AbstractTest() { + + @Test + fun stack() { + val files = listOf(PI_01_LIGHT, PI_02_LIGHT, PI_03_LIGHT, PI_04_LIGHT, PI_05_LIGHT, PI_06_LIGHT, PI_07_LIGHT, PI_08_LIGHT) + val workingDirectory = tempDirectory("pi-") + var outputPath: Path? = null + + val stacker = PixInsightLiveStacker(RUNNER, workingDirectory) + + try { + stacker.start() + + for (file in files) { + outputPath = stacker.add(file) + } + } finally { + stacker.stop() + } + + outputPath.shouldNotBeNull().openAsImage().transform(AutoScreenTransformFunction) + .save("pi-live-stacked").second shouldBe "a107143dff3d43c4b56c872da869f89b" + } +} diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightPlateSolverTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightPlateSolverTest.kt index a073f27b3..52e4a22b6 100644 --- a/nebulosa-pixinsight/src/test/kotlin/PixInsightPlateSolverTest.kt +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightPlateSolverTest.kt @@ -1,14 +1,13 @@ +import PixInsightScriptTest.Companion.RUNNER import io.kotest.matchers.doubles.plusOrMinus import io.kotest.matchers.ints.shouldBeExactly import io.kotest.matchers.shouldBe import nebulosa.math.* import nebulosa.pixinsight.platesolver.PixInsightPlateSolver -import nebulosa.pixinsight.script.PixInsightScriptRunner import nebulosa.test.AbstractTest import nebulosa.test.NonGitHubOnly import nebulosa.test.download import org.junit.jupiter.api.Test -import java.nio.file.Path import kotlin.math.roundToInt @NonGitHubOnly @@ -33,9 +32,4 @@ class PixInsightPlateSolverTest : AbstractTest() { solution.widthInPixels.roundToInt() shouldBeExactly 800 solution.heightInPixels.roundToInt() shouldBeExactly 526 } - - companion object { - - @JvmStatic val RUNNER = PixInsightScriptRunner(Path.of("PixInsight")) - } } diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt index 1af1ee98b..3098a6b02 100644 --- a/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightScriptTest.kt @@ -188,7 +188,7 @@ class PixInsightScriptTest : AbstractTest() { companion object { - @JvmStatic private val RUNNER = PixInsightScriptRunner(Path.of("PixInsight")) + @JvmStatic val RUNNER = PixInsightScriptRunner(Path.of("PixInsight")) @JvmStatic internal fun Path.openAsImage() = if (isFits()) fits().asImage() diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightStackerTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightStackerTest.kt index e912c2457..c04e0a364 100644 --- a/nebulosa-pixinsight/src/test/kotlin/PixInsightStackerTest.kt +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightStackerTest.kt @@ -1,12 +1,11 @@ +import PixInsightScriptTest.Companion.RUNNER import PixInsightScriptTest.Companion.openAsImage import io.kotest.matchers.booleans.shouldBeTrue import io.kotest.matchers.shouldBe import nebulosa.image.algorithms.transformation.AutoScreenTransformFunction -import nebulosa.pixinsight.script.PixInsightScriptRunner import nebulosa.pixinsight.stacker.PixInsightStacker import nebulosa.test.* import org.junit.jupiter.api.Test -import java.nio.file.Path @NonGitHubOnly class PixInsightStackerTest : AbstractTest() { @@ -65,9 +64,4 @@ class PixInsightStackerTest : AbstractTest() { outputPath.openAsImage().transform(AutoScreenTransformFunction) .save("pi-mono-luminance-combined").second shouldBe "85de365a9895234222acdc6e9feb7009" } - - companion object { - - @JvmStatic private val RUNNER = PixInsightScriptRunner(Path.of("PixInsight")) - } } diff --git a/nebulosa-pixinsight/src/test/kotlin/PixInsightStarDetectorTest.kt b/nebulosa-pixinsight/src/test/kotlin/PixInsightStarDetectorTest.kt index 149d650e9..40fb96d0f 100644 --- a/nebulosa-pixinsight/src/test/kotlin/PixInsightStarDetectorTest.kt +++ b/nebulosa-pixinsight/src/test/kotlin/PixInsightStarDetectorTest.kt @@ -1,18 +1,16 @@ +import PixInsightScriptTest.Companion.RUNNER import io.kotest.matchers.collections.shouldHaveSize -import nebulosa.pixinsight.script.PixInsightScriptRunner import nebulosa.pixinsight.stardetector.PixInsightStarDetector import nebulosa.test.NGC3344_MONO_8_FITS import nebulosa.test.NonGitHubOnly import org.junit.jupiter.api.Test -import java.nio.file.Path @NonGitHubOnly class PixInsightStarDetectorTest { @Test fun detectStars() { - val runner = PixInsightScriptRunner(Path.of("PixInsight")) - val detectedStars = PixInsightStarDetector(runner, 0).detect(NGC3344_MONO_8_FITS) + val detectedStars = PixInsightStarDetector(RUNNER, 0).detect(NGC3344_MONO_8_FITS) detectedStars shouldHaveSize 15 } } From bb378adecfb6a436fcd007e2702f2ed23a076e3a Mon Sep 17 00:00:00 2001 From: tiagohm Date: Fri, 9 Aug 2024 18:15:04 -0300 Subject: [PATCH 097/104] [api]: Fix isFits and isXisf methods on empty files --- nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt | 2 +- nebulosa-fits/src/test/kotlin/FitsFormatTest.kt | 4 +++- nebulosa-xisf/src/main/kotlin/nebulosa/xisf/XisfFormat.kt | 2 +- nebulosa-xisf/src/test/kotlin/XisfFormatTest.kt | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt b/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt index 2e5f3c609..a17a61bf3 100644 --- a/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt +++ b/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt @@ -23,7 +23,7 @@ data object FitsFormat : ImageFormat { } @JvmStatic - fun BufferedSource.readSignature() = readString(6L, Charsets.US_ASCII) + fun BufferedSource.readSignature() = if (request(6L)) readString(6L, Charsets.US_ASCII) else "" fun isImageHdu(header: ReadableHeader) = header.getBoolean(FitsKeyword.SIMPLE) || header.getStringOrNull(FitsKeyword.XTENSION) == "IMAGE" diff --git a/nebulosa-fits/src/test/kotlin/FitsFormatTest.kt b/nebulosa-fits/src/test/kotlin/FitsFormatTest.kt index 1cad69e9a..17629276d 100644 --- a/nebulosa-fits/src/test/kotlin/FitsFormatTest.kt +++ b/nebulosa-fits/src/test/kotlin/FitsFormatTest.kt @@ -1,15 +1,17 @@ import io.kotest.matchers.booleans.shouldBeFalse import io.kotest.matchers.booleans.shouldBeTrue import nebulosa.fits.isFits +import nebulosa.test.AbstractTest import nebulosa.test.M82_COLOR_16_XISF import nebulosa.test.NGC3344_COLOR_8_FITS import org.junit.jupiter.api.Test -class FitsFormatTest { +class FitsFormatTest : AbstractTest() { @Test fun shouldBeFitsFormat() { NGC3344_COLOR_8_FITS.isFits().shouldBeTrue() M82_COLOR_16_XISF.isFits().shouldBeFalse() + tempPath("empty-", ".fits").isFits().shouldBeFalse() } } diff --git a/nebulosa-xisf/src/main/kotlin/nebulosa/xisf/XisfFormat.kt b/nebulosa-xisf/src/main/kotlin/nebulosa/xisf/XisfFormat.kt index 3db2be341..c1534f639 100644 --- a/nebulosa-xisf/src/main/kotlin/nebulosa/xisf/XisfFormat.kt +++ b/nebulosa-xisf/src/main/kotlin/nebulosa/xisf/XisfFormat.kt @@ -161,7 +161,7 @@ data object XisfFormat : ImageFormat { } @JvmStatic - fun BufferedSource.readSignature() = readString(8L, Charsets.US_ASCII) + fun BufferedSource.readSignature() = if (request(8L)) readString(8L, Charsets.US_ASCII) else "" @JvmStatic internal fun Buffer.readPixel(format: SampleFormat, byteOrder: ByteOrder): Float { diff --git a/nebulosa-xisf/src/test/kotlin/XisfFormatTest.kt b/nebulosa-xisf/src/test/kotlin/XisfFormatTest.kt index 4eaa339d2..81d74e7b0 100644 --- a/nebulosa-xisf/src/test/kotlin/XisfFormatTest.kt +++ b/nebulosa-xisf/src/test/kotlin/XisfFormatTest.kt @@ -22,6 +22,7 @@ class XisfFormatTest : AbstractTest() { fun shouldBeXisfFormat() { NGC3344_COLOR_8_FITS.isXisf().shouldBeFalse() M82_COLOR_16_XISF.isXisf().shouldBeTrue() + tempPath("empty-", ".xisf").isXisf().shouldBeFalse() } @Test From 258da3dd203b400ef5c49559193a4f4235082b4d Mon Sep 17 00:00:00 2001 From: tiagohm Date: Fri, 9 Aug 2024 21:44:29 -0300 Subject: [PATCH 098/104] [desktop]: Fix Image Histogram not showing --- desktop/src/app/image/image.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop/src/app/image/image.component.ts b/desktop/src/app/image/image.component.ts index ca3e8607e..b5f5d2ab2 100644 --- a/desktop/src/app/image/image.component.ts +++ b/desktop/src/app/image/image.component.ts @@ -858,6 +858,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { this.updateImageSolved(info.solved) this.headers.headers = info.headers + this.statistics.statistics = info.statistics this.retrieveInfoFromImageHeaders(info.headers) From 3e78766dee86ce9c8c7d8c0616adf7d5a3002fdf Mon Sep 17 00:00:00 2001 From: tiagohm Date: Fri, 9 Aug 2024 21:44:57 -0300 Subject: [PATCH 099/104] [api]: Simplify Image Histogram computation --- .../nebulosa/image/algorithms/computation/Histogram.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/computation/Histogram.kt b/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/computation/Histogram.kt index e439a8a82..e9974ff98 100644 --- a/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/computation/Histogram.kt +++ b/nebulosa-image/src/main/kotlin/nebulosa/image/algorithms/computation/Histogram.kt @@ -4,7 +4,6 @@ import nebulosa.image.Image import nebulosa.image.Image.Companion.forEach import nebulosa.image.algorithms.ComputationAlgorithm import nebulosa.image.format.ImageChannel -import kotlin.math.max import kotlin.math.min data class Histogram( @@ -17,11 +16,11 @@ data class Histogram( } override fun compute(source: Image): IntArray { - val data = IntArray(2 shl (bitLength - 1)) + val data = IntArray(1 shl bitLength) val maxValue = data.size - 1 source.forEach(channel) { - val value = max(0, min((it * maxValue).toInt(), maxValue)) + val value = min((it * maxValue).toInt(), maxValue) data[value]++ } From 6d98dc424bcd466b1a5f4870ab9f9c1ef9f785b9 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Fri, 9 Aug 2024 23:09:00 -0300 Subject: [PATCH 100/104] [api]: Create class SystemClock --- api/src/main/kotlin/nebulosa/api/Main.kt | 3 ++- .../nebulosa/api/atlas/SkyAtlasService.kt | 13 ++++++----- .../DateAndTimeParamMethodArgumentResolver.kt | 7 +++--- .../nebulosa/api/cameras/AutoSubFolderMode.kt | 4 +++- .../api/cameras/CameraExposureTask.kt | 4 ++-- .../kotlin/nebulosa/api/image/ImageService.kt | 5 ++++- .../nebulosa/api/mounts/MountService.kt | 5 +++-- .../CameraCaptureNamingFormatterTest.kt | 3 ++- .../alpaca/indi/device/mounts/ASCOMMount.kt | 5 +++-- .../lx200/protocol/LX200ProtocolHandler.kt | 19 ++++++++-------- .../main/kotlin/nebulosa/time/SystemClock.kt | 15 +++++++++++++ .../src/test/kotlin/SystemClockTest.kt | 22 +++++++++++++++++++ nebulosa-wcs/src/test/kotlin/LibWCSTest.kt | 2 +- 13 files changed, 78 insertions(+), 29 deletions(-) create mode 100644 nebulosa-time/src/main/kotlin/nebulosa/time/SystemClock.kt create mode 100644 nebulosa-time/src/test/kotlin/SystemClockTest.kt diff --git a/api/src/main/kotlin/nebulosa/api/Main.kt b/api/src/main/kotlin/nebulosa/api/Main.kt index b9eb21aaf..67929a568 100644 --- a/api/src/main/kotlin/nebulosa/api/Main.kt +++ b/api/src/main/kotlin/nebulosa/api/Main.kt @@ -1,6 +1,7 @@ package nebulosa.api import com.sun.jna.Platform +import nebulosa.time.SystemClock import org.springframework.boot.runApplication import java.nio.file.Path import java.time.LocalDate @@ -26,7 +27,7 @@ fun initAppDirectory(): Path { private fun Path.clearLogIfPastDays(days: Long = 7L) { if (exists()) { - val pastDays = LocalDate.now().minusDays(days) + val pastDays = LocalDate.now(SystemClock).minusDays(days) for (entry in listDirectoryEntries("nebulosa-*.log")) { val logDate = entry.fileName.toString() diff --git a/api/src/main/kotlin/nebulosa/api/atlas/SkyAtlasService.kt b/api/src/main/kotlin/nebulosa/api/atlas/SkyAtlasService.kt index 23c12e405..5831048c4 100644 --- a/api/src/main/kotlin/nebulosa/api/atlas/SkyAtlasService.kt +++ b/api/src/main/kotlin/nebulosa/api/atlas/SkyAtlasService.kt @@ -19,6 +19,7 @@ import nebulosa.nova.position.Geoid import nebulosa.sbd.SmallBodyDatabaseService import nebulosa.skycatalog.SkyObject import nebulosa.skycatalog.SkyObjectType +import nebulosa.time.SystemClock import nebulosa.time.TimeZonedInSeconds import okhttp3.OkHttpClient import okhttp3.Request @@ -122,7 +123,7 @@ class SkyAtlasService( val nauticalDawn = doubleArrayOf(0.0, 0.0) val civilDawn = doubleArrayOf(0.0, 0.0) - val ephemeris = bodyEphemeris(if (fast) VSOP87E.SUN else SUN, location, LocalDateTime.of(date, LocalTime.now()), true) + val ephemeris = bodyEphemeris(if (fast) VSOP87E.SUN else SUN, location, LocalDateTime.of(date, LocalTime.now(SystemClock)), true) val (a) = findDiscrete(0.0, (ephemeris.size - 1).toDouble(), TwilightDiscreteFunction(ephemeris), 1.0) civilDusk[0] = a[0] / 60.0 @@ -147,12 +148,12 @@ class SkyAtlasService( } fun altitudePointsOfSun(location: GeographicCoordinate, date: LocalDate, stepSize: Int, fast: Boolean = false): List { - val ephemeris = bodyEphemeris(if (fast) VSOP87E.SUN else SUN, location, LocalDateTime.of(date, LocalTime.now()), true) + val ephemeris = bodyEphemeris(if (fast) VSOP87E.SUN else SUN, location, LocalDateTime.of(date, LocalTime.now(SystemClock)), true) return altitudePointsOfBody(ephemeris, stepSize) } fun altitudePointsOfMoon(location: GeographicCoordinate, date: LocalDate, stepSize: Int, fast: Boolean = false): List { - val ephemeris = bodyEphemeris(if (fast) FAST_MOON else MOON, location, LocalDateTime.of(date, LocalTime.now()), true) + val ephemeris = bodyEphemeris(if (fast) FAST_MOON else MOON, location, LocalDateTime.of(date, LocalTime.now(SystemClock)), true) return altitudePointsOfBody(ephemeris, stepSize) } @@ -161,7 +162,7 @@ class SkyAtlasService( stepSize: Int, fast: Boolean = false ): List { val target: Any = VSOP87E.entries.takeIf { fast }?.find { "${it.target}" == code } ?: code - val ephemeris = bodyEphemeris(target, location, LocalDateTime.of(date, LocalTime.now()), true) + val ephemeris = bodyEphemeris(target, location, LocalDateTime.of(date, LocalTime.now(SystemClock)), true) return altitudePointsOfBody(ephemeris, stepSize) } @@ -169,12 +170,12 @@ class SkyAtlasService( val target = cachedSimbadEntities[id] ?: simbadEntityRepository.find(id) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Cannot found sky object: [$id]") cachedSimbadEntities[id] = target - val ephemeris = bodyEphemeris(target, location, LocalDateTime.of(date, LocalTime.now()), true) + val ephemeris = bodyEphemeris(target, location, LocalDateTime.of(date, LocalTime.now(SystemClock)), true) return altitudePointsOfBody(ephemeris, stepSize) } fun altitudePointsOfSatellite(location: GeographicCoordinate, satellite: SatelliteEntity, date: LocalDate, stepSize: Int): List { - val ephemeris = bodyEphemeris("TLE@${satellite.tle}", location, LocalDateTime.of(date, LocalTime.now()), true) + val ephemeris = bodyEphemeris("TLE@${satellite.tle}", location, LocalDateTime.of(date, LocalTime.now(SystemClock)), true) return altitudePointsOfBody(ephemeris, stepSize) } diff --git a/api/src/main/kotlin/nebulosa/api/beans/converters/time/DateAndTimeParamMethodArgumentResolver.kt b/api/src/main/kotlin/nebulosa/api/beans/converters/time/DateAndTimeParamMethodArgumentResolver.kt index 539204254..9574c4e70 100644 --- a/api/src/main/kotlin/nebulosa/api/beans/converters/time/DateAndTimeParamMethodArgumentResolver.kt +++ b/api/src/main/kotlin/nebulosa/api/beans/converters/time/DateAndTimeParamMethodArgumentResolver.kt @@ -3,6 +3,7 @@ package nebulosa.api.beans.converters.time import nebulosa.api.beans.converters.annotation import nebulosa.api.beans.converters.hasAnnotation import nebulosa.api.beans.converters.parameter +import nebulosa.time.SystemClock import org.springframework.core.MethodParameter import org.springframework.stereotype.Component import org.springframework.web.bind.support.WebDataBinderFactory @@ -36,17 +37,17 @@ class DateAndTimeParamMethodArgumentResolver : HandlerMethodArgumentResolver { val date = dateValue ?.let { LocalDate.parse(it, DateTimeFormatter.ofPattern(dateAndTimeParam.datePattern)) } - ?: if (dateAndTimeParam.nullable) null else LocalDate.now() + ?: if (dateAndTimeParam.nullable) null else LocalDate.now(SystemClock) if (type === LocalDate::class.java) return date val time = timeValue ?.let { LocalTime.parse(it, DateTimeFormatter.ofPattern(dateAndTimeParam.timePattern)) } - ?: if (dateAndTimeParam.nullable) null else LocalTime.now() + ?: if (dateAndTimeParam.nullable) null else LocalTime.now(SystemClock) if (type === LocalTime::class.java) return time - return LocalDateTime.of(date ?: LocalDate.now(), time ?: LocalTime.now()) + return LocalDateTime.of(date ?: LocalDate.now(SystemClock), time ?: LocalTime.now(SystemClock)) .let { if (dateAndTimeParam.noSeconds) it.withSecond(0).withNano(0) else it } } } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/AutoSubFolderMode.kt b/api/src/main/kotlin/nebulosa/api/cameras/AutoSubFolderMode.kt index 3326d9570..aa0f46793 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/AutoSubFolderMode.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/AutoSubFolderMode.kt @@ -1,5 +1,6 @@ package nebulosa.api.cameras +import nebulosa.time.SystemClock import java.nio.file.Path import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -17,6 +18,7 @@ enum class AutoSubFolderMode { } fun pathFor(parentPath: Path, dateTime: LocalDateTime? = null): Path { - return if (this == OFF) parentPath else Path.of("$parentPath", directoryNameAt(dateTime ?: LocalDateTime.now())) + return if (this == OFF) parentPath + else Path.of("$parentPath", directoryNameAt(dateTime ?: LocalDateTime.now(SystemClock))) } } diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt index 4596bb458..9debefd36 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt @@ -122,7 +122,7 @@ data class CameraExposureTask( null } else if (event.image != null) { outputPath.sink().use(event.image!!::write) - event.image?.first?.header + event.image?.first()?.header } else { LOG.warn("invalid event. event={}", event) return @@ -158,7 +158,7 @@ data class CameraExposureTask( val now = LocalDateTime.now(formatter.clock) val savePath = autoSubFolderMode.pathFor(savePath, now) val format = namingFormat.formatFor(frameType) - val fileName = formatter.format(format, header ?: outputPath.fits().use { it.first!!.header }) + val fileName = formatter.format(format, header ?: outputPath.fits().use { it.first().header }) Path.of("$savePath", "$fileName.fits") } else { Path.of("$savePath", "${formatter.camera.name}.fits") diff --git a/api/src/main/kotlin/nebulosa/api/image/ImageService.kt b/api/src/main/kotlin/nebulosa/api/image/ImageService.kt index ee4dc029f..c7f638bb3 100644 --- a/api/src/main/kotlin/nebulosa/api/image/ImageService.kt +++ b/api/src/main/kotlin/nebulosa/api/image/ImageService.kt @@ -26,6 +26,7 @@ import nebulosa.simbad.SimbadService import nebulosa.skycatalog.ClassificationType import nebulosa.skycatalog.SkyObject import nebulosa.skycatalog.SkyObjectType +import nebulosa.time.SystemClock import nebulosa.time.TimeYMDHMS import nebulosa.time.UTC import nebulosa.wcs.WCS @@ -109,6 +110,8 @@ class ImageService( output.contentType = "image/$format" ImageIO.write(transformedImage, format, output.outputStream) + + LOG.debug { "image opened. path=$path" } } private fun Image.transform( @@ -190,7 +193,7 @@ class ImageService( val annotations = Vector(64) val tasks = ArrayList>(2) - val dateTime = image.header.observationDate ?: LocalDateTime.now() + val dateTime = image.header.observationDate ?: LocalDateTime.now(SystemClock) if (request.minorPlanets) { threadPoolTaskExecutor.submitCompletable { diff --git a/api/src/main/kotlin/nebulosa/api/mounts/MountService.kt b/api/src/main/kotlin/nebulosa/api/mounts/MountService.kt index 876e6509e..b9d1235aa 100644 --- a/api/src/main/kotlin/nebulosa/api/mounts/MountService.kt +++ b/api/src/main/kotlin/nebulosa/api/mounts/MountService.kt @@ -20,6 +20,7 @@ import nebulosa.nova.position.Geoid import nebulosa.nova.position.ICRF import nebulosa.stellarium.protocol.StellariumProtocolServer import nebulosa.time.CurrentTime +import nebulosa.time.SystemClock import nebulosa.wcs.WCS import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode @@ -92,7 +93,7 @@ class MountService( * @return true if mount can slew to [mountPosition] coordinates. */ private fun verifyMountWillPointToSun(idempotencyKey: String, location: GeographicPosition, mountPosition: ICRF): Boolean { - val sunPosition = skyAtlasService.positionOfSun(location, LocalDateTime.now(), true) + val sunPosition = skyAtlasService.positionOfSun(location, LocalDateTime.now(SystemClock), true) .let { ICRF.equatorial(it.rightAscensionJ2000, it.declinationJ2000) } return if (sunPosition.separationFrom(mountPosition).toDegrees <= 1.0) { @@ -262,7 +263,7 @@ class MountService( if (meridianAt) { computeTimeLeftToMeridianFlip(rightAscension, computeLST(mount).also { computedLocation.lst = it }) .also { computedLocation.timeLeftToMeridianFlip = it } - .also { computedLocation.meridianAt = LocalDateTime.now().plusSeconds((it.toHours * 3600.0).toLong()) } + .also { computedLocation.meridianAt = LocalDateTime.now(SystemClock).plusSeconds((it.toHours * 3600.0).toLong()) } } computedLocation.pierSide = PierSide.expectedPierSide(computedLocation.rightAscension, computedLocation.declination, computeLST(mount)) diff --git a/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt b/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt index cc0c6660f..ba9b8e1c6 100644 --- a/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt +++ b/api/src/test/kotlin/CameraCaptureNamingFormatterTest.kt @@ -20,6 +20,7 @@ import nebulosa.indi.device.rotator.Rotator import nebulosa.indi.protocol.INDIProtocol import nebulosa.indi.protocol.PropertyState import nebulosa.math.* +import nebulosa.time.SystemClock import org.junit.jupiter.api.Test import java.time.* import java.util.* @@ -355,7 +356,7 @@ class CameraCaptureNamingFormatterTest { override val longitude = 0.0 override val latitude = 0.0 override val elevation = 0.0 - override val dateTime: OffsetDateTime = OffsetDateTime.now() + override val dateTime: OffsetDateTime = OffsetDateTime.now(SystemClock) override val canPark = true override val parking = false override val parked = false diff --git a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/mounts/ASCOMMount.kt b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/mounts/ASCOMMount.kt index dc79d320a..b540a3f68 100644 --- a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/mounts/ASCOMMount.kt +++ b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/mounts/ASCOMMount.kt @@ -13,6 +13,7 @@ import nebulosa.log.loggerFor import nebulosa.math.* import nebulosa.nova.position.ICRF import nebulosa.time.CurrentTime +import nebulosa.time.SystemClock import java.math.BigDecimal import java.time.Duration import java.time.OffsetDateTime @@ -53,7 +54,7 @@ data class ASCOMMount( @Volatile final override var longitude = 0.0 @Volatile final override var latitude = 0.0 @Volatile final override var elevation = 0.0 - @Volatile final override var dateTime = OffsetDateTime.now()!! + @Volatile final override var dateTime = OffsetDateTime.now(SystemClock)!! override val snoopedDevices = emptyList() @@ -269,7 +270,7 @@ data class ASCOMMount( longitude = 0.0 latitude = 0.0 elevation = 0.0 - dateTime = OffsetDateTime.now()!! + dateTime = OffsetDateTime.now(SystemClock)!! axisRates.clear() } diff --git a/nebulosa-lx200-protocol/src/main/kotlin/nebulosa/lx200/protocol/LX200ProtocolHandler.kt b/nebulosa-lx200-protocol/src/main/kotlin/nebulosa/lx200/protocol/LX200ProtocolHandler.kt index 2e1907d8b..591009c4e 100644 --- a/nebulosa-lx200-protocol/src/main/kotlin/nebulosa/lx200/protocol/LX200ProtocolHandler.kt +++ b/nebulosa-lx200-protocol/src/main/kotlin/nebulosa/lx200/protocol/LX200ProtocolHandler.kt @@ -7,6 +7,7 @@ import nebulosa.log.debug import nebulosa.log.loggerFor import nebulosa.math.deg import nebulosa.math.hours +import nebulosa.time.SystemClock import java.time.* import java.util.concurrent.atomic.AtomicBoolean @@ -16,9 +17,9 @@ class LX200ProtocolHandler(private val server: LX200ProtocolServer) : ChannelInb @Volatile private var rightAscension = 0.0 @Volatile private var declination = 0.0 - @Volatile private var date = LocalDate.now() - @Volatile private var time = LocalTime.now() - @Volatile private var offset = ZoneId.systemDefault().rules.getOffset(Instant.now()) + @Volatile private var date = LocalDate.now(SystemClock) + @Volatile private var time = LocalTime.now(SystemClock) + @Volatile private var offset = SystemClock.zone.rules.getOffset(Instant.now()) override fun handlerAdded(ctx: ChannelHandlerContext) { LOG.info("client connected. address={}", ctx.channel().remoteAddress()) @@ -54,9 +55,9 @@ class LX200ProtocolHandler(private val server: LX200ProtocolServer) : ChannelInb "#:GD#" -> ctx.writeAndFlush(LX200ProtocolMessage.DECPosition(server.declination)) "#:Gg#" -> ctx.writeAndFlush(LX200ProtocolMessage.Longitude(server.longitude)) "#:Gt#" -> ctx.writeAndFlush(LX200ProtocolMessage.Latitude(server.latitude)) - "#:GC#" -> ctx.writeAndFlush(LX200ProtocolMessage.Date(LocalDate.now())) - "#:GL#" -> ctx.writeAndFlush(LX200ProtocolMessage.Time(LocalTime.now())) - "#:GG#" -> ctx.writeAndFlush(LX200ProtocolMessage.ZoneOffset(ZoneId.systemDefault().rules.getOffset(Instant.now()).totalSeconds / 3600.0)) + "#:GC#" -> ctx.writeAndFlush(LX200ProtocolMessage.Date(LocalDate.now(SystemClock))) + "#:GL#" -> ctx.writeAndFlush(LX200ProtocolMessage.Time(LocalTime.now(SystemClock))) + "#:GG#" -> ctx.writeAndFlush(LX200ProtocolMessage.ZoneOffset(SystemClock.zone.rules.getOffset(Instant.now()).totalSeconds / 3600.0)) "#:GW#" -> ctx.writeAndFlush(LX200ProtocolMessage.Status("G", server.tracking, server.parked)) "#:CM#" -> { ctx.writeAndFlush(LX200ProtocolMessage.Zero) @@ -101,14 +102,14 @@ class LX200ProtocolHandler(private val server: LX200ProtocolServer) : ChannelInb ctx.writeAndFlush(LX200ProtocolMessage.Ok) time = LocalTime.parse(command.substring(4, command.length - 1), LX200ProtocolEncoder.CALENDAR_TIME_FORMAT) val localTime = OffsetDateTime.of(date, time, offset) - val utcTime = localTime.minusSeconds(ZoneId.systemDefault().rules.getOffset(Instant.now()).totalSeconds.toLong()) + val utcTime = localTime.minusSeconds(SystemClock.zone.rules.getOffset(Instant.now()).totalSeconds.toLong()) server.time(utcTime) } command.startsWith("#:SC") -> { ctx.writeAndFlush(LX200ProtocolMessage.Text("1Updating planetary data # #")) date = LocalDate.parse(command.substring(4, command.length - 1), LX200ProtocolEncoder.CALENDAR_DATE_FORMAT) val localTime = OffsetDateTime.of(date, time, offset) - val utcTime = localTime.minusSeconds(ZoneId.systemDefault().rules.getOffset(Instant.now()).totalSeconds.toLong()) + val utcTime = localTime.minusSeconds(SystemClock.zone.rules.getOffset(Instant.now()).totalSeconds.toLong()) server.time(utcTime) } command.startsWith("#:SG") -> { @@ -116,7 +117,7 @@ class LX200ProtocolHandler(private val server: LX200ProtocolServer) : ChannelInb val offsetInHours = -command.substring(4, command.length - 1).toDouble() offset = ZoneOffset.ofTotalSeconds((offsetInHours * 3600.0).toInt()) val localTime = OffsetDateTime.of(date, time, offset) - val utcTime = localTime.minusSeconds(ZoneId.systemDefault().rules.getOffset(Instant.now()).totalSeconds.toLong()) + val utcTime = localTime.minusSeconds(SystemClock.zone.rules.getOffset(Instant.now()).totalSeconds.toLong()) server.time(utcTime) } command.startsWith("#:Sr") -> ctx.updateRA(command.substring(4)) diff --git a/nebulosa-time/src/main/kotlin/nebulosa/time/SystemClock.kt b/nebulosa-time/src/main/kotlin/nebulosa/time/SystemClock.kt new file mode 100644 index 000000000..9021c3209 --- /dev/null +++ b/nebulosa-time/src/main/kotlin/nebulosa/time/SystemClock.kt @@ -0,0 +1,15 @@ +package nebulosa.time + +import java.time.Clock +import java.time.ZoneId + +object SystemClock : Clock() { + + private val clock = systemDefaultZone() + + override fun getZone() = ZoneId.systemDefault() + + override fun withZone(zone: ZoneId) = clock.withZone(zone) + + override fun instant() = clock.instant() +} diff --git a/nebulosa-time/src/test/kotlin/SystemClockTest.kt b/nebulosa-time/src/test/kotlin/SystemClockTest.kt new file mode 100644 index 000000000..09b50f117 --- /dev/null +++ b/nebulosa-time/src/test/kotlin/SystemClockTest.kt @@ -0,0 +1,22 @@ +import io.kotest.matchers.longs.shouldBeLessThanOrEqual +import io.kotest.matchers.types.shouldBeSameInstanceAs +import nebulosa.time.SystemClock +import org.junit.jupiter.api.Test +import java.time.LocalDateTime +import java.time.ZoneId +import java.time.temporal.ChronoUnit +import java.util.TimeZone + +class SystemClockTest { + + @Test + fun systemDefault() { + ChronoUnit.MICROS.between(LocalDateTime.now(SystemClock), LocalDateTime.now()) shouldBeLessThanOrEqual 1000L + SystemClock.zone shouldBeSameInstanceAs ZoneId.systemDefault() + + TimeZone.setDefault(TimeZone.getTimeZone("America/Manaus")) + + ChronoUnit.MICROS.between(LocalDateTime.now(SystemClock), LocalDateTime.now()) shouldBeLessThanOrEqual 1000L + SystemClock.zone shouldBeSameInstanceAs ZoneId.systemDefault() + } +} diff --git a/nebulosa-wcs/src/test/kotlin/LibWCSTest.kt b/nebulosa-wcs/src/test/kotlin/LibWCSTest.kt index d2053c6b6..b71772deb 100644 --- a/nebulosa-wcs/src/test/kotlin/LibWCSTest.kt +++ b/nebulosa-wcs/src/test/kotlin/LibWCSTest.kt @@ -172,7 +172,7 @@ class LibWCSTest { @JvmStatic private fun readHeaderFromFits(name: String): ReadableHeader { - return Path.of("src/test/resources/$name.fits").fits().use { it.first!!.header } + return Path.of("src/test/resources/$name.fits").fits().use { it.first().header } } } } From 7d045d0e41b23c5c21b9f106475c7c4b61571aa1 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Fri, 9 Aug 2024 23:13:48 -0300 Subject: [PATCH 101/104] [desktop]: Don't call closeImage on first image --- desktop/src/app/image/image.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop/src/app/image/image.component.ts b/desktop/src/app/image/image.component.ts index b5f5d2ab2..e3e552814 100644 --- a/desktop/src/app/image/image.component.ts +++ b/desktop/src/app/image/image.component.ts @@ -710,7 +710,7 @@ export class ImageComponent implements AfterViewInit, OnDestroy { if (data.path) { this.clearOverlay() - await this.loadImage(true) + await this.loadImage(!!this.imageInfo) } } From bcb4b16c31b7d840d56f35a6f3317ee0ac5c0019 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Fri, 9 Aug 2024 23:14:17 -0300 Subject: [PATCH 102/104] [desktop]: Fix Sky Atlas name for stars and dsos --- desktop/src/app/atlas/atlas.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop/src/app/atlas/atlas.component.html b/desktop/src/app/atlas/atlas.component.html index 840e598a0..f700b6b48 100644 --- a/desktop/src/app/atlas/atlas.component.html +++ b/desktop/src/app/atlas/atlas.component.html @@ -632,7 +632,7 @@ - {{ body.name }} + {{ body.name.replaceAll('|', ' ยท ') }} Date: Fri, 9 Aug 2024 23:44:02 -0300 Subject: [PATCH 103/104] [desktop]: Fix inaccessible image after capture started --- desktop/src/app/image/image.component.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/desktop/src/app/image/image.component.ts b/desktop/src/app/image/image.component.ts index e3e552814..09004ae16 100644 --- a/desktop/src/app/image/image.component.ts +++ b/desktop/src/app/image/image.component.ts @@ -689,7 +689,11 @@ export class ImageComponent implements AfterViewInit, OnDestroy { } private async loadImageFromOpenImage(data: OpenImage) { - Object.assign(this.imageData, data) + if (data.camera) this.imageData.camera = data.camera + if (data.path) this.imageData.path = data.path + this.imageData.source = data.source + if (data.title) this.imageData.title = data.title + if (data.capture) this.imageData.capture = data.capture // Not clicked on menu item. if (this.calibration.source === 'CAMERA' && this.transformation.calibrationGroup !== data.capture?.calibrationGroup) { @@ -1138,7 +1142,6 @@ export class ImageComponent implements AfterViewInit, OnDestroy { const imageWrapper = image.parentElement URL.revokeObjectURL(image.src) - console.log(image.src) if (!this.zoom.panZoom && imageWrapper) { const panZoom = createPanZoom(imageWrapper, { From 78a0b0840a1dcd73bc617efcf73c2029531dce47 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Fri, 9 Aug 2024 23:44:45 -0300 Subject: [PATCH 104/104] [api]: Ensure the temp image file is deleted after capture is finished --- api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt index 9debefd36..c592f3e53 100644 --- a/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt +++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraExposureTask.kt @@ -17,6 +17,7 @@ import java.time.Duration import java.time.LocalDateTime import java.util.concurrent.atomic.AtomicBoolean import kotlin.io.path.createParentDirectories +import kotlin.io.path.deleteIfExists import kotlin.io.path.moveTo import kotlin.io.path.outputStream @@ -112,6 +113,7 @@ data class CameraExposureTask( override fun close() { onCancel(CancellationSource.Close) + outputPath.deleteIfExists() super.close() }