From 53c2ddb2fa51b995bc508a91b2dbc2355c3bafa9 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 14 Dec 2025 23:40:25 -0600 Subject: [PATCH] New Templates (#586) * feat(librechat): add LibreChat blueprint with compose, toml, metadata, links and tags * fix: rename templates to template.toml * fix(librechat): rename api service to librechat in docker-compose.yml * Update blueprints/librechat/template.toml * Update blueprints/librechat/template.toml * fix(librechat): add version under [config] and remove stray [config.mounts] header * fix(librechat): remove predefined persistent volume mounts from template.toml * docs(librechat): add authentication reference link to docker-compose.yml * feat: add Rote template - Add Rote deployment template with frontend, backend, and PostgreSQL services - Configure domain routing for frontend (port 80) and backend (port 3000) - Set up automatic password generation and environment variables - Use latest image tag by default - Add logo and metadata to meta.json * fix: process meta.json to fix formatting and sorting * Update GitHub workflows to target 'canary' branch for meta validation * Update pnpm-lock.yaml to upgrade various dependencies, including '@codemirror/autocomplete', '@radix-ui/react-dialog', and React packages to their latest versions. This includes updates to '@types/react' and '@types/react-dom' for improved compatibility and performance. * Enhance GitHub workflows: add production deployment configuration and target 'canary' branch for pull requests. * Refactor GitHub workflow: comment out build preview steps for clarity and future modifications. * Remove unnecessary blank line in deploy-preview.yml for improved readability. * Refactor GitHub workflow: uncomment build preview steps for improved deployment process and clarity. * Update template.toml (#555) * Update template.toml * Update template.toml * Update template.toml * fix: change VITE_API_BASE to http:// for traefik.me compatibility * changed image from sknnr/enshrouded-dedicated-server to mornedhels/enshrouded-server for autoupdate and easier config * Add Openinary Template (#567) * feat: add Openinary template * feat: update Openinary configuration to support ALLOWED_ORIGIN and refactor domain variable * fix: correct DEFAULT_DOMAIN environment variable reference in docker-compose.yml (#562) * add rustfs template (#568) * feat: add pull request template for improved contribution guidelines * fix: update pull request template to clarify issue closing keywords * feat: add validation scripts and configuration for Docker Compose and template files - Introduced a GitHub Actions workflow to validate Docker Compose files and template.toml on pull requests. - Added helper functions for generating random values and processing variables in templates. - Implemented validation scripts for checking the structure, syntax, and best practices of Docker Compose and template files. - Created necessary TypeScript types and configuration files for the build scripts. * Add Passbolt template blueprint to Dokploy templates (#376) * feat(templates): add Passbolt blueprint for Dokploy - Add docker-compose.yml defining services for Passbolt and MariaDB - Create template.toml with configurable domain, email, and database credentials - Add meta.json with metadata, tags, and link to logo * fix(meta): sort meta.json entries * fix: passbolt template had several issues that broke deployment - env variables were using old array format, changed to new table format - mariadb healthcheck was broken (wrong command for mariadb 11) - missing volume mounts for gpg keys, jwt tokens, and database - setup instructions weren't visible to users, moved to docker-compose - email config had circular references causing warnings - tested admin user creation and confirmed working everything works now, fully tested * Update blueprints/passbolt/template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: Add Kokoro TTS FastAPI template (#353) (#403) * feat: Add Kokoro TTS FastAPI template (#353) - Add CPU-optimized docker-compose.yml with source build - Add GPU-optimized docker-compose-gpu.yml for NVIDIA support - Add comprehensive template.toml with OpenAI-compatible API docs - Add kokoro-tts.svg logo and meta.json entry - Support streaming audio, timestamps, and multi-language TTS - Resolves #353 * updated the meta.json for the build errors * removed the docker-compose-gpu.yml file * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * chore: remove package-lock.json file from the app directory * chore: update Tolgee to latest version and fix SMTP config typo (#432) * chore: update Tolgee to latest version and fix SMTP config typo * Update docker-compose.yml * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix: improve Docker Compose validation workflow to handle subshell issues - Converted the handling of COMPOSE_FILES from a pipe to an array to ensure error propagation in the parent shell. - Updated the loop to iterate over the array for better reliability in the validation process. * refactor: enhance Docker Compose validation workflow to improve error handling - Replaced the pipe with an array to handle directory names, ensuring that errors within the loop propagate correctly to the parent shell. - Updated the loop structure for better reliability in processing the directories. * Feat: Add parseable (#460) * Add parseable * Update docker-compose.yml * Update docker-compose.yml * Update blueprints/parseable/template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * feat: add ChirpStack LoRaWAN Network Server template (#486) * feat: add ChirpStack LoRaWAN Network Server template Add complete ChirpStack v4 template with: - Main ChirpStack server with web UI - UDP and Basics Station gateway bridges - REST API interface - PostgreSQL database with PostGIS extensions - Redis cache - Mosquitto MQTT broker Default configuration for EU868 region with secure random credentials. Supports all LoRaWAN frequency bands globally. * fix(chirpstack): use original configurations from chirpstack-docker repo Update template.toml to use exact configuration files from the chirpstack-docker repository instead of simplified versions: - Use original chirpstack.toml with all 15 enabled regions - Use original gateway bridge configuration with documentation links - Use complete Basics Station EU868 config with frequency plans - Keep original Mosquitto and PostgreSQL initialization scripts Template size increased from 131 to 219 lines (4.7KB) to include comprehensive default configurations that match the official setup. * feat: add all 38 region configuration files * fix(chirpstack): add volume mounts to expose config files to containers * fix(chirpstack): remove read-only flag * fix(chirpstack): correct file paths for configuration mounts in docker-compose and template files * fix: update volume paths to be on correct directory level * fix: configure template for dokploy-network with proper DNS resolution - Add dokploy-network configuration to docker-compose.yml - Replace environment variable placeholders with actual service hostnames - Change PostgreSQL DSN from $POSTGRESQL_HOST to postgres - Change Redis server from $REDIS_HOST to redis - Replace $MQTT_BROKER_HOST with mosquitto in all 39 region configurations These changes ensure Docker DNS resolution works correctly by: - Using dokploy-network (overlay) instead of bridge network - Using service names directly in TOML config files (TOML doesn't expand env vars) - Enabling proper service discovery between containers This resolves DNS resolution failures that caused ChirpStack to fail connecting to PostgreSQL and MQTT services during deployment. * fix: add missing network configurations for all services in docker-compose * feat: add internal services to config.domains for proper network configuration * Update docker-compose.yml * fix: enhance domain validation in template validator - Updated the TemplateValidator to ensure that if the 'host' field is provided, it must be a valid string. - Added comments to clarify that 'host' is optional for internal services. * refactor: remove redundant host validation in template validator - Removed the validation for the 'host' field in the TemplateValidator, as it is optional for internal services and does not require a type check if not provided. * refactor: remove internal service domain configurations from template - Eliminated the domain configurations for internal services (Postgres, Redis, Mosquitto) from the template.toml file, streamlining the configuration for better clarity and maintainability. --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * Update section title from 'Suggestions' to 'Requirements' * Feat : Add MCSManager template support (#521) (#522) * feat: Add MCSManager template support (#521) * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: Add MediaCMS template (#524) * Feat : Add Quant-Ux template -#173 (#525) * Feat : Add Quant-Ux template -#173 * Remove extra newline in docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix(rustdesk): use explicit ports, use port 21118 on hbbs instead of hbbr (#526) * fix: use explicit ports, use port 21118 on hbbs instead of hbbr * fix: whitespace character in rustdesk * feat: Add anytype template (#527) * add anytype template * sort * Update name field for Anytype in meta.json * Update meta.json * Update docker-compose.yml * Update blueprints/anytype/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * refactor: remove dokploy-network configurations from multiple docker-compose files - Removed the external dokploy-network configuration from various services' docker-compose.yml files to streamline network management. - This change simplifies the setup and ensures consistency across blueprints. * chore: upgrade Infisical from v0.90.1 to v0.135.0 (#529) * chore: upgrade Infisical from v0.90.1 to v0.135.0 * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix: update pull request template link for clarity - Changed the link in the pull request template from 'general suggestions' to 'general requirements' to better reflect the content and ensure users follow the correct guidelines when creating templates. * chore: add section for screenshots or videos in pull request template - Introduced a new section in the pull request template to encourage contributors to include screenshots or videos, enhancing the clarity and context of their submissions. * Feat : Add MuleSoft ESB Runtime Template (#498) * added the mulesoft esb template * updated the compose and the meta.json * feat(mulesoft-esb): update image and add dynamic env configuration - Updated image to hari1367709/mule-esb:latest - Added dynamic HTTP_PORT for runtime port configuration - Added MULE_VERSION environment variable for Mule ESB version selection * updated the meta.json to use the version as latest * added a comment line to the template file * updated the mule runtime image * fix(mulesoft-esb): update ports configuration to follow guidelines * updated the port to use the env(HTTP_PORT) * Update docker-compose.yml * Update docker-compose.yml * Update blueprints/mulesoft-esb/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat(blueprint): update trmnl-byos-laravel template (#533) * feat(blueprint): update trmnl-byos-laravel template * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat(blueprint): peerdb template (#579) * feat(blueprint): initial attempt at peerdb template * fix: entrypoint and healthcheck * fix: entrypoint * fix: temporarily remove network * fix: temporal port * chore: remove 36987 for minio * fix: remove peerdb 9900 port exposure * fix: port for console * fix: minio env fix * fix: expose peerdb and minio to dokploy network * fix(peerdb): add defaults * fix: remove extra hosts * fix: remove network entries * fix: use consistent environment variables * feat: add Bluesky PDS template (#542) * feat: Bluesky PDS template * chore: add bluesky pds svg * chore: metadata for bluesky pds * yaml > yml * pnpm lock * fix: correct rotation key config * fix volumes * fix: volumes in the pds compose * define volumes in compose * fix: 32 bit rotation key * create pds.env correctly * some extra fixes * more extra fixes * a blank line * update pnpm lock * Add dokploy-prom-monitoring-extension template with comprehensive tests and documentation (#548) * Add dokploy-prom-monitoring-extension template with comprehensive tests and documentation * Fix METRICS_CONFIG environment variable: use single-line JSON format * Fix template.toml: use correct [config.env] syntax for environment variables * Fix docker-compose.yml: add env_file reference to load environment variables * Delete blueprints/dokploy-prom-monitoring-extension/README.md * Delete test-dokploy-prom-monitoring-extension.sh --------- Co-authored-by: Sanjeevi Subramani Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: improve RustDesk template configuration (#571) * feat: improve RustDesk template configuration - Add comprehensive environment variables for RustDesk server - Add RELAY_HOST, API_SERVER, ID_SERVER, and ENCRYPTION_KEY variables - Follow Dokploy best practices (no container_name, proper port format) - Use restart: unless-stopped policy - Add encryption key generation with password helper * fix: use explicit port mapping for RustDesk services RustDesk requires explicit port bindings (host:container format) to function properly. The service uses specific ports for: - 21115-21116 (TCP/UDP): hbbs service for ID and NAT traversal - 21117-21119 (TCP): hbbr relay service Without explicit port mapping, RustDesk clients cannot establish connections to the server. This is an exception to Dokploy's general port guidelines due to RustDesk's specific networking requirements. --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: add Mumble voice chat server template (#572) * feat: add Mumble voice chat server template - Add Mumble VoIP server blueprint with docker-compose.yml - Configure environment variables for superuser password, welcome text, and max users - Add template.toml with auto-generated secure password - Follow Dokploy best practices (no container_name, proper port format) - Add Mumble metadata to meta.json with proper tags - Support for TCP and UDP on port 64738 * Update template.toml * fix: correct JSON formatting in meta.json for Mumble template entry --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * fix: update WireGuard Easy template for proper functionality (#573) * fix: update WireGuard Easy template for proper functionality - Changed to named volume (etc_wireguard) instead of host path mount - Added explicit port mappings (51820:51820/udp, 51821:51821/tcp) required for WireGuard - Updated environment variables to use correct WG_HOST and PASSWORD format - Added all required WireGuard environment variables: - WG_PORT, PORT, WG_MTU, WG_DEFAULT_DNS, WG_ALLOWED_IPS - WG_POST_UP/WG_POST_DOWN for iptables rules - Added NET_RAW capability for proper network operations - Simplified template.toml to use WIREGUARD_HOST and WIREGUARD_PASSWORD - Removed explicit networks config to enable Dokploy's isolated deployment - Template now works with Dokploy's automatic network isolation This configuration has been tested and confirmed working with isolated deployment enabled. * Update template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * add: restart policy to MinIO service (#576) restart: unless-stopped is a Docker restart policy that automatically restarts a container if it stops due to an error or Docker daemon restart --------- Co-authored-by: Sunil Shrestha Co-authored-by: Rabithua Co-authored-by: Mauricio Siu Co-authored-by: Scan <103391616+scanash00@users.noreply.github.com> Co-authored-by: Crackvignoule Co-authored-by: florianheysen <39408021+florianheysen@users.noreply.github.com> Co-authored-by: Thiago MadPin Co-authored-by: BlinkStrike <18644035+BlinkStrike@users.noreply.github.com> Co-authored-by: M Jupri Amin <127651222+Juupeee@users.noreply.github.com> Co-authored-by: Harikrishnan Dhanasekaran Co-authored-by: Kamil Dzieniszewski Co-authored-by: Nick Anderson Co-authored-by: lefolalan Co-authored-by: Chris <31969757+ChrisvanChip@users.noreply.github.com> Co-authored-by: kipavy <88386090+kipavy@users.noreply.github.com> Co-authored-by: Benjamin Nussbaum Co-authored-by: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com> Co-authored-by: Vidhya LKG for IT <24915474+VidhyaSanjeevi@users.noreply.github.com> Co-authored-by: Sanjeevi Subramani Co-authored-by: Muzaffer Kadir YILMAZ <34358176+muzafferkadir@users.noreply.github.com> Co-authored-by: Jemg --- .../pull_request_template.md | 7 +- .github/workflows/deploy-preview.yml | 4 +- ...s-production.yml => deploy-production.yml} | 0 .github/workflows/validate-docker-compose.yml | 317 + .github/workflows/validate-meta.yml | 4 +- .github/workflows/validate.yml | 4 +- .gitignore | 1 + README.md | 4 +- app/package-lock.json | 4248 ------- app/pnpm-lock.yaml | 1750 +-- blueprints/ackee/template.toml | 1 + blueprints/anytype/docker-compose.yml | 19 + blueprints/anytype/logo.png | Bin 0 -> 51321 bytes blueprints/anytype/template.toml | 4 + blueprints/bluesky-pds/bluesky-pds.svg | 3 + blueprints/bluesky-pds/docker-compose.yml | 48 + blueprints/bluesky-pds/template.toml | 36 + blueprints/budibase/docker-compose.yml | 3 - blueprints/chatwoot/docker-compose.yml | 6 - blueprints/chirpstack/chirpstack.png | Bin 0 -> 12023 bytes blueprints/chirpstack/docker-compose.yml | 81 + blueprints/chirpstack/template.toml | 9815 +++++++++++++++++ blueprints/conduit/docker-compose.yml | 6 - blueprints/discord-tickets/docker-compose.yml | 4 - blueprints/docmost/docker-compose.yml | 4 - .../docker-compose.yml | 11 + .../logo.svg | 21 + .../template.toml | 17 + blueprints/drawio/docker-compose.yml | 4 - blueprints/enshrouded/docker-compose.yml | 19 +- blueprints/evolutionapi/docker-compose.yml | 5 - blueprints/firecrawl/docker-compose.yml | 9 - blueprints/glpi/docker-compose.yml | 4 - blueprints/hi-events/docker-compose.yml | 4 - blueprints/immich/docker-compose.yml | 4 - blueprints/infisical/docker-compose.yml | 9 +- blueprints/invoiceshelf/docker-compose.yml | 4 - blueprints/kimai/docker-compose.yml | 4 - blueprints/kokoro-tts/docker-compose.yml | 23 + blueprints/kokoro-tts/kokoro-tts.svg | 12 + blueprints/kokoro-tts/template.toml | 72 + blueprints/kutt/docker-compose.yml | 2 +- blueprints/librechat/docker-compose.yml | 110 + blueprints/librechat/librechat.png | Bin 0 -> 59599 bytes blueprints/librechat/template.toml | 93 + blueprints/libredesk/docker-compose.yml | 3 - blueprints/logto/docker-compose.yml | 3 - blueprints/mcsmanager/docker-compose.yml | 29 + blueprints/mcsmanager/mcsmanager.png | Bin 0 -> 1132 bytes blueprints/mcsmanager/template.toml | 12 + blueprints/mediacms/docker-compose.yml | 134 + blueprints/mediacms/mediacms.svg | 6 + blueprints/mediacms/template.toml | 17 + blueprints/minio/docker-compose.yml | 2 +- blueprints/mulesoft-esb/docker-compose.yml | 22 + blueprints/mulesoft-esb/mulesoft_logo.png | Bin 0 -> 44699 bytes blueprints/mulesoft-esb/template.toml | 23 + blueprints/mumble/docker-compose.yml | 16 + blueprints/mumble/mumble.png | Bin 0 -> 2388 bytes blueprints/mumble/template.toml | 12 + blueprints/nextcloud-aio/docker-compose.yml | 4 - blueprints/openinary/docker-compose.yml | 26 + blueprints/openinary/openinary.svg | 18 + blueprints/openinary/template.toml | 40 + blueprints/parseable/docker-compose.yml | 23 + blueprints/parseable/logo.svg | 70 + blueprints/parseable/template.toml | 16 + blueprints/passbolt/docker-compose.yml | 79 + blueprints/passbolt/passbolt.svg | 8 + blueprints/passbolt/template.toml | 41 + blueprints/peerdb/docker-compose.yml | 187 + blueprints/peerdb/peerdb.jpeg | Bin 0 -> 10300 bytes blueprints/peerdb/template.toml | 93 + blueprints/peppermint/docker-compose.yml | 4 - blueprints/postiz/docker-compose.yml | 4 - blueprints/quant-ux/docker-compose.yml | 69 + blueprints/quant-ux/logo.svg | 2 + blueprints/quant-ux/template.toml | 50 + blueprints/rote/docker-compose.yml | 45 + blueprints/rote/rote.png | Bin 0 -> 55373 bytes blueprints/rote/template.toml | 23 + blueprints/roundcube/docker-compose.yml | 3 - blueprints/rustdesk/docker-compose.yml | 14 +- blueprints/rustdesk/template.toml | 5 + blueprints/rustfs/docker-compose.yml | 20 + blueprints/rustfs/logo.svg | 1 + blueprints/rustfs/meta-entry.json | 18 + blueprints/rustfs/template.toml | 25 + blueprints/slash/docker-compose.yml | 4 - blueprints/tolgee/docker-compose.yml | 4 +- blueprints/tolgee/template.toml | 3 +- blueprints/trilium/docker-compose.yml | 5 - .../trmnl-byos-laravel/docker-compose.yml | 3 +- blueprints/unifi/docker-compose.yml | 3 - blueprints/wg-easy/docker-compose.yml | 23 +- blueprints/wg-easy/template.toml | 18 +- blueprints/wikijs/docker-compose.yml | 3 - blueprints/windmill/docker-compose.yml | 3 - build-scripts/helpers.ts | 245 + build-scripts/package.json | 24 + build-scripts/pnpm-lock.yaml | 361 + build-scripts/tsconfig.json | 23 + build-scripts/type.ts | 879 ++ build-scripts/validate-docker-compose.ts | 357 + build-scripts/validate-template.ts | 622 ++ meta.json | 324 +- 106 files changed, 15667 insertions(+), 5200 deletions(-) rename .github/{PULL_REQUEST_TEMPLATE => }/pull_request_template.md (73%) rename .github/workflows/{cloudflare-pages-production.yml => deploy-production.yml} (100%) create mode 100644 .github/workflows/validate-docker-compose.yml create mode 100644 .gitignore delete mode 100644 app/package-lock.json create mode 100644 blueprints/anytype/docker-compose.yml create mode 100644 blueprints/anytype/logo.png create mode 100644 blueprints/anytype/template.toml create mode 100644 blueprints/bluesky-pds/bluesky-pds.svg create mode 100644 blueprints/bluesky-pds/docker-compose.yml create mode 100644 blueprints/bluesky-pds/template.toml create mode 100644 blueprints/chirpstack/chirpstack.png create mode 100644 blueprints/chirpstack/docker-compose.yml create mode 100644 blueprints/chirpstack/template.toml create mode 100644 blueprints/dokploy-prom-monitoring-extension/docker-compose.yml create mode 100644 blueprints/dokploy-prom-monitoring-extension/logo.svg create mode 100644 blueprints/dokploy-prom-monitoring-extension/template.toml create mode 100644 blueprints/kokoro-tts/docker-compose.yml create mode 100644 blueprints/kokoro-tts/kokoro-tts.svg create mode 100644 blueprints/kokoro-tts/template.toml create mode 100644 blueprints/librechat/docker-compose.yml create mode 100644 blueprints/librechat/librechat.png create mode 100644 blueprints/librechat/template.toml create mode 100644 blueprints/mcsmanager/docker-compose.yml create mode 100644 blueprints/mcsmanager/mcsmanager.png create mode 100644 blueprints/mcsmanager/template.toml create mode 100644 blueprints/mediacms/docker-compose.yml create mode 100644 blueprints/mediacms/mediacms.svg create mode 100644 blueprints/mediacms/template.toml create mode 100644 blueprints/mulesoft-esb/docker-compose.yml create mode 100644 blueprints/mulesoft-esb/mulesoft_logo.png create mode 100644 blueprints/mulesoft-esb/template.toml create mode 100644 blueprints/mumble/docker-compose.yml create mode 100644 blueprints/mumble/mumble.png create mode 100644 blueprints/mumble/template.toml create mode 100644 blueprints/openinary/docker-compose.yml create mode 100644 blueprints/openinary/openinary.svg create mode 100644 blueprints/openinary/template.toml create mode 100644 blueprints/parseable/docker-compose.yml create mode 100644 blueprints/parseable/logo.svg create mode 100644 blueprints/parseable/template.toml create mode 100644 blueprints/passbolt/docker-compose.yml create mode 100644 blueprints/passbolt/passbolt.svg create mode 100644 blueprints/passbolt/template.toml create mode 100644 blueprints/peerdb/docker-compose.yml create mode 100644 blueprints/peerdb/peerdb.jpeg create mode 100644 blueprints/peerdb/template.toml create mode 100644 blueprints/quant-ux/docker-compose.yml create mode 100644 blueprints/quant-ux/logo.svg create mode 100644 blueprints/quant-ux/template.toml create mode 100644 blueprints/rote/docker-compose.yml create mode 100644 blueprints/rote/rote.png create mode 100644 blueprints/rote/template.toml create mode 100644 blueprints/rustfs/docker-compose.yml create mode 100644 blueprints/rustfs/logo.svg create mode 100644 blueprints/rustfs/meta-entry.json create mode 100644 blueprints/rustfs/template.toml create mode 100644 build-scripts/helpers.ts create mode 100644 build-scripts/package.json create mode 100644 build-scripts/pnpm-lock.yaml create mode 100644 build-scripts/tsconfig.json create mode 100644 build-scripts/type.ts create mode 100644 build-scripts/validate-docker-compose.ts create mode 100644 build-scripts/validate-template.ts diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/pull_request_template.md similarity index 73% rename from .github/PULL_REQUEST_TEMPLATE/pull_request_template.md rename to .github/pull_request_template.md index 0c5e03d5..aa99ffae 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,12 +6,13 @@ New PR of [Template Name] Before submitting this PR, please make sure that: -- [ ] I have read the suggestions in the README.md file https://github.com/Dokploy/templates?tab=readme-ov-file#general-suggestions-when-creating-a-template +- [ ] I have read the suggestions in the README.md file https://github.com/Dokploy/templates?tab=readme-ov-file#general-requirements-when-creating-a-template - [ ] I have tested the template in my instance, so the maintainers don't spend time trying to figure out what's wrong. - [ ] I have added tests that demonstrate that my correction works or that my new feature works. ## Issues related (if applicable) -Close automatically the related issues using the keywords: `closes #ISSUE_NUMBER`, `fixes #ISSUE_NUMBER`, `resolves #ISSUE_NUMBER` +Close automatically the related issues using the keywords: `closes #ISSUE_NUMBER` -Example: `closes #123` \ No newline at end of file + +## Screenshots or Videos diff --git a/.github/workflows/deploy-preview.yml b/.github/workflows/deploy-preview.yml index 2f067433..a342ac7a 100644 --- a/.github/workflows/deploy-preview.yml +++ b/.github/workflows/deploy-preview.yml @@ -5,7 +5,9 @@ on: workflows: [Build Preview Deployment] types: - completed - + pull_request: + branches: + - canary permissions: actions: read deployments: write diff --git a/.github/workflows/cloudflare-pages-production.yml b/.github/workflows/deploy-production.yml similarity index 100% rename from .github/workflows/cloudflare-pages-production.yml rename to .github/workflows/deploy-production.yml diff --git a/.github/workflows/validate-docker-compose.yml b/.github/workflows/validate-docker-compose.yml new file mode 100644 index 00000000..ddd16aab --- /dev/null +++ b/.github/workflows/validate-docker-compose.yml @@ -0,0 +1,317 @@ +name: Validate Docker Compose Files + +on: + pull_request: + branches: + - canary + paths: + - 'blueprints/**/docker-compose.yml' + - 'blueprints/**/template.toml' + workflow_dispatch: + +jobs: + validate-docker-compose: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Necesitamos el historial completo para comparar con base + + - name: Set up Docker Compose + run: | + echo "🐳 Setting up Docker Compose..." + # Docker Compose V2 viene preinstalado en ubuntu-latest + docker compose version + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20.16.0 + + - name: Set up pnpm + uses: pnpm/action-setup@v4 + with: + version: 8 + + - name: Install dependencies + run: | + echo "πŸ“¦ Installing Node.js dependencies..." + cd build-scripts && pnpm install + + - name: Get changed files + id: changed-files + run: | + echo "πŸ” Detecting changed files..." + + # Obtener la rama base + BASE_SHA=$(git merge-base HEAD origin/${{ github.base_ref }}) + + # Encontrar todos los archivos docker-compose.yml y template.toml modificados/agregados + CHANGED_COMPOSE=$(git diff --name-only --diff-filter=ACMRT $BASE_SHA HEAD | grep -E 'blueprints/.*/docker-compose\.yml$' || true) + CHANGED_TOML=$(git diff --name-only --diff-filter=ACMRT $BASE_SHA HEAD | grep -E 'blueprints/.*/template\.toml$' || true) + + # Crear lista de directorios ΓΊnicos que tienen cambios + CHANGED_DIRS=$(echo -e "$CHANGED_COMPOSE\n$CHANGED_TOML" | sed 's|blueprints/\([^/]*\)/.*|\1|' | sort -u) + + echo "Changed compose files:" + echo "$CHANGED_COMPOSE" | while read file; do [ -n "$file" ] && echo " - $file"; done + + echo "Changed TOML files:" + echo "$CHANGED_TOML" | while read file; do [ -n "$file" ] && echo " - $file"; done + + echo "Changed directories:" + echo "$CHANGED_DIRS" | while read dir; do [ -n "$dir" ] && echo " - $dir"; done + + # Guardar para usar en siguientes pasos + echo "compose_files<> $GITHUB_OUTPUT + echo "$CHANGED_COMPOSE" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + echo "toml_files<> $GITHUB_OUTPUT + echo "$CHANGED_TOML" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + echo "directories<> $GITHUB_OUTPUT + echo "$CHANGED_DIRS" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Validate Docker Compose files syntax + id: validate-compose-syntax + run: | + echo "πŸ” Validating Docker Compose files syntax..." + + ERROR=0 + COMPOSE_FILES="${{ steps.changed-files.outputs.compose_files }}" + + if [ -z "$COMPOSE_FILES" ]; then + echo "ℹ️ No docker-compose.yml files changed, skipping validation" + exit 0 + fi + + echo "$COMPOSE_FILES" | while read -r compose_file; do + if [ -z "$compose_file" ]; then + continue + fi + + TEMPLATE_DIR=$(dirname "$compose_file") + TEMPLATE_NAME=$(basename "$TEMPLATE_DIR") + + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "πŸ“¦ Validating syntax: $TEMPLATE_NAME" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + # Validar sintaxis de docker-compose.yml usando docker compose + echo "πŸ” Validating docker-compose.yml syntax..." + if ! docker compose -f "$compose_file" config > /dev/null 2>&1; then + echo "❌ ERROR: docker-compose.yml syntax is invalid in $TEMPLATE_NAME" + echo "Running docker compose config to show errors:" + docker compose -f "$compose_file" config 2>&1 || true + ERROR=1 + else + echo "βœ… docker-compose.yml syntax is valid" + fi + + # Obtener lista de servicios del compose + SERVICES=$(docker compose -f "$compose_file" config --services 2>/dev/null || echo "") + echo "πŸ“‹ Services found in docker-compose.yml:" + echo "$SERVICES" | while read service; do + [ -n "$service" ] && echo " - $service" + done + + # Guardar servicios para validaciΓ³n posterior + echo "$SERVICES" > "/tmp/${TEMPLATE_NAME}_services.txt" + done + + if [ $ERROR -eq 1 ]; then + echo "" + echo "❌ Docker Compose syntax validation failed" + exit 1 + else + echo "" + echo "βœ… All Docker Compose files have valid syntax" + fi + + - name: Validate Docker Compose best practices + id: validate-compose-practices + run: | + echo "πŸ” Validating Docker Compose best practices..." + + ERROR=0 + COMPOSE_FILES="${{ steps.changed-files.outputs.compose_files }}" + + if [ -z "$COMPOSE_FILES" ]; then + echo "ℹ️ No docker-compose.yml files changed, skipping validation" + exit 0 + fi + + # Convert to array to avoid subshell issues with pipe + # This ensures ERROR=1 inside the loop propagates to the parent shell + mapfile -t COMPOSE_ARRAY <<< "$COMPOSE_FILES" + + for compose_file in "${COMPOSE_ARRAY[@]}"; do + if [ -z "$compose_file" ]; then + continue + fi + + TEMPLATE_DIR=$(dirname "$compose_file") + TEMPLATE_NAME=$(basename "$TEMPLATE_DIR") + + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "πŸ“¦ Validating best practices: $TEMPLATE_NAME" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + # Validar usando el script de TypeScript + if ! (cd build-scripts && pnpm exec tsx validate-docker-compose.ts --file "../$compose_file" --verbose); then + ERROR=1 + fi + done + + if [ $ERROR -eq 1 ]; then + echo "" + echo "❌ Docker Compose best practices validation failed" + exit 1 + else + echo "" + echo "βœ… All Docker Compose files follow best practices" + fi + + - name: Validate template.toml files + id: validate-toml + run: | + echo "πŸ” Validating template.toml files..." + + ERROR=0 + DIRECTORIES="${{ steps.changed-files.outputs.directories }}" + + if [ -z "$DIRECTORIES" ]; then + echo "ℹ️ No template directories changed, skipping TOML validation" + exit 0 + fi + + # Convert to array to avoid subshell issues with pipe + # This ensures ERROR=1 inside the loop propagates to the parent shell + mapfile -t DIRS_ARRAY <<< "$DIRECTORIES" + + for template_dir in "${DIRS_ARRAY[@]}"; do + if [ -z "$template_dir" ]; then + continue + fi + + TEMPLATE_PATH="blueprints/$template_dir" + TOML_FILE="$TEMPLATE_PATH/template.toml" + + if [ ! -f "$TOML_FILE" ]; then + echo "⚠️ WARNING: template.toml not found in $template_dir (might be deleted)" + continue + fi + + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "πŸ“ Validating: $template_dir/template.toml" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + # Validar usando el script de TypeScript con tsx + # Ejecutar desde build-scripts para tener acceso a node_modules + if ! (cd build-scripts && pnpm exec tsx validate-template.ts --dir "../$TEMPLATE_PATH" --verbose); then + ERROR=1 + fi + done + + if [ $ERROR -eq 1 ]; then + echo "" + echo "❌ template.toml validation failed" + exit 1 + else + echo "" + echo "βœ… All template.toml files are valid" + fi + + - name: Test Docker Compose (dry-run) + id: test-compose + run: | + echo "πŸ§ͺ Testing Docker Compose files (dry-run)..." + + ERROR=0 + DIRECTORIES="${{ steps.changed-files.outputs.directories }}" + + if [ -z "$DIRECTORIES" ]; then + echo "ℹ️ No template directories changed, skipping dry-run test" + exit 0 + fi + + echo "$DIRECTORIES" | while read -r template_dir; do + if [ -z "$template_dir" ]; then + continue + fi + + COMPOSE_FILE="blueprints/$template_dir/docker-compose.yml" + + if [ ! -f "$COMPOSE_FILE" ]; then + continue + fi + + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "πŸ§ͺ Testing: $template_dir" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + # Cambiar al directorio del template para resolver rutas relativas + cd "blueprints/$template_dir" + + # Validar que docker-compose puede parsear el archivo completamente + echo "πŸ” Running docker compose config (full validation)..." + if docker compose config > /dev/null 2>&1; then + echo "βœ… Docker Compose file is fully valid and can be processed" + + # Mostrar informaciΓ³n ΓΊtil + echo "πŸ“‹ Configuration summary:" + docker compose config --services | while read service; do + [ -n "$service" ] && echo " Service: $service" + done + else + echo "❌ ERROR: Docker Compose file failed full validation" + docker compose config 2>&1 || true + ERROR=1 + fi + + cd - > /dev/null + done + + if [ $ERROR -eq 1 ]; then + echo "" + echo "❌ Docker Compose dry-run test failed" + exit 1 + else + echo "" + echo "βœ… All Docker Compose files passed dry-run test" + fi + + - name: Summary + if: always() + run: | + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "πŸ“Š Validation Summary" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + if [ "${{ steps.validate-compose-syntax.outcome }}" == "success" ] && \ + [ "${{ steps.validate-compose-practices.outcome }}" == "success" ] && \ + [ "${{ steps.validate-toml.outcome }}" == "success" ] && \ + [ "${{ steps.test-compose.outcome }}" == "success" ]; then + echo "βœ… All validations passed!" + echo "" + echo "Your Docker Compose and template.toml files are valid and ready to merge." + else + echo "❌ Some validations failed. Please review the errors above." + echo "" + echo "Common issues to check:" + echo " - docker-compose.yml syntax errors" + echo " - template.toml syntax errors" + echo " - serviceName in template.toml must match service names in docker-compose.yml" + echo " - Avoid using container_name, explicit networks, or port mappings" + fi + diff --git a/.github/workflows/validate-meta.yml b/.github/workflows/validate-meta.yml index a394e7ec..8f9acb7a 100644 --- a/.github/workflows/validate-meta.yml +++ b/.github/workflows/validate-meta.yml @@ -2,10 +2,10 @@ name: Validate and Process Meta.json on: push: - branches: [main, master, develop] + branches: [canary] paths: ["meta.json"] pull_request: - branches: [main, master] + branches: [canary] paths: ["meta.json"] workflow_dispatch: diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 48cfaa8c..3e749b35 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -3,10 +3,10 @@ name: Validate Blueprints Structure and Meta on: pull_request: branches: - - main + - canary push: branches: - - main + - canary jobs: validate: diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/README.md b/README.md index 81ac50e3..b774c972 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ We have a few helpers that are very common when creating a template, these are: -## General Suggestions when creating a template +## General Requirements when creating a template - Don't use this way in your docker compose file: @@ -225,4 +225,4 @@ services: 6. Now you can click on the Deploy Button and wait for the deployment to finish, and try to access to the service, if everything is correct you should access to the service and see the template working. -use the command `node dedupe-and-sort-meta.js` to deduplicate and sort the meta.json file. \ No newline at end of file +use the command `node dedupe-and-sort-meta.js` to deduplicate and sort the meta.json file. diff --git a/app/package-lock.json b/app/package-lock.json deleted file mode 100644 index 9579d3d9..00000000 --- a/app/package-lock.json +++ /dev/null @@ -1,4248 +0,0 @@ -{ - "name": "my-app", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "my-app", - "version": "0.0.0", - "dependencies": { - "@codemirror/autocomplete": "^6.18.6", - "@codemirror/lang-json": "^6.0.1", - "@codemirror/lang-yaml": "^6.1.1", - "@codemirror/language": "^6.10.1", - "@codemirror/legacy-modes": "6.4.0", - "@codemirror/view": "6.29.0", - "@iarna/toml": "^2.2.5", - "@radix-ui/react-dialog": "^1.1.6", - "@radix-ui/react-dropdown-menu": "^2.1.6", - "@radix-ui/react-label": "^2.1.2", - "@radix-ui/react-popover": "^1.1.6", - "@radix-ui/react-slot": "^1.1.2", - "@radix-ui/react-tabs": "^1.1.3", - "@tailwindcss/vite": "^4.0.12", - "@uiw/codemirror-theme-github": "^4.22.1", - "@uiw/react-codemirror": "^4.22.1", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "cmdk": "1.0.0", - "copy-to-clipboard": "^3.3.3", - "lucide-react": "^0.479.0", - "next-themes": "^0.4.5", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "react-router-dom": "^7.4.1", - "sonner": "^2.0.1", - "tailwind-merge": "^3.0.2", - "tailwindcss": "^4.0.12", - "tailwindcss-animate": "^1.0.7", - "vite-plugin-static-copy": "^2.3.2", - "yaml": "2.7.1", - "zustand": "^5.0.3" - }, - "devDependencies": { - "@types/node": "^20.8.2", - "@types/react": "^19.0.10", - "@types/react-dom": "^19.0.4", - "@vitejs/plugin-react": "^4.3.4", - "globals": "^15.15.0", - "typescript": "~5.7.2", - "vite": "^6.2.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", - "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", - "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", - "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.28.0", - "@babel/types": "^7.28.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", - "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", - "dev": true, - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", - "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.28.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", - "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", - "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@codemirror/autocomplete": { - "version": "6.18.6", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz", - "integrity": "sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@codemirror/commands": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz", - "integrity": "sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.27.0", - "@lezer/common": "^1.1.0" - } - }, - "node_modules/@codemirror/lang-json": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", - "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@lezer/json": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-yaml": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.2.tgz", - "integrity": "sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.2.0", - "@lezer/lr": "^1.0.0", - "@lezer/yaml": "^1.0.0" - } - }, - "node_modules/@codemirror/language": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.2.tgz", - "integrity": "sha512-p44TsNArL4IVXDTbapUmEkAlvWs2CFQbcfc0ymDsis1kH2wh0gcY96AS29c/vp2d0y2Tquk1EDSaawpzilUiAw==", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.23.0", - "@lezer/common": "^1.1.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0", - "style-mod": "^4.0.0" - } - }, - "node_modules/@codemirror/legacy-modes": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.4.0.tgz", - "integrity": "sha512-5m/K+1A6gYR0e+h/dEde7LoGimMjRtWXZFg4Lo70cc8HzjSdHe3fLwjWMR0VRl5KFT1SxalSap7uMgPKF28wBA==", - "dependencies": { - "@codemirror/language": "^6.0.0" - } - }, - "node_modules/@codemirror/lint": { - "version": "6.8.5", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.5.tgz", - "integrity": "sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.35.0", - "crelt": "^1.0.5" - } - }, - "node_modules/@codemirror/lint/node_modules/@codemirror/view": { - "version": "6.38.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.1.tgz", - "integrity": "sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ==", - "dependencies": { - "@codemirror/state": "^6.5.0", - "crelt": "^1.0.6", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, - "node_modules/@codemirror/search": { - "version": "6.5.11", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz", - "integrity": "sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, - "node_modules/@codemirror/state": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", - "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", - "dependencies": { - "@marijn/find-cluster-break": "^1.0.0" - } - }, - "node_modules/@codemirror/theme-one-dark": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz", - "integrity": "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/highlight": "^1.0.0" - } - }, - "node_modules/@codemirror/view": { - "version": "6.29.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.29.0.tgz", - "integrity": "sha512-ED4ims4fkf7eOA+HYLVP8VVg3NMllt1FPm9PEJBfYFnidKlRITBaua38u68L1F60eNtw2YNcDN5jsIzhKZwWQA==", - "dependencies": { - "@codemirror/state": "^6.4.0", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", - "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", - "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", - "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", - "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", - "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", - "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", - "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", - "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", - "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", - "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", - "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", - "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", - "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", - "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", - "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", - "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", - "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", - "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", - "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", - "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", - "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", - "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", - "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", - "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", - "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", - "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.2.tgz", - "integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==", - "dependencies": { - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.2.tgz", - "integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==", - "dependencies": { - "@floating-ui/core": "^1.7.2", - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.4.tgz", - "integrity": "sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw==", - "dependencies": { - "@floating-ui/dom": "^1.7.2" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", - "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==" - }, - "node_modules/@iarna/toml": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", - "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==" - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", - "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", - "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@lezer/common": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", - "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==" - }, - "node_modules/@lezer/highlight": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", - "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lezer/json": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", - "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/lr": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", - "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lezer/yaml": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz", - "integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.4.0" - } - }, - "node_modules/@marijn/find-cluster-break": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", - "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==" - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@radix-ui/primitive": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", - "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==" - }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", - "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-collection": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", - "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dialog": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz", - "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==", - "dependencies": { - "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.10", - "@radix-ui/react-focus-guards": "1.1.2", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-direction": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", - "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz", - "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", - "dependencies": { - "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-escape-keydown": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.15.tgz", - "integrity": "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==", - "dependencies": { - "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-menu": "2.1.15", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz", - "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", - "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-id": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-label": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", - "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.15.tgz", - "integrity": "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==", - "dependencies": { - "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.10", - "@radix-ui/react-focus-guards": "1.1.2", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.7", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.10", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popover": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.14.tgz", - "integrity": "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==", - "dependencies": { - "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.10", - "@radix-ui/react-focus-guards": "1.1.2", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.7", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz", - "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==", - "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-rect": "1.1.1", - "@radix-ui/react-use-size": "1.1.1", - "@radix-ui/rect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", - "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-presence": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz", - "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz", - "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==", - "dependencies": { - "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.12.tgz", - "integrity": "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==", - "dependencies": { - "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.10", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", - "dependencies": { - "@radix-ui/react-use-effect-event": "0.0.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", - "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", - "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", - "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", - "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", - "dependencies": { - "@radix-ui/rect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", - "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", - "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==" - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", - "dev": true - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.1.tgz", - "integrity": "sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.1.tgz", - "integrity": "sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.1.tgz", - "integrity": "sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.1.tgz", - "integrity": "sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.1.tgz", - "integrity": "sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.1.tgz", - "integrity": "sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.1.tgz", - "integrity": "sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.1.tgz", - "integrity": "sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.1.tgz", - "integrity": "sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.1.tgz", - "integrity": "sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.1.tgz", - "integrity": "sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.1.tgz", - "integrity": "sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.1.tgz", - "integrity": "sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.1.tgz", - "integrity": "sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.1.tgz", - "integrity": "sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.1.tgz", - "integrity": "sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.1.tgz", - "integrity": "sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.1.tgz", - "integrity": "sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.1.tgz", - "integrity": "sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.1.tgz", - "integrity": "sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@tailwindcss/node": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", - "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", - "dependencies": { - "@ampproject/remapping": "^2.3.0", - "enhanced-resolve": "^5.18.1", - "jiti": "^2.4.2", - "lightningcss": "1.30.1", - "magic-string": "^0.30.17", - "source-map-js": "^1.2.1", - "tailwindcss": "4.1.11" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", - "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", - "hasInstallScript": true, - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.4.3" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.11", - "@tailwindcss/oxide-darwin-arm64": "4.1.11", - "@tailwindcss/oxide-darwin-x64": "4.1.11", - "@tailwindcss/oxide-freebsd-x64": "4.1.11", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", - "@tailwindcss/oxide-linux-x64-musl": "4.1.11", - "@tailwindcss/oxide-wasm32-wasi": "4.1.11", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", - "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", - "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", - "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", - "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", - "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", - "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", - "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", - "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", - "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", - "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@emnapi/wasi-threads": "^1.0.2", - "@napi-rs/wasm-runtime": "^0.2.11", - "@tybys/wasm-util": "^0.9.0", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", - "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", - "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/vite": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", - "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==", - "dependencies": { - "@tailwindcss/node": "4.1.11", - "@tailwindcss/oxide": "4.1.11", - "tailwindcss": "4.1.11" - }, - "peerDependencies": { - "vite": "^5.2.0 || ^6 || ^7" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.19.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz", - "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==", - "dev": true, - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/react": { - "version": "19.1.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", - "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", - "dev": true, - "dependencies": { - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz", - "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==", - "dev": true, - "peerDependencies": { - "@types/react": "^19.0.0" - } - }, - "node_modules/@uiw/codemirror-extensions-basic-setup": { - "version": "4.24.1", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.24.1.tgz", - "integrity": "sha512-o1m1a8eUS3fWERMbDFvN8t8sZUFPgDKNemmlQ5Ot2vKm+Ax84lKP1dhEFgkiOaZ1bDHk4T5h6SjHuTghrJHKww==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/commands": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/search": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0" - }, - "funding": { - "url": "https://jaywcjlove.github.io/#/sponsor" - }, - "peerDependencies": { - "@codemirror/autocomplete": ">=6.0.0", - "@codemirror/commands": ">=6.0.0", - "@codemirror/language": ">=6.0.0", - "@codemirror/lint": ">=6.0.0", - "@codemirror/search": ">=6.0.0", - "@codemirror/state": ">=6.0.0", - "@codemirror/view": ">=6.0.0" - } - }, - "node_modules/@uiw/codemirror-theme-github": { - "version": "4.24.1", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-github/-/codemirror-theme-github-4.24.1.tgz", - "integrity": "sha512-dl4qFEXINE4TFus7ALMfjFUCl7sWLkqTdaSaln0Vv3s+HVzSMAh5lkEdnH3yPcOOCl5ehYG4zIx8bqEnA2/FYQ==", - "dependencies": { - "@uiw/codemirror-themes": "4.24.1" - }, - "funding": { - "url": "https://jaywcjlove.github.io/#/sponsor" - } - }, - "node_modules/@uiw/codemirror-themes": { - "version": "4.24.1", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.24.1.tgz", - "integrity": "sha512-hduBbFNiWNW6nYa2/giKQ9YpzhWNw87BGpCjC+cXYMZ7bCD6q5DC6Hw+7z7ZwSzEaOQvV91lmirOjJ8hn9+pkg==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0" - }, - "funding": { - "url": "https://jaywcjlove.github.io/#/sponsor" - }, - "peerDependencies": { - "@codemirror/language": ">=6.0.0", - "@codemirror/state": ">=6.0.0", - "@codemirror/view": ">=6.0.0" - } - }, - "node_modules/@uiw/react-codemirror": { - "version": "4.24.1", - "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.24.1.tgz", - "integrity": "sha512-BivF4NLqbuBQK5gPVhSkOARi9nPXw8X5r25EnInPeY+I9l1dfEX8O9V6+0xHTlGHyUo0cNfGEF9t1KHEicUfJw==", - "dependencies": { - "@babel/runtime": "^7.18.6", - "@codemirror/commands": "^6.1.0", - "@codemirror/state": "^6.1.1", - "@codemirror/theme-one-dark": "^6.0.0", - "@uiw/codemirror-extensions-basic-setup": "4.24.1", - "codemirror": "^6.0.0" - }, - "funding": { - "url": "https://jaywcjlove.github.io/#/sponsor" - }, - "peerDependencies": { - "@babel/runtime": ">=7.11.0", - "@codemirror/state": ">=6.0.0", - "@codemirror/theme-one-dark": ">=6.0.0", - "@codemirror/view": ">=6.0.0", - "codemirror": ">=6.0.0", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", - "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/aria-hidden": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", - "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", - "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": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001727", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", - "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "engines": { - "node": ">=18" - } - }, - "node_modules/class-variance-authority": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", - "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", - "dependencies": { - "clsx": "^2.1.1" - }, - "funding": { - "url": "https://polar.sh/cva" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/cmdk": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz", - "integrity": "sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==", - "dependencies": { - "@radix-ui/react-dialog": "1.0.5", - "@radix-ui/react-primitive": "1.0.3" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/cmdk/node_modules/@radix-ui/primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", - "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", - "dependencies": { - "@babel/runtime": "^7.13.10" - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-compose-refs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", - "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-context": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", - "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-dialog": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz", - "integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.5", - "@radix-ui/react-focus-guards": "1.0.1", - "@radix-ui/react-focus-scope": "1.0.4", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-portal": "1.0.4", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-controllable-state": "1.0.1", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.5" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", - "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-escape-keydown": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-focus-guards": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", - "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-focus-scope": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", - "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-id": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", - "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-layout-effect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-portal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", - "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-presence": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", - "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-primitive": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", - "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-slot": "1.0.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", - "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", - "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", - "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-callback-ref": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", - "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-callback-ref": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", - "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/cmdk/node_modules/react-remove-scroll": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", - "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", - "dependencies": { - "react-remove-scroll-bar": "^2.3.3", - "react-style-singleton": "^2.2.1", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.0", - "use-sidecar": "^1.1.2" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/codemirror": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", - "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/commands": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/search": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0" - } - }, - "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/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "engines": { - "node": ">=18" - } - }, - "node_modules/copy-to-clipboard": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", - "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", - "dependencies": { - "toggle-selection": "^1.0.6" - } - }, - "node_modules/crelt": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", - "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true - }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-node-es": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.188", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.188.tgz", - "integrity": "sha512-pfEx5CBFAocOKNrc+i5fSvhDaI1Vr9R9aT5uX1IzM3hhdL6k649wfuUcdUd9EZnmbE1xdfA51CwqQ61CO3Xl3g==", - "dev": true - }, - "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/esbuild": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", - "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.8", - "@esbuild/android-arm": "0.25.8", - "@esbuild/android-arm64": "0.25.8", - "@esbuild/android-x64": "0.25.8", - "@esbuild/darwin-arm64": "0.25.8", - "@esbuild/darwin-x64": "0.25.8", - "@esbuild/freebsd-arm64": "0.25.8", - "@esbuild/freebsd-x64": "0.25.8", - "@esbuild/linux-arm": "0.25.8", - "@esbuild/linux-arm64": "0.25.8", - "@esbuild/linux-ia32": "0.25.8", - "@esbuild/linux-loong64": "0.25.8", - "@esbuild/linux-mips64el": "0.25.8", - "@esbuild/linux-ppc64": "0.25.8", - "@esbuild/linux-riscv64": "0.25.8", - "@esbuild/linux-s390x": "0.25.8", - "@esbuild/linux-x64": "0.25.8", - "@esbuild/netbsd-arm64": "0.25.8", - "@esbuild/netbsd-x64": "0.25.8", - "@esbuild/openbsd-arm64": "0.25.8", - "@esbuild/openbsd-x64": "0.25.8", - "@esbuild/openharmony-arm64": "0.25.8", - "@esbuild/sunos-x64": "0.25.8", - "@esbuild/win32-arm64": "0.25.8", - "@esbuild/win32-ia32": "0.25.8", - "@esbuild/win32-x64": "0.25.8" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fdir": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", - "dev": true, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-nonce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", - "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "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==" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/jiti": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", - "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/lightningcss": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-darwin-arm64": "1.30.1", - "lightningcss-darwin-x64": "1.30.1", - "lightningcss-freebsd-x64": "1.30.1", - "lightningcss-linux-arm-gnueabihf": "1.30.1", - "lightningcss-linux-arm64-gnu": "1.30.1", - "lightningcss-linux-arm64-musl": "1.30.1", - "lightningcss-linux-x64-gnu": "1.30.1", - "lightningcss-linux-x64-musl": "1.30.1", - "lightningcss-win32-arm64-msvc": "1.30.1", - "lightningcss-win32-x64-msvc": "1.30.1" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "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/lucide-react": { - "version": "0.479.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.479.0.tgz", - "integrity": "sha512-aBhNnveRhorBOK7uA4gDjgaf+YlHMdMhQ/3cupk6exM10hWlEU+2QtWYOfhXhjAsmdb6LeKR+NZnow4UxRRiTQ==", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "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==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "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_modules/next-themes": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", - "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", - "peerDependencies": { - "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" - } - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true - }, - "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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-map": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", - "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" - }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "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.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "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==", - "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/react": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", - "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", - "dependencies": { - "scheduler": "^0.26.0" - }, - "peerDependencies": { - "react": "^19.1.0" - } - }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-remove-scroll": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", - "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", - "dependencies": { - "react-remove-scroll-bar": "^2.3.7", - "react-style-singleton": "^2.2.3", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.3", - "use-sidecar": "^1.1.3" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-remove-scroll-bar": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", - "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", - "dependencies": { - "react-style-singleton": "^2.2.2", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-router": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.7.0.tgz", - "integrity": "sha512-3FUYSwlvB/5wRJVTL/aavqHmfUKe0+Xm9MllkYgGo9eDwNdkvwlJGjpPxono1kCycLt6AnDTgjmXvK3/B4QGuw==", - "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } - } - }, - "node_modules/react-router-dom": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.7.0.tgz", - "integrity": "sha512-wwGS19VkNBkneVh9/YD0pK3IsjWxQUVMDD6drlG7eJpo1rXBtctBqDyBm/k+oKHRAm1x9XWT3JFC82QI9YOXXA==", - "dependencies": { - "react-router": "7.7.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - } - }, - "node_modules/react-style-singleton": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", - "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", - "dependencies": { - "get-nonce": "^1.0.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.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==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.45.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.1.tgz", - "integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.45.1", - "@rollup/rollup-android-arm64": "4.45.1", - "@rollup/rollup-darwin-arm64": "4.45.1", - "@rollup/rollup-darwin-x64": "4.45.1", - "@rollup/rollup-freebsd-arm64": "4.45.1", - "@rollup/rollup-freebsd-x64": "4.45.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.45.1", - "@rollup/rollup-linux-arm-musleabihf": "4.45.1", - "@rollup/rollup-linux-arm64-gnu": "4.45.1", - "@rollup/rollup-linux-arm64-musl": "4.45.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.45.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.45.1", - "@rollup/rollup-linux-riscv64-gnu": "4.45.1", - "@rollup/rollup-linux-riscv64-musl": "4.45.1", - "@rollup/rollup-linux-s390x-gnu": "4.45.1", - "@rollup/rollup-linux-x64-gnu": "4.45.1", - "@rollup/rollup-linux-x64-musl": "4.45.1", - "@rollup/rollup-win32-arm64-msvc": "4.45.1", - "@rollup/rollup-win32-ia32-msvc": "4.45.1", - "@rollup/rollup-win32-x64-msvc": "4.45.1", - "fsevents": "~2.3.2" - } - }, - "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==", - "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/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==" - }, - "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_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==" - }, - "node_modules/sonner": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.6.tgz", - "integrity": "sha512-yHFhk8T/DK3YxjFQXIrcHT1rGEeTLliVzWbO0xN8GberVun2RiBnxAjXAYpZrqwEVHBG9asI/Li8TAAhN9m59Q==", - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", - "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/style-mod": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", - "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" - }, - "node_modules/tailwind-merge": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz", - "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/dcastil" - } - }, - "node_modules/tailwindcss": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", - "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==" - }, - "node_modules/tailwindcss-animate": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", - "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", - "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders" - } - }, - "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", - "dev": true, - "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "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==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "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.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/use-callback-ref": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", - "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-sidecar": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", - "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", - "dependencies": { - "detect-node-es": "^1.1.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/vite": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz", - "integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite-plugin-static-copy": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-2.3.2.tgz", - "integrity": "sha512-iwrrf+JupY4b9stBttRWzGHzZbeMjAHBhkrn67MNACXJVjEMRpCI10Q3AkxdBkl45IHaTfw/CNVevzQhP7yTwg==", - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.3", - "fast-glob": "^3.2.11", - "fs-extra": "^11.1.0", - "p-map": "^7.0.3", - "picocolors": "^1.0.0" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "vite": "^5.0.0 || ^6.0.0" - } - }, - "node_modules/w3c-keyname": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/zustand": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.6.tgz", - "integrity": "sha512-ihAqNeUVhe0MAD+X8M5UzqyZ9k3FFZLBTtqo6JLPwV53cbRB/mJwBI0PxcIgqhBBHlEs8G45OTDTMq3gNcLq3A==", - "engines": { - "node": ">=12.20.0" - }, - "peerDependencies": { - "@types/react": ">=18.0.0", - "immer": ">=9.0.6", - "react": ">=18.0.0", - "use-sync-external-store": ">=1.2.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "immer": { - "optional": true - }, - "react": { - "optional": true - }, - "use-sync-external-store": { - "optional": true - } - } - } - } -} diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml index 9fec5d4b..2d26f18e 100644 --- a/app/pnpm-lock.yaml +++ b/app/pnpm-lock.yaml @@ -9,17 +9,17 @@ importers: .: dependencies: '@codemirror/autocomplete': - specifier: ^6.18.6 - version: 6.18.6 + specifier: ^6.19.1 + version: 6.19.1 '@codemirror/lang-json': - specifier: ^6.0.1 - version: 6.0.1 + specifier: ^6.0.2 + version: 6.0.2 '@codemirror/lang-yaml': - specifier: ^6.1.1 + specifier: ^6.1.2 version: 6.1.2 '@codemirror/language': - specifier: ^6.10.1 - version: 6.10.8 + specifier: ^6.11.3 + version: 6.11.3 '@codemirror/legacy-modes': specifier: 6.4.0 version: 6.4.0 @@ -30,32 +30,32 @@ importers: specifier: ^2.2.5 version: 2.2.5 '@radix-ui/react-dialog': - specifier: ^1.1.6 - version: 1.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^1.1.15 + version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@radix-ui/react-dropdown-menu': - specifier: ^2.1.6 - version: 2.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^2.1.16 + version: 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@radix-ui/react-label': - specifier: ^2.1.2 - version: 2.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^2.1.7 + version: 2.1.8(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@radix-ui/react-popover': - specifier: ^1.1.6 - version: 1.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^1.1.15 + version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@radix-ui/react-slot': - specifier: ^1.1.2 - version: 1.1.2(@types/react@19.0.10)(react@19.0.0) + specifier: ^1.2.3 + version: 1.2.4(@types/react@19.2.4)(react@19.2.0) '@radix-ui/react-tabs': - specifier: ^1.1.3 - version: 1.1.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^1.1.13 + version: 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@tailwindcss/vite': - specifier: ^4.0.12 - version: 4.0.12(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1)) + specifier: ^4.1.16 + version: 4.1.17(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1)) '@uiw/codemirror-theme-github': - specifier: ^4.22.1 - version: 4.23.10(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0) + specifier: ^4.25.2 + version: 4.25.3(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0) '@uiw/react-codemirror': - specifier: ^4.22.1 - version: 4.23.10(@babel/runtime@7.26.9)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.29.0)(codemirror@6.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^4.25.2 + version: 4.25.3(@babel/runtime@7.26.9)(@codemirror/autocomplete@6.19.1)(@codemirror/language@6.11.3)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.29.0)(codemirror@6.0.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -64,123 +64,131 @@ importers: version: 2.1.1 cmdk: specifier: 1.0.0 - version: 1.0.0(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + version: 1.0.0(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) copy-to-clipboard: specifier: ^3.3.3 version: 3.3.3 lucide-react: specifier: ^0.479.0 - version: 0.479.0(react@19.0.0) + version: 0.479.0(react@19.2.0) next-themes: - specifier: ^0.4.5 - version: 0.4.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^0.4.6 + version: 0.4.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: - specifier: ^19.0.0 - version: 19.0.0 + specifier: ^19.2.0 + version: 19.2.0 react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) + specifier: ^19.2.0 + version: 19.2.0(react@19.2.0) react-router-dom: - specifier: ^7.4.1 - version: 7.4.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^7.9.4 + version: 7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) sonner: - specifier: ^2.0.1 - version: 2.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^2.0.7 + version: 2.0.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0) tailwind-merge: - specifier: ^3.0.2 - version: 3.0.2 + specifier: ^3.3.1 + version: 3.4.0 tailwindcss: - specifier: ^4.0.12 - version: 4.0.12 + specifier: ^4.1.16 + version: 4.1.17 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@4.0.12) + version: 1.0.7(tailwindcss@4.1.17) vite-plugin-static-copy: - specifier: 2.3.0 - version: 2.3.0(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1)) + specifier: ^2.3.2 + version: 2.3.2(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1)) yaml: specifier: 2.7.1 version: 2.7.1 zustand: - specifier: ^5.0.3 - version: 5.0.3(@types/react@19.0.10)(react@19.0.0) + specifier: ^5.0.8 + version: 5.0.8(@types/react@19.2.4)(react@19.2.0) devDependencies: '@types/node': - specifier: ^20.8.2 - version: 20.17.24 + specifier: ^20.19.23 + version: 20.19.25 '@types/react': - specifier: ^19.0.10 - version: 19.0.10 + specifier: ^19.2.2 + version: 19.2.4 '@types/react-dom': - specifier: ^19.0.4 - version: 19.0.4(@types/react@19.0.10) + specifier: ^19.2.2 + version: 19.2.3(@types/react@19.2.4) '@vitejs/plugin-react': - specifier: ^4.3.4 - version: 4.3.4(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1)) + specifier: ^4.7.0 + version: 4.7.0(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1)) globals: specifier: ^15.15.0 version: 15.15.0 typescript: - specifier: ~5.7.2 + specifier: ~5.7.3 version: 5.7.3 vite: - specifier: ^6.2.0 - version: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1) + specifier: ^6.4.1 + version: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1) packages: - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.26.8': - resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} engines: {node: '>=6.9.0'} - '@babel/core@7.26.9': - resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.26.9': - resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.26.5': - resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.26.5': - resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.25.9': resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.25.9': resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.26.9': - resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==} + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} '@babel/parser@7.26.9': @@ -188,14 +196,19 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-transform-react-jsx-self@7.25.9': - resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-source@7.25.9': - resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -204,32 +217,36 @@ packages: resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==} engines: {node: '>=6.9.0'} - '@babel/template@7.26.9': - resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.26.9': - resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} engines: {node: '>=6.9.0'} '@babel/types@7.26.9': resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} engines: {node: '>=6.9.0'} - '@codemirror/autocomplete@6.18.6': - resolution: {integrity: sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + + '@codemirror/autocomplete@6.19.1': + resolution: {integrity: sha512-q6NenYkEy2fn9+JyjIxMWcNjzTL/IhwqfzOut1/G3PrIFkrbl4AL7Wkse5tLrQUUyqGoAKU5+Pi5jnnXxH5HGw==} '@codemirror/commands@6.8.0': resolution: {integrity: sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ==} - '@codemirror/lang-json@6.0.1': - resolution: {integrity: sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==} + '@codemirror/lang-json@6.0.2': + resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==} '@codemirror/lang-yaml@6.1.2': resolution: {integrity: sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==} - '@codemirror/language@6.10.8': - resolution: {integrity: sha512-wcP8XPPhDH2vTqf181U8MbZnW+tDyPYy0UzVOa+oHORjyT+mhhom9vBd7dApJwoDz9Nb/a8kHjJIsuA/t8vNFw==} + '@codemirror/language@6.11.3': + resolution: {integrity: sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==} '@codemirror/legacy-modes@6.4.0': resolution: {integrity: sha512-5m/K+1A6gYR0e+h/dEde7LoGimMjRtWXZFg4Lo70cc8HzjSdHe3fLwjWMR0VRl5KFT1SxalSap7uMgPKF28wBA==} @@ -420,10 +437,16 @@ packages: '@iarna/toml@2.2.5': resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -435,9 +458,15 @@ packages: '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@lezer/common@1.2.3': resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==} @@ -471,11 +500,11 @@ packages: '@radix-ui/primitive@1.0.1': resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} - '@radix-ui/primitive@1.1.1': - resolution: {integrity: sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==} + '@radix-ui/primitive@1.1.3': + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} - '@radix-ui/react-arrow@1.1.2': - resolution: {integrity: sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==} + '@radix-ui/react-arrow@1.1.7': + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -487,8 +516,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collection@1.1.2': - resolution: {integrity: sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==} + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -509,8 +538,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-compose-refs@1.1.1': - resolution: {integrity: sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==} + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -527,8 +556,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-context@1.1.1': - resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==} + '@radix-ui/react-context@1.1.2': + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -549,8 +578,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dialog@1.1.6': - resolution: {integrity: sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==} + '@radix-ui/react-dialog@1.1.15': + resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -562,8 +591,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-direction@1.1.0': - resolution: {integrity: sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==} + '@radix-ui/react-direction@1.1.1': + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -584,8 +613,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dismissable-layer@1.1.5': - resolution: {integrity: sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==} + '@radix-ui/react-dismissable-layer@1.1.11': + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -597,8 +626,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dropdown-menu@2.1.6': - resolution: {integrity: sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA==} + '@radix-ui/react-dropdown-menu@2.1.16': + resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -619,8 +648,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-focus-guards@1.1.1': - resolution: {integrity: sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==} + '@radix-ui/react-focus-guards@1.1.3': + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -641,8 +670,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-focus-scope@1.1.2': - resolution: {integrity: sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==} + '@radix-ui/react-focus-scope@1.1.7': + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -663,8 +692,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-id@1.1.0': - resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==} + '@radix-ui/react-id@1.1.1': + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -672,8 +701,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-label@2.1.2': - resolution: {integrity: sha512-zo1uGMTaNlHehDyFQcDZXRJhUPDuukcnHz0/jnrup0JA6qL+AFpAnty+7VKa9esuU5xTblAZzTGYJKSKaBxBhw==} + '@radix-ui/react-label@2.1.8': + resolution: {integrity: sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -685,8 +714,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-menu@2.1.6': - resolution: {integrity: sha512-tBBb5CXDJW3t2mo9WlO7r6GTmWV0F0uzHZVFmlRmYpiSK1CDU5IKojP1pm7oknpBOrFZx/YgBRW9oorPO2S/Lg==} + '@radix-ui/react-menu@2.1.16': + resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -698,8 +727,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popover@1.1.6': - resolution: {integrity: sha512-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg==} + '@radix-ui/react-popover@1.1.15': + resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -711,8 +740,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popper@1.2.2': - resolution: {integrity: sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==} + '@radix-ui/react-popper@1.2.8': + resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -737,8 +766,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-portal@1.1.4': - resolution: {integrity: sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==} + '@radix-ui/react-portal@1.1.9': + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -763,8 +792,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-presence@1.1.2': - resolution: {integrity: sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==} + '@radix-ui/react-presence@1.1.5': + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -789,8 +818,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-primitive@2.0.2': - resolution: {integrity: sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==} + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -802,8 +831,21 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-roving-focus@1.1.2': - resolution: {integrity: sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==} + '@radix-ui/react-primitive@2.1.4': + resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-roving-focus@1.1.11': + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -824,8 +866,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-slot@1.1.2': - resolution: {integrity: sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==} + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -833,8 +875,17 @@ packages: '@types/react': optional: true - '@radix-ui/react-tabs@1.1.3': - resolution: {integrity: sha512-9mFyI30cuRDImbmFF6O2KUJdgEOsGh9Vmx9x/Dh9tOhL7BngmQPQfwW4aejKm5OHpfWIdmeV6ySyuxoOGjtNng==} + '@radix-ui/react-slot@1.2.4': + resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-tabs@1.1.13': + resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -855,8 +906,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-callback-ref@1.1.0': - resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} + '@radix-ui/react-use-callback-ref@1.1.1': + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -873,8 +924,17 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-controllable-state@1.1.0': - resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -891,8 +951,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-escape-keydown@1.1.0': - resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==} + '@radix-ui/react-use-escape-keydown@1.1.1': + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -909,8 +969,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-layout-effect@1.1.0': - resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==} + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -918,8 +978,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-rect@1.1.0': - resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==} + '@radix-ui/react-use-rect@1.1.1': + resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -927,8 +987,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-size@1.1.0': - resolution: {integrity: sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==} + '@radix-ui/react-use-size@1.1.1': + resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -936,8 +996,11 @@ packages: '@types/react': optional: true - '@radix-ui/rect@1.1.0': - resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==} + '@radix-ui/rect@1.1.1': + resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} '@rollup/rollup-android-arm-eabi@4.35.0': resolution: {integrity: sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==} @@ -1034,83 +1097,95 @@ packages: cpu: [x64] os: [win32] - '@tailwindcss/node@4.0.12': - resolution: {integrity: sha512-a6J11K1Ztdln9OrGfoM75/hChYPcHYGNYimqciMrvKXRmmPaS8XZTHhdvb5a3glz4Kd4ZxE1MnuFE2c0fGGmtg==} + '@tailwindcss/node@4.1.17': + resolution: {integrity: sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==} - '@tailwindcss/oxide-android-arm64@4.0.12': - resolution: {integrity: sha512-dAXCaemu3mHLXcA5GwGlQynX8n7tTdvn5i1zAxRvZ5iC9fWLl5bGnjZnzrQqT7ttxCvRwdVf3IHUnMVdDBO/kQ==} + '@tailwindcss/oxide-android-arm64@4.1.17': + resolution: {integrity: sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.0.12': - resolution: {integrity: sha512-vPNI+TpJQ7sizselDXIJdYkx9Cu6JBdtmRWujw9pVIxW8uz3O2PjgGGzL/7A0sXI8XDjSyRChrUnEW9rQygmJQ==} + '@tailwindcss/oxide-darwin-arm64@4.1.17': + resolution: {integrity: sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.0.12': - resolution: {integrity: sha512-RL/9jM41Fdq4Efr35C5wgLx98BirnrfwuD+zgMFK6Ir68HeOSqBhW9jsEeC7Y/JcGyPd3MEoJVIU4fAb7YLg7A==} + '@tailwindcss/oxide-darwin-x64@4.1.17': + resolution: {integrity: sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.0.12': - resolution: {integrity: sha512-7WzWiax+LguJcMEimY0Q4sBLlFXu1tYxVka3+G2M9KmU/3m84J3jAIV4KZWnockbHsbb2XgrEjtlJKVwHQCoRA==} + '@tailwindcss/oxide-freebsd-x64@4.1.17': + resolution: {integrity: sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.12': - resolution: {integrity: sha512-X9LRC7jjE1QlfIaBbXjY0PGeQP87lz5mEfLSVs2J1yRc9PSg1tEPS9NBqY4BU9v5toZgJgzKeaNltORyTs22TQ==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17': + resolution: {integrity: sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.0.12': - resolution: {integrity: sha512-i24IFNq2402zfDdoWKypXz0ZNS2G4NKaA82tgBlE2OhHIE+4mg2JDb5wVfyP6R+MCm5grgXvurcIcKWvo44QiQ==} + '@tailwindcss/oxide-linux-arm64-gnu@4.1.17': + resolution: {integrity: sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.0.12': - resolution: {integrity: sha512-LmOdshJBfAGIBG0DdBWhI0n5LTMurnGGJCHcsm9F//ISfsHtCnnYIKgYQui5oOz1SUCkqsMGfkAzWyNKZqbGNw==} + '@tailwindcss/oxide-linux-arm64-musl@4.1.17': + resolution: {integrity: sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.0.12': - resolution: {integrity: sha512-OSK667qZRH30ep8RiHbZDQfqkXjnzKxdn0oRwWzgCO8CoTxV+MvIkd0BWdQbYtYuM1wrakARV/Hwp0eA/qzdbw==} + '@tailwindcss/oxide-linux-x64-gnu@4.1.17': + resolution: {integrity: sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.0.12': - resolution: {integrity: sha512-uylhWq6OWQ8krV8Jk+v0H/3AZKJW6xYMgNMyNnUbbYXWi7hIVdxRKNUB5UvrlC3RxtgsK5EAV2i1CWTRsNcAnA==} + '@tailwindcss/oxide-linux-x64-musl@4.1.17': + resolution: {integrity: sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-win32-arm64-msvc@4.0.12': - resolution: {integrity: sha512-XDLnhMoXZEEOir1LK43/gHHwK84V1GlV8+pAncUAIN2wloeD+nNciI9WRIY/BeFTqES22DhTIGoilSO39xDb2g==} + '@tailwindcss/oxide-wasm32-wasi@4.1.17': + resolution: {integrity: sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.17': + resolution: {integrity: sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.0.12': - resolution: {integrity: sha512-I/BbjCLpKDQucvtn6rFuYLst1nfFwSMYyPzkx/095RE+tuzk5+fwXuzQh7T3fIBTcbn82qH/sFka7yPGA50tLw==} + '@tailwindcss/oxide-win32-x64-msvc@4.1.17': + resolution: {integrity: sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.0.12': - resolution: {integrity: sha512-DWb+myvJB9xJwelwT9GHaMc1qJj6MDXRDR0CS+T8IdkejAtu8ctJAgV4r1drQJLPeS7mNwq2UHW2GWrudTf63A==} + '@tailwindcss/oxide@4.1.17': + resolution: {integrity: sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==} engines: {node: '>= 10'} - '@tailwindcss/vite@4.0.12': - resolution: {integrity: sha512-JM3gp601UJiryIZ9R2bSqalzcOy15RCybQ1Q+BJqDEwVyo4LkWKeqQAcrpHapWXY31OJFTuOUVBFDWMhzHm2Bg==} + '@tailwindcss/vite@4.1.17': + resolution: {integrity: sha512-4+9w8ZHOiGnpcGI6z1TVVfWaX/koK7fKeSYF3qlYg2xpBtbteP2ddBxiarL+HVgfSJGeK5RIxRQmKm4rTJJAwA==} peerDependencies: - vite: ^5.2.0 || ^6 + vite: ^5.2.0 || ^6 || ^7 '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -1124,25 +1199,22 @@ packages: '@types/babel__traverse@7.20.6': resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - '@types/cookie@0.6.0': - resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} - '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/node@20.17.24': - resolution: {integrity: sha512-d7fGCyB96w9BnWQrOsJtpyiSaBcAYYr75bnK6ZRjDbql2cGLj/3GsL5OYmLPNq76l7Gf2q4Rv9J2o6h5CrD9sA==} + '@types/node@20.19.25': + resolution: {integrity: sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==} - '@types/react-dom@19.0.4': - resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==} + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: - '@types/react': ^19.0.0 + '@types/react': ^19.2.0 - '@types/react@19.0.10': - resolution: {integrity: sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==} + '@types/react@19.2.4': + resolution: {integrity: sha512-tBFxBp9Nfyy5rsmefN+WXc1JeW/j2BpBHFdLZbEVfs9wn3E3NRFxwV0pJg8M1qQAexFpvz73hJXFofV0ZAu92A==} - '@uiw/codemirror-extensions-basic-setup@4.23.10': - resolution: {integrity: sha512-zpbmSeNs3OU/f/Eyd6brFnjsBUYwv2mFjWxlAsIRSwTlW+skIT60rQHFBSfsj/5UVSxSLWVeUYczN7AyXvgTGQ==} + '@uiw/codemirror-extensions-basic-setup@4.25.3': + resolution: {integrity: sha512-F1doRyD50CWScwGHG2bBUtUpwnOv/zqSnzkZqJcX5YAHQx6Z1CuX8jdnFMH6qktRrPU1tfpNYftTWu3QIoHiMA==} peerDependencies: '@codemirror/autocomplete': '>=6.0.0' '@codemirror/commands': '>=6.0.0' @@ -1152,32 +1224,32 @@ packages: '@codemirror/state': '>=6.0.0' '@codemirror/view': '>=6.0.0' - '@uiw/codemirror-theme-github@4.23.10': - resolution: {integrity: sha512-jTg2sHAcU1d+8x0O+EBDI71rtJ8PWKIW8gzy+SW4wShQTAdsqGHk5y1ynt3KIeoaUkqngLqAK4SkhPaUKlqZqg==} + '@uiw/codemirror-theme-github@4.25.3': + resolution: {integrity: sha512-KdmcO9VicsBgsDErNrNBqwMuTbJRIpeMl9oIjmrNx2iEfIDSOMBIKlX+BkgwTAU+VmhqYY/68/kmF1K8z2FxrQ==} - '@uiw/codemirror-themes@4.23.10': - resolution: {integrity: sha512-dU0UgEEgEXCAYpxuVDQ6fovE82XsqgHZckTJOH6Bs8xCi3Z7dwBKO4pXuiA8qGDwTOXOMjSzfi+pRViDm7OfWw==} + '@uiw/codemirror-themes@4.25.3': + resolution: {integrity: sha512-k7/B7Vf4jU/WcdewgJWP9tMFxbjB6UpUymZ3fx/TsbGwt2JXAouw0uyqCn1RlYBfr7YQnvEs3Ju9ECkd2sKzdg==} peerDependencies: '@codemirror/language': '>=6.0.0' '@codemirror/state': '>=6.0.0' '@codemirror/view': '>=6.0.0' - '@uiw/react-codemirror@4.23.10': - resolution: {integrity: sha512-AbN4eVHOL4ckRuIXpZxkzEqL/1ChVA+BSdEnAKjIB68pLQvKsVoYbiFP8zkXkYc4+Fcgq5KbAjvYqdo4ewemKw==} + '@uiw/react-codemirror@4.25.3': + resolution: {integrity: sha512-1wtBZTXPIp8u6F/xjHvsUAYlEeF5Dic4xZBnqJyLzv7o7GjGYEUfSz9Z7bo9aK9GAx2uojG/AuBMfhA4uhvIVQ==} peerDependencies: '@babel/runtime': '>=7.11.0' '@codemirror/state': '>=6.0.0' '@codemirror/theme-one-dark': '>=6.0.0' '@codemirror/view': '>=6.0.0' codemirror: '>=6.0.0' - react: '>=16.8.0' - react-dom: '>=16.8.0' + react: '>=17.0.0' + react-dom: '>=17.0.0' - '@vitejs/plugin-react@4.3.4': - resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==} + '@vitejs/plugin-react@4.7.0': + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} @@ -1258,8 +1330,8 @@ packages: electron-to-chromium@1.5.113: resolution: {integrity: sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg==} - enhanced-resolve@5.18.1: - resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + enhanced-resolve@5.18.3: + resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} engines: {node: '>=10.13.0'} esbuild@0.25.1: @@ -1278,6 +1350,15 @@ packages: fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -1303,10 +1384,6 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - globals@15.15.0: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} @@ -1330,8 +1407,8 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - jiti@2.4.2: - resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true js-tokens@4.0.0: @@ -1350,68 +1427,74 @@ packages: jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - lightningcss-darwin-arm64@1.29.2: - resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==} + lightningcss-android-arm64@1.30.2: + resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.30.2: + resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.29.2: - resolution: {integrity: sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==} + lightningcss-darwin-x64@1.30.2: + resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.29.2: - resolution: {integrity: sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==} + lightningcss-freebsd-x64@1.30.2: + resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.29.2: - resolution: {integrity: sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==} + lightningcss-linux-arm-gnueabihf@1.30.2: + resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.29.2: - resolution: {integrity: sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==} + lightningcss-linux-arm64-gnu@1.30.2: + resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - lightningcss-linux-arm64-musl@1.29.2: - resolution: {integrity: sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==} + lightningcss-linux-arm64-musl@1.30.2: + resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - lightningcss-linux-x64-gnu@1.29.2: - resolution: {integrity: sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==} + lightningcss-linux-x64-gnu@1.30.2: + resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - lightningcss-linux-x64-musl@1.29.2: - resolution: {integrity: sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==} + lightningcss-linux-x64-musl@1.30.2: + resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - lightningcss-win32-arm64-msvc@1.29.2: - resolution: {integrity: sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==} + lightningcss-win32-arm64-msvc@1.30.2: + resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.29.2: - resolution: {integrity: sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==} + lightningcss-win32-x64-msvc@1.30.2: + resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.29.2: - resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==} + lightningcss@1.30.2: + resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} engines: {node: '>= 12.0.0'} lru-cache@5.1.1: @@ -1422,6 +1505,9 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1438,8 +1524,8 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - next-themes@0.4.5: - resolution: {integrity: sha512-E8/gYKBxZknOXBiDk/sRokAvkOw35PTUD4Gxtq1eBhd0r4Dx5S42zU65/q8ozR5rcSG2ZlE1E3+ShlUpC7an+A==} + next-themes@0.4.6: + resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} peerDependencies: react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc @@ -1462,6 +1548,10 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + postcss@8.5.3: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} @@ -1469,13 +1559,13 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - react-dom@19.0.0: - resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} + react-dom@19.2.0: + resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} peerDependencies: - react: ^19.0.0 + react: ^19.2.0 - react-refresh@0.14.2: - resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} react-remove-scroll-bar@2.3.8: @@ -1508,15 +1598,15 @@ packages: '@types/react': optional: true - react-router-dom@7.4.1: - resolution: {integrity: sha512-L3/4tig0Lvs6m6THK0HRV4eHUdpx0dlJasgCxXKnavwhh4tKYgpuZk75HRYNoRKDyDWi9QgzGXsQ1oQSBlWpAA==} + react-router-dom@7.9.6: + resolution: {integrity: sha512-2MkC2XSXq6HjGcihnx1s0DBWQETI4mlis4Ux7YTLvP67xnGxCvq+BcCQSO81qQHVUTM1V53tl4iVVaY5sReCOA==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' react-dom: '>=18' - react-router@7.4.1: - resolution: {integrity: sha512-Vmizn9ZNzxfh3cumddqv3kLOKvc7AskUT0dC1prTabhiEi0U4A33LmkDOJ79tXaeSqCqMBXBU/ySX88W85+EUg==} + react-router@7.9.6: + resolution: {integrity: sha512-Y1tUp8clYRXpfPITyuifmSoE2vncSME18uVLgaqyxh9H35JWpIfzHo+9y3Fzh5odk/jxPW29IgLgzcdwxGqyNA==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' @@ -1535,8 +1625,8 @@ packages: '@types/react': optional: true - react@19.0.0: - resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} + react@19.2.0: + resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} engines: {node: '>=0.10.0'} readdirp@3.6.0: @@ -1558,8 +1648,8 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - scheduler@0.25.0: - resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} @@ -1568,8 +1658,8 @@ packages: set-cookie-parser@2.7.1: resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} - sonner@2.0.1: - resolution: {integrity: sha512-FRBphaehZ5tLdLcQ8g2WOIRE+Y7BCfWi5Zyd8bCvBjiW8TxxAyoWZIxS661Yz6TGPqFQ4VLzOF89WEYhfynSFQ==} + sonner@2.0.7: + resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} peerDependencies: react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc @@ -1581,21 +1671,25 @@ packages: style-mod@4.1.2: resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==} - tailwind-merge@3.0.2: - resolution: {integrity: sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==} + tailwind-merge@3.4.0: + resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==} tailwindcss-animate@1.0.7: resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} peerDependencies: tailwindcss: '>=3.0.0 || insiders' - tailwindcss@4.0.12: - resolution: {integrity: sha512-bT0hJo91FtncsAMSsMzUkoo/iEU0Xs5xgFgVC9XmdM9bw5MhZuQFjPNl6wxAE0SiQF/YTZJa+PndGWYSDtuxAg==} + tailwindcss@4.1.17: + resolution: {integrity: sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==} tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1606,16 +1700,13 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - turbo-stream@2.4.0: - resolution: {integrity: sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==} - typescript@5.7.3: resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} engines: {node: '>=14.17'} hasBin: true - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} @@ -1647,14 +1738,14 @@ packages: '@types/react': optional: true - vite-plugin-static-copy@2.3.0: - resolution: {integrity: sha512-LLKwhhHetGaCnWz4mas4qqjjguDka6/6b4+SeIohRroj8aCE7QTfiZECfPecslFQkWZ3HdQuq5kOPmWZjNYlKA==} + vite-plugin-static-copy@2.3.2: + resolution: {integrity: sha512-iwrrf+JupY4b9stBttRWzGHzZbeMjAHBhkrn67MNACXJVjEMRpCI10Q3AkxdBkl45IHaTfw/CNVevzQhP7yTwg==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: vite: ^5.0.0 || ^6.0.0 - vite@6.2.1: - resolution: {integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==} + vite@6.4.1: + resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -1704,8 +1795,8 @@ packages: engines: {node: '>= 14'} hasBin: true - zustand@5.0.3: - resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} + zustand@5.0.8: + resolution: {integrity: sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw==} engines: {node: '>=12.20.0'} peerDependencies: '@types/react': '>=18.0.0' @@ -1724,31 +1815,26 @@ packages: snapshots: - '@ampproject/remapping@2.3.0': + '@babel/code-frame@7.27.1': dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - - '@babel/code-frame@7.26.2': - dependencies: - '@babel/helper-validator-identifier': 7.25.9 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.26.8': {} + '@babel/compat-data@7.28.5': {} - '@babel/core@7.26.9': + '@babel/core@7.28.5': dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.9 - '@babel/helper-compilation-targets': 7.26.5 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) - '@babel/helpers': 7.26.9 - '@babel/parser': 7.26.9 - '@babel/template': 7.26.9 - '@babel/traverse': 7.26.9 - '@babel/types': 7.26.9 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.0 gensync: 1.0.0-beta.2 @@ -1757,84 +1843,94 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.26.9': + '@babel/generator@7.28.5': dependencies: - '@babel/parser': 7.26.9 - '@babel/types': 7.26.9 - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/helper-compilation-targets@7.26.5': + '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.26.8 - '@babel/helper-validator-option': 7.25.9 + '@babel/compat-data': 7.28.5 + '@babel/helper-validator-option': 7.27.1 browserslist: 4.24.4 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-module-imports@7.25.9': + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.26.9 - '@babel/types': 7.26.9 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.9 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.9 + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.26.5': {} + '@babel/helper-plugin-utils@7.27.1': {} '@babel/helper-string-parser@7.25.9': {} + '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-validator-identifier@7.25.9': {} - '@babel/helper-validator-option@7.25.9': {} + '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helpers@7.26.9': + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.28.4': dependencies: - '@babel/template': 7.26.9 - '@babel/types': 7.26.9 + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 '@babel/parser@7.26.9': dependencies: '@babel/types': 7.26.9 - '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.9)': + '@babel/parser@7.28.5': dependencies: - '@babel/core': 7.26.9 - '@babel/helper-plugin-utils': 7.26.5 + '@babel/types': 7.28.5 - '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.9)': + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.9 - '@babel/helper-plugin-utils': 7.26.5 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 '@babel/runtime@7.26.9': dependencies: regenerator-runtime: 0.14.1 - '@babel/template@7.26.9': + '@babel/template@7.27.2': dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.9 - '@babel/types': 7.26.9 + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 - '@babel/traverse@7.26.9': + '@babel/traverse@7.28.5': dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.9 - '@babel/parser': 7.26.9 - '@babel/template': 7.26.9 - '@babel/types': 7.26.9 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 debug: 4.4.0 - globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -1843,36 +1939,41 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@codemirror/autocomplete@6.18.6': + '@babel/types@7.28.5': dependencies: - '@codemirror/language': 6.10.8 + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@codemirror/autocomplete@6.19.1': + dependencies: + '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@codemirror/view': 6.29.0 '@lezer/common': 1.2.3 '@codemirror/commands@6.8.0': dependencies: - '@codemirror/language': 6.10.8 + '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@codemirror/view': 6.29.0 '@lezer/common': 1.2.3 - '@codemirror/lang-json@6.0.1': + '@codemirror/lang-json@6.0.2': dependencies: - '@codemirror/language': 6.10.8 + '@codemirror/language': 6.11.3 '@lezer/json': 1.0.3 '@codemirror/lang-yaml@6.1.2': dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.10.8 + '@codemirror/autocomplete': 6.19.1 + '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@lezer/common': 1.2.3 '@lezer/highlight': 1.2.1 '@lezer/lr': 1.4.2 '@lezer/yaml': 1.0.3 - '@codemirror/language@6.10.8': + '@codemirror/language@6.11.3': dependencies: '@codemirror/state': 6.5.2 '@codemirror/view': 6.29.0 @@ -1883,7 +1984,7 @@ snapshots: '@codemirror/legacy-modes@6.4.0': dependencies: - '@codemirror/language': 6.10.8 + '@codemirror/language': 6.11.3 '@codemirror/lint@6.8.4': dependencies: @@ -1903,7 +2004,7 @@ snapshots: '@codemirror/theme-one-dark@6.1.2': dependencies: - '@codemirror/language': 6.10.8 + '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@codemirror/view': 6.29.0 '@lezer/highlight': 1.2.1 @@ -2004,33 +2105,50 @@ snapshots: '@floating-ui/core': 1.6.9 '@floating-ui/utils': 0.2.9 - '@floating-ui/react-dom@2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@floating-ui/react-dom@2.1.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@floating-ui/dom': 1.6.13 - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) '@floating-ui/utils@0.2.9': {} '@iarna/toml@2.2.5': {} + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/set-array@1.2.1': {} '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@lezer/common@1.2.3': {} '@lezer/highlight@1.2.1': @@ -2071,454 +2189,480 @@ snapshots: dependencies: '@babel/runtime': 7.26.9 - '@radix-ui/primitive@1.1.1': {} + '@radix-ui/primitive@1.1.3': {} - '@radix-ui/react-arrow@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-collection@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.1.2(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-compose-refs@1.0.1(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-compose-refs@1.0.1(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.4)(react@19.2.0)': dependencies: - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-context@1.0.1(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-context@1.0.1(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-context@1.1.1(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-context@1.1.2(@types/react@19.2.4)(react@19.2.0)': dependencies: - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-dialog@1.0.5(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-dialog@1.0.5(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-context': 1.0.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-id': 1.0.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.0.2(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@19.0.10)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@19.2.4)(react@19.2.0) aria-hidden: 1.2.4 - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) - react-remove-scroll: 2.5.5(@types/react@19.0.10)(react@19.0.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-remove-scroll: 2.5.5(@types/react@19.2.4)(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-dialog@1.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-portal': 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.1.2(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.10)(react@19.0.0) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.4)(react@19.2.0) aria-hidden: 1.2.4 - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) - react-remove-scroll: 2.6.3(@types/react@19.0.10)(react@19.0.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-remove-scroll: 2.6.3(@types/react@19.2.4)(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-direction@1.1.0(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-direction@1.1.1(@types/react@19.2.4)(react@19.2.0)': dependencies: - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-dismissable-layer@1.1.5(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-dropdown-menu@2.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-menu': 2.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-focus-guards@1.0.1(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-focus-guards@1.0.1(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-focus-guards@1.1.1(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.4)(react@19.2.0)': dependencies: - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-focus-scope@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-id@1.0.1(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-id@1.0.1(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-id@1.1.0(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-id@1.1.1(@types/react@19.2.4)(react@19.2.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-label@2.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-label@2.1.8(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-menu@2.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-popper': 1.2.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-portal': 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.1.2(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.10)(react@19.0.0) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.4)(react@19.2.0) aria-hidden: 1.2.4 - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) - react-remove-scroll: 2.6.3(@types/react@19.0.10)(react@19.0.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-remove-scroll: 2.6.3(@types/react@19.2.4)(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-popover@1.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-popper': 1.2.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-portal': 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.1.2(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.10)(react@19.0.0) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.4)(react@19.2.0) aria-hidden: 1.2.4 - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) - react-remove-scroll: 2.6.3(@types/react@19.0.10)(react@19.0.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-remove-scroll: 2.6.3(@types/react@19.2.4)(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-popper@1.2.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@floating-ui/react-dom': 2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-arrow': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-rect': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/rect': 1.1.0 - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@floating-ui/react-dom': 2.1.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/rect': 1.1.1 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-portal@1.0.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-portal@1.0.4(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-portal@1.1.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-presence@1.0.1(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-presence@1.0.1(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-presence@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-primitive@1.0.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-primitive@1.0.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - '@radix-ui/react-slot': 1.0.2(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-slot': 1.0.2(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-primitive@2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/react-slot': 1.1.2(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-roving-focus@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-slot': 1.2.4(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) - '@radix-ui/react-slot@1.0.2(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + optionalDependencies: + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) + + '@radix-ui/react-slot@1.0.2(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-slot@1.1.2(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-slot@1.2.3(@types/react@19.2.4)(react@19.2.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-tabs@1.1.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-slot@1.2.4(@types/react@19.2.4)(react@19.2.0)': dependencies: - '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-context': 1.1.1(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.10)(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 - '@types/react-dom': 19.0.4(@types/react@19.0.10) + '@types/react': 19.2.4 - '@radix-ui/react-use-callback-ref@1.0.1(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + optionalDependencies: + '@types/react': 19.2.4 + '@types/react-dom': 19.2.3(@types/react@19.2.4) + + '@radix-ui/react-use-callback-ref@1.0.1(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.4)(react@19.2.0)': dependencies: - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-use-controllable-state@1.0.1(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-use-controllable-state@1.0.1(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.4)(react@19.2.0)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.4)(react@19.2.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.4)(react@19.2.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 + optionalDependencies: + '@types/react': 19.2.4 + + '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.4)(react@19.2.0)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-use-layout-effect@1.0.1(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-use-layout-effect@1.0.1(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.4)(react@19.2.0)': dependencies: - react: 19.0.0 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-use-rect@1.1.0(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.4)(react@19.2.0)': dependencies: - '@radix-ui/rect': 1.1.0 - react: 19.0.0 + '@radix-ui/rect': 1.1.1 + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/react-use-size@1.1.0(@types/react@19.0.10)(react@19.0.0)': + '@radix-ui/react-use-size@1.1.1(@types/react@19.2.4)(react@19.2.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.10)(react@19.0.0) - react: 19.0.0 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.4)(react@19.2.0) + react: 19.2.0 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@radix-ui/rect@1.1.0': {} + '@radix-ui/rect@1.1.1': {} + + '@rolldown/pluginutils@1.0.0-beta.27': {} '@rollup/rollup-android-arm-eabi@4.35.0': optional: true @@ -2577,66 +2721,73 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.35.0': optional: true - '@tailwindcss/node@4.0.12': + '@tailwindcss/node@4.1.17': dependencies: - enhanced-resolve: 5.18.1 - jiti: 2.4.2 - tailwindcss: 4.0.12 + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.18.3 + jiti: 2.6.1 + lightningcss: 1.30.2 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.1.17 - '@tailwindcss/oxide-android-arm64@4.0.12': + '@tailwindcss/oxide-android-arm64@4.1.17': optional: true - '@tailwindcss/oxide-darwin-arm64@4.0.12': + '@tailwindcss/oxide-darwin-arm64@4.1.17': optional: true - '@tailwindcss/oxide-darwin-x64@4.0.12': + '@tailwindcss/oxide-darwin-x64@4.1.17': optional: true - '@tailwindcss/oxide-freebsd-x64@4.0.12': + '@tailwindcss/oxide-freebsd-x64@4.1.17': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.12': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.0.12': + '@tailwindcss/oxide-linux-arm64-gnu@4.1.17': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.0.12': + '@tailwindcss/oxide-linux-arm64-musl@4.1.17': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.0.12': + '@tailwindcss/oxide-linux-x64-gnu@4.1.17': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.0.12': + '@tailwindcss/oxide-linux-x64-musl@4.1.17': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.0.12': + '@tailwindcss/oxide-wasm32-wasi@4.1.17': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.0.12': + '@tailwindcss/oxide-win32-arm64-msvc@4.1.17': optional: true - '@tailwindcss/oxide@4.0.12': + '@tailwindcss/oxide-win32-x64-msvc@4.1.17': + optional: true + + '@tailwindcss/oxide@4.1.17': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.0.12 - '@tailwindcss/oxide-darwin-arm64': 4.0.12 - '@tailwindcss/oxide-darwin-x64': 4.0.12 - '@tailwindcss/oxide-freebsd-x64': 4.0.12 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.12 - '@tailwindcss/oxide-linux-arm64-gnu': 4.0.12 - '@tailwindcss/oxide-linux-arm64-musl': 4.0.12 - '@tailwindcss/oxide-linux-x64-gnu': 4.0.12 - '@tailwindcss/oxide-linux-x64-musl': 4.0.12 - '@tailwindcss/oxide-win32-arm64-msvc': 4.0.12 - '@tailwindcss/oxide-win32-x64-msvc': 4.0.12 + '@tailwindcss/oxide-android-arm64': 4.1.17 + '@tailwindcss/oxide-darwin-arm64': 4.1.17 + '@tailwindcss/oxide-darwin-x64': 4.1.17 + '@tailwindcss/oxide-freebsd-x64': 4.1.17 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.17 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.17 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.17 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.17 + '@tailwindcss/oxide-linux-x64-musl': 4.1.17 + '@tailwindcss/oxide-wasm32-wasi': 4.1.17 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.17 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.17 - '@tailwindcss/vite@4.0.12(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1))': + '@tailwindcss/vite@4.1.17(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1))': dependencies: - '@tailwindcss/node': 4.0.12 - '@tailwindcss/oxide': 4.0.12 - lightningcss: 1.29.2 - tailwindcss: 4.0.12 - vite: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1) + '@tailwindcss/node': 4.1.17 + '@tailwindcss/oxide': 4.1.17 + tailwindcss: 4.1.17 + vite: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1) '@types/babel__core@7.20.5': dependencies: @@ -2659,71 +2810,70 @@ snapshots: dependencies: '@babel/types': 7.26.9 - '@types/cookie@0.6.0': {} - '@types/estree@1.0.6': {} - '@types/node@20.17.24': + '@types/node@20.19.25': dependencies: - undici-types: 6.19.8 + undici-types: 6.21.0 - '@types/react-dom@19.0.4(@types/react@19.0.10)': + '@types/react-dom@19.2.3(@types/react@19.2.4)': dependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - '@types/react@19.0.10': + '@types/react@19.2.4': dependencies: csstype: 3.1.3 - '@uiw/codemirror-extensions-basic-setup@4.23.10(@codemirror/autocomplete@6.18.6)(@codemirror/commands@6.8.0)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0)': + '@uiw/codemirror-extensions-basic-setup@4.25.3(@codemirror/autocomplete@6.19.1)(@codemirror/commands@6.8.0)(@codemirror/language@6.11.3)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0)': dependencies: - '@codemirror/autocomplete': 6.18.6 + '@codemirror/autocomplete': 6.19.1 '@codemirror/commands': 6.8.0 - '@codemirror/language': 6.10.8 + '@codemirror/language': 6.11.3 '@codemirror/lint': 6.8.4 '@codemirror/search': 6.5.10 '@codemirror/state': 6.5.2 '@codemirror/view': 6.29.0 - '@uiw/codemirror-theme-github@4.23.10(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0)': + '@uiw/codemirror-theme-github@4.25.3(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0)': dependencies: - '@uiw/codemirror-themes': 4.23.10(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0) + '@uiw/codemirror-themes': 4.25.3(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0) transitivePeerDependencies: - '@codemirror/language' - '@codemirror/state' - '@codemirror/view' - '@uiw/codemirror-themes@4.23.10(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0)': + '@uiw/codemirror-themes@4.25.3(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0)': dependencies: - '@codemirror/language': 6.10.8 + '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@codemirror/view': 6.29.0 - '@uiw/react-codemirror@4.23.10(@babel/runtime@7.26.9)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.29.0)(codemirror@6.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@uiw/react-codemirror@4.25.3(@babel/runtime@7.26.9)(@codemirror/autocomplete@6.19.1)(@codemirror/language@6.11.3)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.29.0)(codemirror@6.0.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.26.9 '@codemirror/commands': 6.8.0 '@codemirror/state': 6.5.2 '@codemirror/theme-one-dark': 6.1.2 '@codemirror/view': 6.29.0 - '@uiw/codemirror-extensions-basic-setup': 4.23.10(@codemirror/autocomplete@6.18.6)(@codemirror/commands@6.8.0)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0) + '@uiw/codemirror-extensions-basic-setup': 4.25.3(@codemirror/autocomplete@6.19.1)(@codemirror/commands@6.8.0)(@codemirror/language@6.11.3)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0) codemirror: 6.0.1 - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) transitivePeerDependencies: - '@codemirror/autocomplete' - '@codemirror/language' - '@codemirror/lint' - '@codemirror/search' - '@vitejs/plugin-react@4.3.4(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1))': + '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1))': dependencies: - '@babel/core': 7.26.9 - '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.9) - '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.9) + '@babel/core': 7.28.5 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5) + '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 - react-refresh: 0.14.2 - vite: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1) + react-refresh: 0.17.0 + vite: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1) transitivePeerDependencies: - supports-color @@ -2769,21 +2919,21 @@ snapshots: clsx@2.1.1: {} - cmdk@1.0.0(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + cmdk@1.0.0(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@radix-ui/react-dialog': 1.0.5(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + '@radix-ui/react-dialog': 1.0.5(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.2.3(@types/react@19.2.4))(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) transitivePeerDependencies: - '@types/react' - '@types/react-dom' codemirror@6.0.1: dependencies: - '@codemirror/autocomplete': 6.18.6 + '@codemirror/autocomplete': 6.19.1 '@codemirror/commands': 6.8.0 - '@codemirror/language': 6.10.8 + '@codemirror/language': 6.11.3 '@codemirror/lint': 6.8.4 '@codemirror/search': 6.5.10 '@codemirror/state': 6.5.2 @@ -2811,7 +2961,7 @@ snapshots: electron-to-chromium@1.5.113: {} - enhanced-resolve@5.18.1: + enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 @@ -2858,6 +3008,10 @@ snapshots: dependencies: reusify: 1.1.0 + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -2879,8 +3033,6 @@ snapshots: dependencies: is-glob: 4.0.3 - globals@11.12.0: {} - globals@15.15.0: {} graceful-fs@4.2.11: {} @@ -2897,7 +3049,7 @@ snapshots: is-number@7.0.0: {} - jiti@2.4.2: {} + jiti@2.6.1: {} js-tokens@4.0.0: {} @@ -2911,58 +3063,66 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - lightningcss-darwin-arm64@1.29.2: + lightningcss-android-arm64@1.30.2: optional: true - lightningcss-darwin-x64@1.29.2: + lightningcss-darwin-arm64@1.30.2: optional: true - lightningcss-freebsd-x64@1.29.2: + lightningcss-darwin-x64@1.30.2: optional: true - lightningcss-linux-arm-gnueabihf@1.29.2: + lightningcss-freebsd-x64@1.30.2: optional: true - lightningcss-linux-arm64-gnu@1.29.2: + lightningcss-linux-arm-gnueabihf@1.30.2: optional: true - lightningcss-linux-arm64-musl@1.29.2: + lightningcss-linux-arm64-gnu@1.30.2: optional: true - lightningcss-linux-x64-gnu@1.29.2: + lightningcss-linux-arm64-musl@1.30.2: optional: true - lightningcss-linux-x64-musl@1.29.2: + lightningcss-linux-x64-gnu@1.30.2: optional: true - lightningcss-win32-arm64-msvc@1.29.2: + lightningcss-linux-x64-musl@1.30.2: optional: true - lightningcss-win32-x64-msvc@1.29.2: + lightningcss-win32-arm64-msvc@1.30.2: optional: true - lightningcss@1.29.2: + lightningcss-win32-x64-msvc@1.30.2: + optional: true + + lightningcss@1.30.2: dependencies: detect-libc: 2.0.3 optionalDependencies: - lightningcss-darwin-arm64: 1.29.2 - lightningcss-darwin-x64: 1.29.2 - lightningcss-freebsd-x64: 1.29.2 - lightningcss-linux-arm-gnueabihf: 1.29.2 - lightningcss-linux-arm64-gnu: 1.29.2 - lightningcss-linux-arm64-musl: 1.29.2 - lightningcss-linux-x64-gnu: 1.29.2 - lightningcss-linux-x64-musl: 1.29.2 - lightningcss-win32-arm64-msvc: 1.29.2 - lightningcss-win32-x64-msvc: 1.29.2 + lightningcss-android-arm64: 1.30.2 + lightningcss-darwin-arm64: 1.30.2 + lightningcss-darwin-x64: 1.30.2 + lightningcss-freebsd-x64: 1.30.2 + lightningcss-linux-arm-gnueabihf: 1.30.2 + lightningcss-linux-arm64-gnu: 1.30.2 + lightningcss-linux-arm64-musl: 1.30.2 + lightningcss-linux-x64-gnu: 1.30.2 + lightningcss-linux-x64-musl: 1.30.2 + lightningcss-win32-arm64-msvc: 1.30.2 + lightningcss-win32-x64-msvc: 1.30.2 lru-cache@5.1.1: dependencies: yallist: 3.1.1 - lucide-react@0.479.0(react@19.0.0): + lucide-react@0.479.0(react@19.2.0): dependencies: - react: 19.0.0 + react: 19.2.0 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 merge2@1.4.1: {} @@ -2975,10 +3135,10 @@ snapshots: nanoid@3.3.9: {} - next-themes@0.4.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + next-themes@0.4.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) node-releases@2.0.19: {} @@ -2990,6 +3150,8 @@ snapshots: picomatch@2.3.1: {} + picomatch@4.0.3: {} + postcss@8.5.3: dependencies: nanoid: 3.3.9 @@ -2998,68 +3160,66 @@ snapshots: queue-microtask@1.2.3: {} - react-dom@19.0.0(react@19.0.0): + react-dom@19.2.0(react@19.2.0): dependencies: - react: 19.0.0 - scheduler: 0.25.0 + react: 19.2.0 + scheduler: 0.27.0 - react-refresh@0.14.2: {} + react-refresh@0.17.0: {} - react-remove-scroll-bar@2.3.8(@types/react@19.0.10)(react@19.0.0): + react-remove-scroll-bar@2.3.8(@types/react@19.2.4)(react@19.2.0): dependencies: - react: 19.0.0 - react-style-singleton: 2.2.3(@types/react@19.0.10)(react@19.0.0) + react: 19.2.0 + react-style-singleton: 2.2.3(@types/react@19.2.4)(react@19.2.0) tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - react-remove-scroll@2.5.5(@types/react@19.0.10)(react@19.0.0): + react-remove-scroll@2.5.5(@types/react@19.2.4)(react@19.2.0): dependencies: - react: 19.0.0 - react-remove-scroll-bar: 2.3.8(@types/react@19.0.10)(react@19.0.0) - react-style-singleton: 2.2.3(@types/react@19.0.10)(react@19.0.0) + react: 19.2.0 + react-remove-scroll-bar: 2.3.8(@types/react@19.2.4)(react@19.2.0) + react-style-singleton: 2.2.3(@types/react@19.2.4)(react@19.2.0) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.0.10)(react@19.0.0) - use-sidecar: 1.1.3(@types/react@19.0.10)(react@19.0.0) + use-callback-ref: 1.3.3(@types/react@19.2.4)(react@19.2.0) + use-sidecar: 1.1.3(@types/react@19.2.4)(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - react-remove-scroll@2.6.3(@types/react@19.0.10)(react@19.0.0): + react-remove-scroll@2.6.3(@types/react@19.2.4)(react@19.2.0): dependencies: - react: 19.0.0 - react-remove-scroll-bar: 2.3.8(@types/react@19.0.10)(react@19.0.0) - react-style-singleton: 2.2.3(@types/react@19.0.10)(react@19.0.0) + react: 19.2.0 + react-remove-scroll-bar: 2.3.8(@types/react@19.2.4)(react@19.2.0) + react-style-singleton: 2.2.3(@types/react@19.2.4)(react@19.2.0) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.0.10)(react@19.0.0) - use-sidecar: 1.1.3(@types/react@19.0.10)(react@19.0.0) + use-callback-ref: 1.3.3(@types/react@19.2.4)(react@19.2.0) + use-sidecar: 1.1.3(@types/react@19.2.4)(react@19.2.0) optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - react-router-dom@7.4.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + react-router-dom@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) - react-router: 7.4.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-router: 7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - react-router@7.4.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@types/cookie': 0.6.0 cookie: 1.0.2 - react: 19.0.0 + react: 19.2.0 set-cookie-parser: 2.7.1 - turbo-stream: 2.4.0 optionalDependencies: - react-dom: 19.0.0(react@19.0.0) + react-dom: 19.2.0(react@19.2.0) - react-style-singleton@2.2.3(@types/react@19.0.10)(react@19.0.0): + react-style-singleton@2.2.3(@types/react@19.2.4)(react@19.2.0): dependencies: get-nonce: 1.0.1 - react: 19.0.0 + react: 19.2.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - react@19.0.0: {} + react@19.2.0: {} readdirp@3.6.0: dependencies: @@ -3098,31 +3258,36 @@ snapshots: dependencies: queue-microtask: 1.2.3 - scheduler@0.25.0: {} + scheduler@0.27.0: {} semver@6.3.1: {} set-cookie-parser@2.7.1: {} - sonner@2.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + sonner@2.0.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - react: 19.0.0 - react-dom: 19.0.0(react@19.0.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) source-map-js@1.2.1: {} style-mod@4.1.2: {} - tailwind-merge@3.0.2: {} + tailwind-merge@3.4.0: {} - tailwindcss-animate@1.0.7(tailwindcss@4.0.12): + tailwindcss-animate@1.0.7(tailwindcss@4.1.17): dependencies: - tailwindcss: 4.0.12 + tailwindcss: 4.1.17 - tailwindcss@4.0.12: {} + tailwindcss@4.1.17: {} tapable@2.2.1: {} + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -3131,11 +3296,9 @@ snapshots: tslib@2.8.1: {} - turbo-stream@2.4.0: {} - typescript@5.7.3: {} - undici-types@6.19.8: {} + undici-types@6.21.0: {} universalify@2.0.1: {} @@ -3145,40 +3308,43 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - use-callback-ref@1.3.3(@types/react@19.0.10)(react@19.0.0): + use-callback-ref@1.3.3(@types/react@19.2.4)(react@19.2.0): dependencies: - react: 19.0.0 + react: 19.2.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - use-sidecar@1.1.3(@types/react@19.0.10)(react@19.0.0): + use-sidecar@1.1.3(@types/react@19.2.4)(react@19.2.0): dependencies: detect-node-es: 1.1.0 - react: 19.0.0 + react: 19.2.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.10 + '@types/react': 19.2.4 - vite-plugin-static-copy@2.3.0(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1)): + vite-plugin-static-copy@2.3.2(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1)): dependencies: chokidar: 3.6.0 fast-glob: 3.3.3 fs-extra: 11.3.0 p-map: 7.0.3 picocolors: 1.1.1 - vite: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1) + vite: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1) - vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1): + vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.7.1): dependencies: esbuild: 0.25.1 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 postcss: 8.5.3 rollup: 4.35.0 + tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 20.17.24 + '@types/node': 20.19.25 fsevents: 2.3.3 - jiti: 2.4.2 - lightningcss: 1.29.2 + jiti: 2.6.1 + lightningcss: 1.30.2 yaml: 2.7.1 w3c-keyname@2.2.8: {} @@ -3187,7 +3353,7 @@ snapshots: yaml@2.7.1: {} - zustand@5.0.3(@types/react@19.0.10)(react@19.0.0): + zustand@5.0.8(@types/react@19.2.4)(react@19.2.0): optionalDependencies: - '@types/react': 19.0.10 - react: 19.0.0 + '@types/react': 19.2.4 + react: 19.2.0 diff --git a/blueprints/ackee/template.toml b/blueprints/ackee/template.toml index ebffa3e2..75ef3fe7 100644 --- a/blueprints/ackee/template.toml +++ b/blueprints/ackee/template.toml @@ -10,6 +10,7 @@ serviceName = "ackee" port = 3000 host = "${domain}" + [config.env] ACKEE_USERNAME = "${ACKEE_USERNAME}" ACKEE_PASSWORD = "${ACKEE_PASSWORD}" diff --git a/blueprints/anytype/docker-compose.yml b/blueprints/anytype/docker-compose.yml new file mode 100644 index 00000000..5d516cb6 --- /dev/null +++ b/blueprints/anytype/docker-compose.yml @@ -0,0 +1,19 @@ +# Example: Any-Sync-Bundle with embedded MongoDB and Redis (all-in-one image) +# +# Usage: +# docker compose -f compose.aio.yml up -d +# +# The bundle image already contains MongoDB and Redis. Only the bundle service is required + +services: + any-sync-bundle: + image: ghcr.io/grishy/any-sync-bundle:latest + restart: unless-stopped + ports: + - "33010:33010" + - "33020:33020/udp" + volumes: + - ./data:/data + environment: + # Advertise addresses clients should use. Replace with your server hostname/IP. + ANY_SYNC_BUNDLE_INIT_EXTERNAL_ADDRS: "192.168.100.9" diff --git a/blueprints/anytype/logo.png b/blueprints/anytype/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..903e9aeb1d47985cfc281716145968b29563604f GIT binary patch literal 51321 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

T&E$ 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 uRc+$|O3=DfJ8*(?Z2SN0AI97t&v4`yC2e7ZI*$ literal 0 HcmV?d00001 diff --git a/blueprints/anytype/template.toml b/blueprints/anytype/template.toml new file mode 100644 index 00000000..e1388da7 --- /dev/null +++ b/blueprints/anytype/template.toml @@ -0,0 +1,4 @@ +[config] +domains = [] +mounts = [] +env = [] \ No newline at end of file diff --git a/blueprints/bluesky-pds/bluesky-pds.svg b/blueprints/bluesky-pds/bluesky-pds.svg new file mode 100644 index 00000000..77ebea07 --- /dev/null +++ b/blueprints/bluesky-pds/bluesky-pds.svg @@ -0,0 +1,3 @@ + + + diff --git a/blueprints/bluesky-pds/docker-compose.yml b/blueprints/bluesky-pds/docker-compose.yml new file mode 100644 index 00000000..4f9ae9a2 --- /dev/null +++ b/blueprints/bluesky-pds/docker-compose.yml @@ -0,0 +1,48 @@ +services: + pds: + image: 'ghcr.io/bluesky-social/pds:0.4.182' + volumes: + - pds-data:/pds + environment: + - SERVICE_URL_PDS_3000 + - PDS_HOSTNAME + - PDS_JWT_SECRET + - PDS_ADMIN_PASSWORD + - 'PDS_ADMIN_EMAIL=${PDS_ADMIN_EMAIL}' + - PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX + - 'PDS_DATA_DIRECTORY=${PDS_DATA_DIRECTORY:-/pds}' + - 'PDS_BLOBSTORE_DISK_LOCATION=${PDS_DATA_DIRECTORY:-/pds}/blocks' + - 'PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-104857600}' + - 'PDS_DID_PLC_URL=${PDS_DID_PLC_URL:-https://plc.directory}' + - 'PDS_EMAIL_FROM_ADDRESS=${PDS_EMAIL_FROM_ADDRESS}' + - 'PDS_EMAIL_SMTP_URL=${PDS_EMAIL_SMTP_URL}' + - 'PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL:-https://api.bsky.app}' + - 'PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID:-did:web:api.bsky.app}' + - 'PDS_REPORT_SERVICE_URL=${PDS_REPORT_SERVICE_URL:-https://mod.bsky.app/xrpc/com.atproto.moderation.createReport}' + - 'PDS_REPORT_SERVICE_DID=${PDS_REPORT_SERVICE_DID:-did:plc:ar7c4by46qjdydhdevvrndac}' + - 'PDS_CRAWLERS=${PDS_CRAWLERS:-https://bsky.network}' + - 'LOG_ENABLED=${LOG_ENABLED:-true}' + command: | + sh -c ' + set -euo pipefail + echo "Installing required packages and pdsadmin..." + apk add --no-cache openssl curl bash jq coreutils gnupg util-linux-misc >/dev/null + curl -o /usr/local/bin/pdsadmin.sh https://raw.githubusercontent.com/bluesky-social/pds/main/pdsadmin.sh + chmod 700 /usr/local/bin/pdsadmin.sh + ln -sf /usr/local/bin/pdsadmin.sh /usr/local/bin/pdsadmin + echo "Creating an empty pds.env file so pdsadmin works..." + touch /pds/pds.env + echo "Launching PDS, enjoy!..." + exec node --enable-source-maps index.js + ' + healthcheck: + test: + - CMD + - wget + - '--spider' + - 'http://127.0.0.1:3000/xrpc/_health' + interval: 5s + timeout: 10s + retries: 10 +volumes: + pds-data: \ No newline at end of file diff --git a/blueprints/bluesky-pds/template.toml b/blueprints/bluesky-pds/template.toml new file mode 100644 index 00000000..3de5b201 --- /dev/null +++ b/blueprints/bluesky-pds/template.toml @@ -0,0 +1,36 @@ +[variables] +main_domain = "${domain}" +admin_password = "${password:32}" +jwt_secret = "${jwt:32}" +rotation_key = "${jwt:32}" +data_directory = "/pds" +blob_upload_limit = "104857600" +log_enabled = "true" + +[config] +mounts = [] +env = [ + "PDS_ADMIN_PASSWORD=${admin_password}", + "PDS_HOSTNAME=${main_domain}", + "PDS_JWT_SECRET=${jwt_secret}", + "PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${rotation_key}", + "PDS_ADMIN_EMAIL=", + "PDS_EMAIL_FROM_ADDRESS=", + "PDS_EMAIL_SMTP_URL=", + "PDS_DATA_DIRECTORY=${data_directory}", + "PDS_BLOBSTORE_DISK_LOCATION=${data_directory}/blocks", + "PDS_BLOB_UPLOAD_LIMIT=${blob_upload_limit}", + "PDS_DID_PLC_URL=https://plc.directory", + "PDS_BSKY_APP_VIEW_URL=https://api.bsky.app", + "PDS_BSKY_APP_VIEW_DID=did:web:api.bsky.app", + "PDS_REPORT_SERVICE_URL=https://mod.bsky.app/xrpc/com.atproto.moderation.createReport", + "PDS_REPORT_SERVICE_DID=did:plc:ar7c4by46qjdydhdevvrndac", + "PDS_CRAWLERS=https://bsky.network", + "LOG_ENABLED=${log_enabled}" +] + +[[config.domains]] +serviceName = "pds" +port = 3000 +host = "${main_domain}" +path = "/" \ No newline at end of file diff --git a/blueprints/budibase/docker-compose.yml b/blueprints/budibase/docker-compose.yml index 620324dc..92ad3288 100644 --- a/blueprints/budibase/docker-compose.yml +++ b/blueprints/budibase/docker-compose.yml @@ -182,9 +182,6 @@ services: labels: - com.centurylinklabs.watchtower.enable=false -networks: - dokploy-network: - external: true volumes: minio_data: diff --git a/blueprints/chatwoot/docker-compose.yml b/blueprints/chatwoot/docker-compose.yml index ece9ef44..a43b43f7 100644 --- a/blueprints/chatwoot/docker-compose.yml +++ b/blueprints/chatwoot/docker-compose.yml @@ -4,8 +4,6 @@ x-base-config: &base-config image: chatwoot/chatwoot:v4.0.3 volumes: - chatwoot-storage:/app/storage - networks: - - dokploy-network environment: - FRONTEND_URL=${FRONTEND_URL} - SECRET_KEY_BASE=${SECRET_KEY_BASE} @@ -63,10 +61,6 @@ services: volumes: - chatwoot-redis-data:/data -networks: - dokploy-network: - external: true - volumes: chatwoot-storage: chatwoot-postgres-data: diff --git a/blueprints/chirpstack/chirpstack.png b/blueprints/chirpstack/chirpstack.png new file mode 100644 index 0000000000000000000000000000000000000000..b84e845f357ce883f98865cf8f008de5c25c67d9 GIT binary patch literal 12023 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:@/?sslmode=. + # + # SSL mode options: + # * disable - Do not use TLS + # * prefer - Attempt to connect with TLS but allow sessions without + # * require - Require the use of TLS + dsn="postgres://chirpstack:${postgres_password}@postgres/chirpstack?sslmode=disable" + + # Max open connections. + # + # This sets the max. number of open connections that are allowed in the + # PostgreSQL connection pool. + max_open_connections=10 + + # Min idle connections. + # + # This sets the min. number of idle connections in the PostgreSQL connection + # pool (0 = equal to max_open_connections). + min_idle_connections=0 + + +# Redis configuration. +[redis] + + # Server address or addresses. + # + # Set multiple addresses when connecting to a cluster. + servers=[ + "redis://redis/", + ] + + # TLS enabled. + tls_enabled=false + + # Redis Cluster. + # + # Set this to true when the provided URLs are pointing to a Redis Cluster + # instance. + cluster=false + + +# Network related configuration. +[network] + + # Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203). + net_id="000000" + + # Enabled regions. + # + # Multiple regions can be enabled simultaneously. Each region must match + # the 'name' parameter of the region configuration in '[[regions]]'. + enabled_regions=[ + "as923", + "as923_2", + "as923_3", + "as923_4", + "au915_0", + "cn470_10", + "cn779", + "eu433", + "eu868", + "in865", + "ism2400", + "kr920", + "ru864", + "us915_0", + "us915_1", + ] + + +# API interface configuration. +[api] + + # interface:port to bind the API interface to. + bind="0.0.0.0:8080" + + # Secret. + # + # This secret is used for generating login and API tokens, make sure this + # is never exposed. Changing this secret will invalidate all login and API + # tokens. The following command can be used to generate a random secret: + # openssl rand -base64 32 + secret="${api_secret}" + + +[integration] + enabled=["mqtt"] + + [integration.mqtt] + server="tcp://mosquitto:1883/" + json=true +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_as923_2.toml" +content = """ +# This file contains an example AS923_2 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="as923_2" + + # Description is a short description for this region. + description="AS923-2" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AS923_2" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="as923_2" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=921400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=921600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=921400000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=3 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_as923_3.toml" +content = """ +# This file contains an example AS923_3 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="as923_3" + + # Description is a short description for this region. + description="AS923-3" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AS923_3" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="as923_3" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=916600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=916800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=2 + + # RX2 frequency (Hz) + rx2_frequency=916600000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=3 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_as923_4.toml" +content = """ +# This file contains an example AS923_4 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="as923_4" + + # Description is a short description for this region. + description="AS923-4" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AS923_4" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="as923_4" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=917300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=917500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=2 + + # RX2 frequency (Hz) + rx2_frequency=917300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=3 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_as923.toml" +content = """ +# This file contains an example AS923 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="as923" + + # Description is a short description for this region. + description="AS923" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AS923" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="as923" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=923200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=923400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=2 + + # RX2 frequency (Hz) + rx2_frequency=923200000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=3 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_au915_0.toml" +content = """ +# This file contains an example AU915 example (channels 0-7 + 64). +[[regions]] + + # ID is an use-defined identifier for this region. + id="au915_0" + + # Description is a short description for this region. + description="AU915 (channels 0-7 + 64)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AU915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="au915_0" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=915200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=915400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=915600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=915800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=916000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=916200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=916400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=916600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=915900000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[0, 1, 2, 3, 4, 5, 6, 7, 64] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_au915_1.toml" +content = """ +# This file contains an example AU915 example (channels 8-15 + 65). +[[regions]] + + # ID is an use-defined identifier for this region. + id="au915_1" + + # Description is a short description for this region. + description="AU915 (channels 8-15 + 65)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AU915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="au915_1" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=916800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=917000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=917200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=917400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=917600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=917800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=918000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=918200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=917500000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[8, 9, 10, 11, 12, 13, 14, 15, 65] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_au915_2.toml" +content = """ +# This file contains an example AU915 example (channels 16-23 + 66). +[[regions]] + + # ID is an use-defined identifier for this region. + id="au915_2" + + # Description is a short description for this region. + description="AU915 (channels 16-23 + 65)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AU915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="au915_2" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=918400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=918600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=918800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=919000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=919200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=919400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=919600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=919800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=919100000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[16, 17, 18, 19, 20, 21, 22, 23, 65] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_au915_3.toml" +content = """ +# This file contains an example AU915 example (channels 24-31 + 67). +[[regions]] + + # ID is an use-defined identifier for this region. + id="au915_3" + + # Description is a short description for this region. + description="AU915 (channels 24-31 + 67)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AU915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="au915_3" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=920000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=920200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=920400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=920600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=920800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=921000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=921200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=921400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=920700000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[24, 25, 26, 27, 28, 29, 30, 31, 67] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_au915_4.toml" +content = """ +# This file contains an example AU915 example (channels 32-39 + 68). +[[regions]] + + # ID is an use-defined identifier for this region. + id="au915_4" + + # Description is a short description for this region. + description="AU915 (channels 32-39 + 68)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AU915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="au915_4" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=921600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=921800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=922000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=922200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=922400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=922600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=922800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=923000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=922300000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[32, 33, 34, 35, 36, 37, 38, 39, 68] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_au915_5.toml" +content = """ +# This file contains an example AU915 example (channels 40-47 + 69). +[[regions]] + + # ID is an use-defined identifier for this region. + id="au915_5" + + # Description is a short description for this region. + description="AU915 (channels 40-47 + 69)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AU915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="au915_5" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=923200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=923400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=923600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=923800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=924000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=924200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=924400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=924600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=923900000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[40, 41, 42, 43, 44, 45, 46, 47, 69] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_au915_6.toml" +content = """ +# This file contains an example AU915 example (channels 48-55 + 70). +[[regions]] + + # ID is an use-defined identifier for this region. + id="au915_6" + + # Description is a short description for this region. + description="AU915 (channels 48-55 + 70)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AU915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="au915_6" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=924800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=925000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=925200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=925400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=925600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=925800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=926000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=926200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=925500000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[48, 49, 50, 51, 52, 53, 54, 55, 70] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_au915_7.toml" +content = """ +# This file contains an example AU915 example (channels 56-63 + 71). +[[regions]] + + # ID is an use-defined identifier for this region. + id="au915_7" + + # Description is a short description for this region. + description="AU915 (channels 56-63 + 71)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="AU915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="au915_7" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=926400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=926600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=926800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=927000000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=927200000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=927400000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=927600000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=927800000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=927100000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[56, 57, 58, 59, 60, 61, 62, 63, 71] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_0.toml" +content = """ +# This file contains an example CN470 example (channels 0-7). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_0" + + # Description is a short description for this region. + description="CN470 (channels 0-7)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_0" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=470300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=470500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=470700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=470900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=471100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=471300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=471500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=471700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[0, 1, 2, 3, 4, 5, 6, 7] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_10.toml" +content = """ +# This file contains an example CN470 example (channels 80-87). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_10" + + # Description is a short description for this region. + description="CN470 (channels 80-87)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_10" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=486300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=486500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=486700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=486900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=487100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=487300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=487500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=487700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[80, 81, 82, 83, 84, 85, 86, 87] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_11.toml" +content = """ +# This file contains an example CN470 example (channels 88-95). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_11" + + # Description is a short description for this region. + description="CN470 (channels 88-95)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_11" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=487900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=488100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=488300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=488500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=488700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=488900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=489100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=489300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[88, 89, 90, 91, 92, 93, 94, 95] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_1.toml" +content = """ +# This file contains an example CN470 example (channels 8-15). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_1" + + # Description is a short description for this region. + description="CN470 (channels 8-15)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_1" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=471900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=472100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=472300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=472500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=472700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=472900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=473100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=473300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[8, 9, 10, 11, 12, 13, 14, 15] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_2.toml" +content = """ +# This file contains an example CN470 example (channels 16-23). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_2" + + # Description is a short description for this region. + description="CN470 (channels 16-23)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_2" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=473500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=473700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=473900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=474100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=474300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=474500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=474700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=474900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[16, 17, 18, 19, 20, 21, 22, 23] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_3.toml" +content = """ +# This file contains an example CN470 example (channels 24-31). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_3" + + # Description is a short description for this region. + description="CN470 (channels 24-31)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_3" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=475100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=475300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=475500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=475700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=475900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=476100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=476300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=476500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[24, 25, 26, 27, 28, 29, 30, 31] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_4.toml" +content = """ +# This file contains an example CN470 example (channels 32-39). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_4" + + # Description is a short description for this region. + description="CN470 (channels 32-39)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_4" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=476700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=476900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=477100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=477300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=477500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=477700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=477900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=478100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[32, 33, 34, 35, 36, 37, 38, 39] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_5.toml" +content = """ +# This file contains an example CN470 example (channels 40-47). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_5" + + # Description is a short description for this region. + description="CN470 (channels 40-47)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_5" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=478300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=478500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=478700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=478900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=479100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=479300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=479500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=479700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[40, 41, 42, 43, 44, 45, 46, 47] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_6.toml" +content = """ +# This file contains an example CN470 example (channels 48-55). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_6" + + # Description is a short description for this region. + description="CN470 (channels 48-55)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_6" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=479900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=480100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=480300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=480500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=480700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=480900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=481100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=481300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[48, 49, 50, 51, 52, 53, 54, 55] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_7.toml" +content = """ +# This file contains an example CN470 example (channels 56-63). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_7" + + # Description is a short description for this region. + description="CN470 (channels 56-63)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_7" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=481500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=481700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=481900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=482100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=482300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=482500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=482700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=482900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[56, 57, 58, 59, 60, 61, 62, 63] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_8.toml" +content = """ +# This file contains an example CN470 example (channels 64-71). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_8" + + # Description is a short description for this region. + description="CN470 (channels 64-71)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_8" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=483100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=483300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=483500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=483700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=483900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=484100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=484300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=484500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[64, 65, 66, 67, 68, 69, 70, 71] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn470_9.toml" +content = """ +# This file contains an example CN470 example (channels 72-79). +[[regions]] + + # ID is an use-defined identifier for this region. + id="cn470_9" + + # Description is a short description for this region. + description="CN470 (channels 72-79)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN470" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn470_9" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=484700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=484900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=485100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=485300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=485500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=485700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=485900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=486100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=505300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[72, 73, 74, 75, 76, 77, 78, 79] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=2 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_cn779.toml" +content = """ +# This file contains an example CN779 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="cn779" + + # Description is a short description for this region. + description="CN779" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="CN779" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="cn779" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=779500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=779700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=779900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=786000000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=3 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_eu433.toml" +content = """ +# This file contains an example EU433 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="eu433" + + # Description is a short description for this region. + description="EU443" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="EU433" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="eu433" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=433175000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=433375000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=433575000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=434665000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=3 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_eu868.toml" +content = """ +# This file contains an example EU868 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="eu868" + + # Description is a short description for this region. + description="EU868" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="EU868" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="eu868" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=868100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=868300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=868500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=867100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=867300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=867500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=867700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=867900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=868300000 + bandwidth=250000 + modulation="LORA" + spreading_factors=[7] + + [[regions.gateway.channels]] + frequency=868800000 + bandwidth=125000 + modulation="FSK" + datarate=50000 + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=869525000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=3 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Below is the common set of extra channels. Please make sure that these + # channels are also supported by the gateways. + [[regions.network.extra_channels]] + frequency=867100000 + min_dr=0 + max_dr=5 + + [[regions.network.extra_channels]] + frequency=867300000 + min_dr=0 + max_dr=5 + + [[regions.network.extra_channels]] + frequency=867500000 + min_dr=0 + max_dr=5 + + [[regions.network.extra_channels]] + frequency=867700000 + min_dr=0 + max_dr=5 + + [[regions.network.extra_channels]] + frequency=867900000 + min_dr=0 + max_dr=5 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_in865.toml" +content = """ +# This file contains an example IN865 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="in865" + + # Description is a short description for this region. + description="IN865" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="IN865" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="in865" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=865062500 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=865402500 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=865985000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=2 + + # RX2 frequency (Hz) + rx2_frequency=866550000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=4 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_ism2400.toml" +content = """ +# This file contains an example ISM2400 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="ism2400" + + # Description is a short description for this region. + description="ISM2400" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="ISM2400" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="ism2400" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=2403000000 + bandwidth=812000 + modulation="LORA" + spreading_factors=[12] + + [[regions.gateway.channels]] + frequency=2479000000 + bandwidth=812000 + modulation="LORA" + spreading_factors=[12] + + [[regions.gateway.channels]] + frequency=2425000000 + bandwidth=812000 + modulation="LORA" + spreading_factors=[12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=2423000000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=7 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_kr920.toml" +content = """ +# This file contains an example KR920 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="kr920" + + # Description is a short description for this region. + description="KR920" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="KR920" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="kr920" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=922100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=922300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=922500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=921900000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=3 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_ru864.toml" +content = """ +# This file contains an example RU864 configuration. +[[regions]] + + # ID is an user-defined identifier for this region. + id="ru864" + + # Description is a short description for this region. + description="RU864" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="RU864" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="ru864" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=868900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + [[regions.gateway.channels]] + frequency=869100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10, 11, 12] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=0 + + # RX2 frequency (Hz) + rx2_frequency=869100000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=5 + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=3 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_us915_0.toml" +content = """ +# This file contains an example US915 example (channels 0-7 + 64). +[[regions]] + + # ID is an use-defined identifier for this region. + id="us915_0" + + # Description is a short description for this region. + description="US915 (channels 0-7 + 64)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="US915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="us915_0" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=902300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=902500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=902700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=902900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=903100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=903300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=903500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=903700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=903000000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=3 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[0, 1, 2, 3, 4, 5, 6, 7, 64] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_us915_1.toml" +content = """ +# This file contains an example US915 example (channels 8-15 + 65). +[[regions]] + + # ID is an use-defined identifier for this region. + id="us915_1" + + # Description is a short description for this region. + description="US915 (channels 8-15 + 65)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="US915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="us915_1" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=903900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=904100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=904300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=904500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=904700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=904900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=905100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=905300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=904600000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=3 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[8, 9, 10, 11, 12, 13, 14, 15, 65] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_us915_2.toml" +content = """ +# This file contains an example US915 example (channels 16-23 + 66). +[[regions]] + + # ID is an use-defined identifier for this region. + id="us915_2" + + # Description is a short description for this region. + description="US915 (channels 16-23 + 66)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="US915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="us915_2" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=905500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=905700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=905900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=906100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=906300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=906500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=906700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=906900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=906200000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=3 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[16, 17, 18, 19, 20, 21, 22, 23, 66] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_us915_3.toml" +content = """ +# This file contains an example US915 example (channels 24-31 + 67). +[[regions]] + + # ID is an use-defined identifier for this region. + id="us915_3" + + # Description is a short description for this region. + description="US915 (channels 24-31 + 67)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="US915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="us915_3" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=907100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=907300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=907500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=907700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=907900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=908100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=908300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=908500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=907800000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=3 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[24, 25, 26, 27, 28, 29, 30, 31, 67] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_us915_4.toml" +content = """ +# This file contains an example US915 example (channels 32-39 + 68). +[[regions]] + + # ID is an use-defined identifier for this region. + id="us915_4" + + # Description is a short description for this region. + description="US915 (channels 32-39 + 68)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="US915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="us915_4" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=908700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=908900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=909100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=909300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=909500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=909700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=909900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=910100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=909400000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=3 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[32, 33, 34, 35, 36, 37, 38, 39, 68] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_us915_5.toml" +content = """ +# This file contains an example US915 example (channels 40-47 + 69). +[[regions]] + + # ID is an use-defined identifier for this region. + id="us915_5" + + # Description is a short description for this region. + description="US915 (channels 40-47 + 69)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="US915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="us915_5" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=910300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=910500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=910700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=910900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=911100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=911300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=911500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=911700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=911000000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=3 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[40, 41, 42, 43, 44, 45, 46, 47, 69] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_us915_6.toml" +content = """ +# This file contains an example US915 example (channels 48-55 + 70). +[[regions]] + + # ID is an use-defined identifier for this region. + id="us915_6" + + # Description is a short description for this region. + description="US915 (channels 48-55 + 70)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="US915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="us915_6" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=911900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=912100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=912300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=912500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=912700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=912900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=913100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=913300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=912600000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=3 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[48, 49, 50, 51, 52, 53, 54, 55, 70] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack" +filePath = "/chirpstack/region_us915_7.toml" +content = """ +# This file contains an example US915 example (channels 56-63 + 71). +[[regions]] + + # ID is an use-defined identifier for this region. + id="us915_7" + + # Description is a short description for this region. + description="US915 (channels 56-63 + 71)" + + # Common-name refers to the common-name of this region as defined by + # the LoRa Alliance. + common_name="US915" + + + # Gateway configuration. + [regions.gateway] + + # Force gateways as private. + # + # If enabled, gateways can only be used by devices under the same tenant. + force_gws_private=false + + + # Gateway backend configuration. + [regions.gateway.backend] + + # The enabled backend type. + enabled="mqtt" + + # MQTT configuration. + [regions.gateway.backend.mqtt] + + # Topic prefix. + # + # The topic prefix can be used to define the region of the gateway. + # Note, there is no need to add a trailing '/' to the prefix. The trailing + # '/' is automatically added to the prefix if it is configured. + topic_prefix="us915_7" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://mosquitto:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + # Quality of service level + # + # 0: at most once + # 1: at least once + # 2: exactly once + # + # Note: an increase of this value will decrease the performance. + # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels + qos=0 + + # Clean session + # + # Set the "clean session" flag in the connect message when this client + # connects to an MQTT broker. By setting this flag you are indicating + # that no messages saved by the broker for this client should be delivered. + clean_session=false + + # Client ID + # + # Set the client id to be used by this client when connecting to the MQTT + # broker. A client id must be no longer than 23 characters. If left blank, + # a random id will be generated by ChirpStack. + client_id="" + + # Keep alive interval. + # + # This defines the maximum time that that should pass without communication + # between the client and server. + keep_alive_interval="30s" + + # CA certificate file (optional) + # + # Use this when setting up a secure connection (when server uses ssl://...) + # but the certificate used by the server is not trusted by any CA certificate + # on the server (e.g. when self generated). + ca_cert="" + + # TLS certificate file (optional) + tls_cert="" + + # TLS key file (optional) + tls_key="" + + + # Gateway channel configuration. + # + # Note: this configuration is only used in case the gateway is using the + # ChirpStack Concentratord daemon. In any other case, this configuration + # is ignored. + [[regions.gateway.channels]] + frequency=913500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=913700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=913900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=914100000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=914300000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=914500000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=914700000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=914900000 + bandwidth=125000 + modulation="LORA" + spreading_factors=[7, 8, 9, 10] + + [[regions.gateway.channels]] + frequency=914200000 + bandwidth=500000 + modulation="LORA" + spreading_factors=[8] + + + # Region specific network configuration. + [regions.network] + + # Installation margin (dB) used by the ADR engine. + # + # A higher number means that the network-server will keep more margin, + # resulting in a lower data-rate but decreasing the chance that the + # device gets disconnected because it is unable to reach one of the + # surrounded gateways. + installation_margin=10 + + # RX window (Class-A). + # + # Set this to: + # 0: RX1 / RX2 + # 1: RX1 only + # 2: RX2 only + rx_window=0 + + # RX1 delay (1 - 15 seconds). + rx1_delay=1 + + # RX1 data-rate offset + rx1_dr_offset=0 + + # RX2 data-rate + rx2_dr=8 + + # RX2 frequency (Hz) + rx2_frequency=923300000 + + # Prefer RX2 on RX1 data-rate less than. + # + # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate + # is smaller than the configured value, then the Network Server will + # first try to schedule the downlink for RX2, failing that (e.g. the gateway + # has already a payload scheduled at the RX2 timing) it will try RX1. + rx2_prefer_on_rx1_dr_lt=0 + + # Prefer RX2 on link budget. + # + # When the link-budget is better for RX2 than for RX1, the Network Server will first + # try to schedule the downlink in RX2, failing that it will try RX1. + rx2_prefer_on_link_budget=false + + # Downlink TX Power (dBm) + # + # When set to -1, the downlink TX Power from the configured band will + # be used. + # + # Please consult the LoRaWAN Regional Parameters and local regulations + # for valid and legal options. Note that the configured TX Power must be + # supported by your gateway(s). + downlink_tx_power=-1 + + # ADR is disabled. + adr_disabled=false + + # Minimum data-rate. + min_dr=0 + + # Maximum data-rate. + max_dr=3 + + # Enabled uplink channels. + # + # Use this when ony a sub-set of the by default enabled channels are being + # used. For example when only using the first 8 channels of the US band. + # Note: when left blank / empty array, all channels will be enabled. + enabled_uplink_channels=[56, 57, 58, 59, 60, 61, 62, 63, 71] + + + # Rejoin-request configuration (LoRaWAN 1.1) + [regions.network.rejoin_request] + + # Request devices to periodically send rejoin-requests. + enabled=false + + # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4) + # uplink messages. Valid values are 0 to 15. + max_count_n=0 + + # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10) + # seconds. Valid values are 0 to 15. + # + # 0 = roughly 17 minutes + # 15 = about 1 year + max_time_n=0 + + + # Class-B configuration. + [regions.network.class_b] + + # Ping-slot data-rate. + ping_slot_dr=8 + + # Ping-slot frequency (Hz) + # + # set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 +""" + +[[config.mounts]] +serviceName = "chirpstack-gateway-bridge" +filePath = "/chirpstack-gateway-bridge/chirpstack-gateway-bridge.toml" +content = """ +# See https://www.chirpstack.io/gateway-bridge/install/config/ for a full +# configuration example and documentation. + +[integration.mqtt.auth.generic] +servers=["tcp://mosquitto:1883"] +username="" +password="" +""" + +[[config.mounts]] +serviceName = "chirpstack-gateway-bridge-basicstation" +filePath = "/chirpstack-gateway-bridge/chirpstack-gateway-bridge-basicstation-eu868.toml" +content = """ +# See https://www.chirpstack.io/gateway-bridge/install/config/ for a full +# configuration example and documentation. + +[integration.mqtt.auth.generic] +servers=["tcp://mosquitto:1883"] +username="" +password="" + +[integration.mqtt] +event_topic_template="eu868/gateway/{{ .GatewayID }}/event/{{ .EventType }}" +state_topic_template="eu868/gateway/{{ .GatewayID }}/state/{{ .StateType }}" +command_topic_template="eu868/gateway/{{ .GatewayID }}/command/#" + +[backend] +type="basic_station" + + [backend.basic_station] + bind=":3001" + tls_cert="" + tls_key="" + ca_cert="" + + region="EU868" + frequency_min=863000000 + frequency_max=870000000 + + + [[backend.basic_station.concentrators]] + + [backend.basic_station.concentrators.multi_sf] + frequencies=[ + 868100000, + 868300000, + 868500000, + 867100000, + 867300000, + 867500000, + 867700000, + 867900000, + ] + + [backend.basic_station.concentrators.lora_std] + frequency=868300000 + bandwidth=250000 + spreading_factor=7 + + [backend.basic_station.concentrators.fsk] + frequency=868800000 +""" + +[[config.mounts]] +serviceName = "mosquitto" +filePath = "/mosquitto/config/mosquitto.conf" +content = """ +listener 1883 +allow_anonymous true +""" + +[[config.mounts]] +serviceName = "postgres" +filePath = "/postgresql/initdb/001-chirpstack_extensions.sh" +content = """ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname="$POSTGRES_DB" <<-EOSQL + create extension pg_trgm; + create extension hstore; +EOSQL +""" diff --git a/blueprints/conduit/docker-compose.yml b/blueprints/conduit/docker-compose.yml index f2f1fb34..8f774673 100644 --- a/blueprints/conduit/docker-compose.yml +++ b/blueprints/conduit/docker-compose.yml @@ -7,8 +7,6 @@ services: restart: unless-stopped volumes: - db:/var/lib/matrix-conduit/ - networks: - - dokploy-network environment: CONDUIT_SERVER_NAME: ${MATRIX_SUBDOMAIN} CONDUIT_DATABASE_PATH: /var/lib/matrix-conduit/ @@ -25,7 +23,3 @@ services: CONDUIT_CONFIG: '' # Ignore this volumes: db: - -networks: - dokploy-network: - external: true diff --git a/blueprints/discord-tickets/docker-compose.yml b/blueprints/discord-tickets/docker-compose.yml index f797a77b..62105b3a 100644 --- a/blueprints/discord-tickets/docker-compose.yml +++ b/blueprints/discord-tickets/docker-compose.yml @@ -45,10 +45,6 @@ services: PUBLISH_COMMANDS: "true" SUPER: ${SUPER_USERS} -networks: - dokploy-network: - external: true - volumes: tickets-mysql-data: tickets-app-data: \ No newline at end of file diff --git a/blueprints/docmost/docker-compose.yml b/blueprints/docmost/docker-compose.yml index b5995594..d7efba92 100644 --- a/blueprints/docmost/docker-compose.yml +++ b/blueprints/docmost/docker-compose.yml @@ -34,10 +34,6 @@ services: volumes: - redis_docmost_data:/data -networks: - dokploy-network: - external: true - volumes: docmost: db_docmost_data: diff --git a/blueprints/dokploy-prom-monitoring-extension/docker-compose.yml b/blueprints/dokploy-prom-monitoring-extension/docker-compose.yml new file mode 100644 index 00000000..1fd3e03d --- /dev/null +++ b/blueprints/dokploy-prom-monitoring-extension/docker-compose.yml @@ -0,0 +1,11 @@ +services: + dokploy-monitoring: + image: dokploy/monitoring:canary + restart: unless-stopped + env_file: + - .env + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - monitoring-data:/app/data +volumes: + monitoring-data: {} diff --git a/blueprints/dokploy-prom-monitoring-extension/logo.svg b/blueprints/dokploy-prom-monitoring-extension/logo.svg new file mode 100644 index 00000000..5c6a02e4 --- /dev/null +++ b/blueprints/dokploy-prom-monitoring-extension/logo.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/blueprints/dokploy-prom-monitoring-extension/template.toml b/blueprints/dokploy-prom-monitoring-extension/template.toml new file mode 100644 index 00000000..bd0c07b5 --- /dev/null +++ b/blueprints/dokploy-prom-monitoring-extension/template.toml @@ -0,0 +1,17 @@ +[variables] +main_domain = "${domain}" +monitoring_token = "${password:32}" +callback_url = "http://dokploy:3000/api/trpc/notification.receiveNotification" +server_type = "Dokploy" +refresh_rate = "30" +retention_days = "7" +cpu_threshold = "80" +memory_threshold = "85" + +[[config.domains]] +serviceName = "dokploy-monitoring" +port = 3001 +host = "${main_domain}" + +[config.env] +METRICS_CONFIG = "{\"server\":{\"refreshRate\":${refresh_rate},\"port\":3001,\"type\":\"${server_type}\",\"token\":\"${monitoring_token}\",\"urlCallback\":\"${callback_url}\",\"retentionDays\":${retention_days},\"cronJob\":\"0 0 * * *\",\"thresholds\":{\"cpu\":${cpu_threshold},\"memory\":${memory_threshold}},\"prometheus\":{\"enabled\":true}},\"containers\":{\"refreshRate\":${refresh_rate},\"services\":{\"include\":[],\"exclude\":[]}}}" diff --git a/blueprints/drawio/docker-compose.yml b/blueprints/drawio/docker-compose.yml index a7d7b578..cdd036d9 100644 --- a/blueprints/drawio/docker-compose.yml +++ b/blueprints/drawio/docker-compose.yml @@ -51,9 +51,5 @@ services: DRAWIO_GITLAB_SECRET: ${DRAWIO_GITLAB_SECRET} DRAWIO_GITLAB_URL: ${DRAWIO_GITLAB_URL} DRAWIO_CLOUD_CONVERT_APIKEY: ${DRAWIO_CLOUD_CONVERT_APIKEY} -networks: - dokploy-network: - external: true - volumes: fonts_volume: \ No newline at end of file diff --git a/blueprints/enshrouded/docker-compose.yml b/blueprints/enshrouded/docker-compose.yml index 9c92efb3..614dd36e 100644 --- a/blueprints/enshrouded/docker-compose.yml +++ b/blueprints/enshrouded/docker-compose.yml @@ -1,18 +1,25 @@ services: enshrouded: - image: sknnr/enshrouded-dedicated-server:latest + image: mornedhels/enshrouded-server:latest + container_name: enshrouded + hostname: enshrouded restart: unless-stopped + stop_grace_period: 90s ports: - "15637:15637/udp" - "27015:27015/udp" + volumes: + - enshrouded-persistent-data:/opt/enshrouded + # only add ntsync device if your kernel supports it (6.14 or newer) + # devices: + # - /dev/ntsync:/dev/ntsync environment: - SERVER_NAME=${SERVER_NAME} - SERVER_PASSWORD=${SERVER_PASSWORD} - - PORT=15637 - - SERVER_SLOTS=6 - - SERVER_IP=0.0.0.0 - volumes: - - enshrouded-persistent-data:/home/steam/enshrouded/savegame + - SERVER_SLOT_COUNT=6 + - UPDATE_CRON=0 3 * * * + - PUID=4711 + - PGID=4711 volumes: enshrouded-persistent-data: \ No newline at end of file diff --git a/blueprints/evolutionapi/docker-compose.yml b/blueprints/evolutionapi/docker-compose.yml index d4803de1..5807ff82 100644 --- a/blueprints/evolutionapi/docker-compose.yml +++ b/blueprints/evolutionapi/docker-compose.yml @@ -47,11 +47,6 @@ services: volumes: - evolution-redis-data:/data - -networks: - dokploy-network: - external: true - volumes: evolution-instances: evolution-postgres-data: diff --git a/blueprints/firecrawl/docker-compose.yml b/blueprints/firecrawl/docker-compose.yml index f4181cfc..d7622f7a 100644 --- a/blueprints/firecrawl/docker-compose.yml +++ b/blueprints/firecrawl/docker-compose.yml @@ -124,15 +124,6 @@ services: interval: 10s timeout: 5s retries: 10 - networks: - - backend - - dokploy-network - -networks: - backend: - driver: bridge - dokploy-network: - external: true volumes: nuq_pg_data: \ No newline at end of file diff --git a/blueprints/glpi/docker-compose.yml b/blueprints/glpi/docker-compose.yml index fa732fa3..3abe1f05 100644 --- a/blueprints/glpi/docker-compose.yml +++ b/blueprints/glpi/docker-compose.yml @@ -20,7 +20,3 @@ services: volumes: glpi-mysql-data: glpi-www-data: - -networks: - dokploy-network: - external: true \ No newline at end of file diff --git a/blueprints/hi-events/docker-compose.yml b/blueprints/hi-events/docker-compose.yml index cce45fec..3c2291b9 100644 --- a/blueprints/hi-events/docker-compose.yml +++ b/blueprints/hi-events/docker-compose.yml @@ -36,9 +36,5 @@ services: volumes: - pg_hi-events_data:/var/lib/postgresql/data -networks: - dokploy-network: - external: true - volumes: pg_hi-events_data: \ No newline at end of file diff --git a/blueprints/immich/docker-compose.yml b/blueprints/immich/docker-compose.yml index cdd31199..8f12d6d1 100644 --- a/blueprints/immich/docker-compose.yml +++ b/blueprints/immich/docker-compose.yml @@ -96,10 +96,6 @@ services: ] restart: always -networks: - dokploy-network: - external: true - volumes: immich-model-cache: immich-postgres: diff --git a/blueprints/infisical/docker-compose.yml b/blueprints/infisical/docker-compose.yml index 7566c898..ac5718bc 100644 --- a/blueprints/infisical/docker-compose.yml +++ b/blueprints/infisical/docker-compose.yml @@ -3,7 +3,7 @@ services: depends_on: db: condition: service_healthy - image: infisical/infisical:v0.90.1-postgres + image: infisical/infisical:v0.135.0-postgres environment: - NODE_ENV=production - ENCRYPTION_KEY @@ -20,7 +20,6 @@ services: command: npm run migration:latest pull_policy: always - backend: restart: unless-stopped depends_on: @@ -30,7 +29,7 @@ services: condition: service_started db-migration: condition: service_completed_successfully - image: infisical/infisical:v0.90.1-postgres + image: infisical/infisical:v0.135.0-postgres pull_policy: always environment: - NODE_ENV=production @@ -77,7 +76,5 @@ volumes: pg_infisical_data: redis_infisical_data: -networks: - dokploy-network: - external: true + diff --git a/blueprints/invoiceshelf/docker-compose.yml b/blueprints/invoiceshelf/docker-compose.yml index 0f1c3d2c..8d2c8265 100644 --- a/blueprints/invoiceshelf/docker-compose.yml +++ b/blueprints/invoiceshelf/docker-compose.yml @@ -47,10 +47,6 @@ services: invoiceshelf-postgres: condition: service_healthy -networks: - dokploy-network: - external: true - volumes: invoiceshelf-postgres-data: invoiceshelf-app-data: diff --git a/blueprints/kimai/docker-compose.yml b/blueprints/kimai/docker-compose.yml index d3eab1c3..c97cadfb 100644 --- a/blueprints/kimai/docker-compose.yml +++ b/blueprints/kimai/docker-compose.yml @@ -40,10 +40,6 @@ services: start_period: 30s -networks: - dokploy-network: - external: true - volumes: kimai-data: mysql-data: \ No newline at end of file diff --git a/blueprints/kokoro-tts/docker-compose.yml b/blueprints/kokoro-tts/docker-compose.yml new file mode 100644 index 00000000..a0298ce1 --- /dev/null +++ b/blueprints/kokoro-tts/docker-compose.yml @@ -0,0 +1,23 @@ +services: + kokoro-tts: + build: + context: https://github.com/remsky/Kokoro-FastAPI.git#master + dockerfile: docker/cpu/Dockerfile + restart: unless-stopped + ports: + - 8880 + environment: + - MODEL_PATH=/app/models + - DEVICE=${DEVICE:-cpu} + - HOST=0.0.0.0 + - PORT=8880 + volumes: + - kokoro-models:/app/models + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8880/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s +volumes: + kokoro-models: diff --git a/blueprints/kokoro-tts/kokoro-tts.svg b/blueprints/kokoro-tts/kokoro-tts.svg new file mode 100644 index 00000000..5ed64ed8 --- /dev/null +++ b/blueprints/kokoro-tts/kokoro-tts.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/blueprints/kokoro-tts/template.toml b/blueprints/kokoro-tts/template.toml new file mode 100644 index 00000000..73f367c4 --- /dev/null +++ b/blueprints/kokoro-tts/template.toml @@ -0,0 +1,72 @@ +[variables] +main_domain = "${domain}" +device = "cpu" + +[config] +env = [ + "DEVICE=${device}", + "MODEL_PATH=/app/models", + "HOST=0.0.0.0", + "PORT=8880", + "PYTHONUNBUFFERED=1", + "UV_SYSTEM_PYTHON=1" +] + +[[config.domains]] +serviceName = "kokoro-tts" +port = 8880 +host = "${main_domain}" +path = "/" + +[[config.mounts]] +filePath = "README.md" +content = """# Kokoro TTS FastAPI + +This template provides a Dockerized FastAPI wrapper for the Kokoro-82M text-to-speech model. + +## Features + +- Multi-language support (English, Japanese, Chinese) +- OpenAI-compatible speech endpoint +- CPU and GPU support +- Web interface for monitoring +- RESTful API with comprehensive documentation +- Streaming audio generation +- Word-level timestamps and phonemes + +## Usage + +- **Web Interface**: Access the web UI at `https://${main_domain}/web` +- **API Documentation**: Available at `https://${main_domain}/docs` +- **Health Check**: Monitor service health at `https://${main_domain}/health` + +## Configuration + +The service runs on port 8880 and supports both CPU and GPU inference. +For GPU support, ensure your Dokploy instance has NVIDIA GPU support enabled. + +## API Endpoints + +- `POST /v1/audio/speech` - Generate speech from text (OpenAI compatible) +- `POST /dev/captioned_speech` - Generate speech with timestamps +- `POST /dev/phonemize` - Convert text to phonemes +- `POST /dev/generate_from_phonemes` - Generate audio from phonemes +- `GET /health` - Health check endpoint +- `GET /docs` - Interactive API documentation +- `GET /web` - Web interface + +## Model Information + +- Model: Kokoro-82M +- License: Apache-2.0 +- Repository: https://github.com/remsky/Kokoro-FastAPI +- HuggingFace Model: https://huggingface.co/hexgrad/Kokoro-82M + +## Notes + +- This template builds the image from source during deployment +- Uses CPU-optimized Dockerfile by default +- Initial build may take several minutes due to model download +- Ensure sufficient disk space for model storage +- For GPU support, change dockerfile path to `docker/gpu/Dockerfile` in docker-compose.yml +""" diff --git a/blueprints/kutt/docker-compose.yml b/blueprints/kutt/docker-compose.yml index 5ee1b971..947f4d26 100644 --- a/blueprints/kutt/docker-compose.yml +++ b/blueprints/kutt/docker-compose.yml @@ -7,7 +7,7 @@ services: environment: DB_FILENAME: "/var/lib/kutt/data.sqlite" JWT_SECRET: ${JWT_SECRET} - DEFAULT_DOMAIN: ${DOMAIN} + DEFAULT_DOMAIN: ${DEFAULT_DOMAIN} TRUST_PROXY: ${TRUST_PROXY} DISALLOW_ANONYMOUS_LINKS: ${DISALLOW_ANONYMOUS_LINKS} CUSTOM_DOMAIN_USE_HTTPS: ${CUSTOM_DOMAIN_USE_HTTPS} diff --git a/blueprints/librechat/docker-compose.yml b/blueprints/librechat/docker-compose.yml new file mode 100644 index 00000000..a5a4c5a9 --- /dev/null +++ b/blueprints/librechat/docker-compose.yml @@ -0,0 +1,110 @@ +# LibreChat Docker Compose for Dokploy Template +# Setting up authentication: "npm run create-user", refer to https://www.librechat.ai/docs/configuration/authentication + +services: + librechat: + image: ghcr.io/danny-avila/librechat-dev:latest + restart: always + depends_on: + - mongodb + - rag_api + environment: + # Server Configuration + - HOST=0.0.0.0 + - PORT=${PORT:-3080} + # Domain Configuration + - DOMAIN_CLIENT=${DOMAIN_CLIENT} + - DOMAIN_SERVER=${DOMAIN_SERVER} + # Database and Search Configuration + - MONGO_URI=mongodb://mongodb:27017/LibreChat + - MEILI_HOST=http://meilisearch:7700 + - SEARCH=true + - NO_INDEX=true + - MEILI_NO_ANALYTICS=true + - MEILI_MASTER_KEY=${MEILI_MASTER_KEY} + # Security & Sessions + - JWT_SECRET=${JWT_SECRET} + - JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET} + - CREDS_KEY=${CREDS_KEY} + - CREDS_IV=${CREDS_IV} + - RAG_PORT=${RAG_PORT:-8000} + - RAG_API_URL=http://rag_api:${RAG_PORT:-8000} + # API Keys and Secrets + - OPENAI_API_KEY=${OPENAI_API_KEY} + - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} + - OPENROUTER_KEY=${OPENROUTER_KEY} + - GOOGLE_KEY=${GOOGLE_KEY} + - ENDPOINTS=google,openAI,assistants,azureOpenAI,anthropic + # ... Additional Endpoints + # UI + - APP_TITLE=${APP_TITLE:-LibreChat} + - CUSTOM_FOOTER=${CUSTOM_FOOTER:-Made with ❀️ by LibreChat} + - ALLOW_EMAIL_LOGIN=${ALLOW_EMAIL_LOGIN:-true} + - ALLOW_SOCIAL_LOGIN=${ALLOW_SOCIAL_LOGIN:-false} + - ALLOW_REGISTRATION=${ALLOW_REGISTRATION:-false} + volumes: + - type: bind + source: ../files/librechat.yaml + target: /app/librechat.yaml + - librechat_data:/app/client/public/images + - librechat_data:/app/uploads + - librechat_data:/app/logs + + mongodb: + image: mongo + restart: always + volumes: + - mongo_data:/data/db + command: mongod --noauth + + meilisearch: + image: getmeili/meilisearch:v1.12.3 + restart: always + environment: + - MEILI_HOST=http://meilisearch:7700 + - MEILI_NO_ANALYTICS=true + - MEILI_MASTER_KEY=${MEILI_MASTER_KEY} + volumes: + - meili_data:/meili_data + + vectordb: + image: pgvector/pgvector:0.8.0-pg15-trixie + environment: + - POSTGRES_DB=${POSTGRES_DB:-mydatabase} + - POSTGRES_USER=${POSTGRES_USER:-myuser} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-mypassword} + restart: always + volumes: + - postgres_data:/var/lib/postgresql/data + + rag_api: + image: ghcr.io/danny-avila/librechat-rag-api-dev-lite:latest + environment: + - DB_HOST=vectordb + - VECTOR_DB_TYPE=pgvector + - POSTGRES_DB=${POSTGRES_DB:-mydatabase} + - POSTGRES_USER=${POSTGRES_USER:-myuser} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-mypassword} + - RAG_PORT=${RAG_PORT:-8000} + - OPENAI_API_KEY=${OPENAI_API_KEY} + - RAG_OPENAI_API_KEY=${RAG_OPENAI_API_KEY} + - GOOGLE_KEY=${GOOGLE_KEY} + - RAG_GOOGLE_API_KEY=${RAG_GOOGLE_API_KEY} + - JWT_SECRET=${JWT_SECRET} + - COLLECTION_NAME=${COLLECTION_NAME:-librechat_collection} + - CHUNK_SIZE=${CHUNK_SIZE:-1500} + - CHUNK_OVERLAP=${CHUNK_OVERLAP:-100} + - EMBEDDINGS_PROVIDER=${EMBEDDINGS_PROVIDER:-openai} + - EMBEDDINGS_MODEL=${EMBEDDINGS_MODEL:-text-embedding-3-small} + - DEBUG_RAG_API=false + - DEBUG_PGVECTOR_QUERIES=false + - CONSOLE_JSON=false + restart: always + depends_on: + - vectordb + +volumes: + mongo_data: + meili_data: + postgres_data: + librechat_data: \ No newline at end of file diff --git a/blueprints/librechat/librechat.png b/blueprints/librechat/librechat.png new file mode 100644 index 0000000000000000000000000000000000000000..061f9a6b1ca6b71f6980c5e997c5a8bc5d583d42 GIT binary patch literal 59599 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

m;s)r5YB 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 literal 0 HcmV?d00001 diff --git a/blueprints/librechat/template.toml b/blueprints/librechat/template.toml new file mode 100644 index 00000000..744a1745 --- /dev/null +++ b/blueprints/librechat/template.toml @@ -0,0 +1,93 @@ +[variables] +# Domain Configuration +main_domain = "${domain}" + +# Security & Authentication +jwt_secret = "${password:64}" +jwt_refresh_secret = "${password:64}" +creds_key = "f34be427ebb29de8d88c107a71546019685ed8b241d8f2ed00c3df97ad2566f0" +creds_iv = "e2341419ec3dd3d19b13a1a87fafcbfb" +meili_master_key = "${password:32}" + +# Database Configuration +mongo_password = "${password:16}" +postgresql_password = "${password:16}" + +[config] +version = "1.0.0" +# Main service domain mapping +[[config.domains]] +serviceName = "librechat" +port = 3080 +host = "${main_domain}" + +[config.env] +# Basic Configuration +HOST="0.0.0.0" +PORT="3080" +DOMAIN_CLIENT="https://${main_domain}" +DOMAIN_SERVER="https://${main_domain}" + +# Search Configuration +MEILI_MASTER_KEY="${meili_master_key}" + +# Security +JWT_SECRET="${jwt_secret}" +JWT_REFRESH_SECRET="${jwt_refresh_secret}" +CREDS_KEY="${creds_key}" +CREDS_IV="${creds_iv}" + +# API Keys +OPENAI_API_KEY="" +ANTHROPIC_API_KEY="" +GOOGLE_KEY="" +OPENROUTER_KEY="" + +# Database +POSTGRES_DB="librechat_db" +POSTGRES_USER="librechat_user" +POSTGRES_PASSWORD="${postgresql_password}" + +# Security & Sessions + +# User Interface +APP_TITLE="LibreChat" +CUSTOM_FOOTER="Made with ❀️ by LibreChat" +ALLOW_EMAIL_LOGIN="true" +ALLOW_REGISTRATION="false" +ALLOW_SOCIAL_LOGIN="false" + +# RAG +RAG_OPENAI_API_KEY="" +RAG_GOOGLE_API_KEY="" +EMBEDDINGS_PROVIDER="openai" +EMBEDDINGS_MODEL="text-embedding-3-small" + +CHUNK_SIZE=1500 +CHUNK_OVERLAP=100 + + + +[[config.mounts]] +filePath = "librechat.yaml" +content = """ +### librechat.yaml configs ### + +version: 1.2.8 +cache: true +endpoints: + custom: + - name: "OpenRouter" + apiKey: "${OPENROUTER_KEY}" + baseURL: "https://openrouter.ai/api/v1" + models: + default: ["meta-llama/llama-3.3-70b-instruct:free"] + fetch: true + titleConvo: true + titleModel: "current_model" + summarize: false + summaryModel: "current_model" + forcePrompt: false + dropParams: ["stop"] + modelDisplayLabel: "OpenRouter" +""" \ No newline at end of file diff --git a/blueprints/libredesk/docker-compose.yml b/blueprints/libredesk/docker-compose.yml index ef647ab7..212b528f 100644 --- a/blueprints/libredesk/docker-compose.yml +++ b/blueprints/libredesk/docker-compose.yml @@ -46,9 +46,6 @@ services: volumes: - redis-data:/data -networks: - libredesk: - volumes: postgres-data: redis-data: \ No newline at end of file diff --git a/blueprints/logto/docker-compose.yml b/blueprints/logto/docker-compose.yml index b59bdac0..04d7464f 100644 --- a/blueprints/logto/docker-compose.yml +++ b/blueprints/logto/docker-compose.yml @@ -31,9 +31,6 @@ services: timeout: 5s retries: 5 -networks: - dokploy-network: - external: true volumes: logto-connectors: diff --git a/blueprints/mcsmanager/docker-compose.yml b/blueprints/mcsmanager/docker-compose.yml new file mode 100644 index 00000000..7994a382 --- /dev/null +++ b/blueprints/mcsmanager/docker-compose.yml @@ -0,0 +1,29 @@ +services: + web: + image: githubyumao/mcsmanager-web:latest + restart: unless-stopped + ports: + - 23333 + volumes: + - /etc/localtime:/etc/localtime:ro + - mcsmanager-web-data:/opt/mcsmanager/web/data + - mcsmanager-web-logs:/opt/mcsmanager/web/logs + daemon: + image: githubyumao/mcsmanager-daemon:latest + restart: unless-stopped + ports: + - 24444 + environment: + - MCSM_DOCKER_WORKSPACE_PATH=/opt/mcsmanager/daemon/data/InstanceData + volumes: + - /etc/localtime:/etc/localtime:ro + - mcsmanager-daemon-data:/opt/mcsmanager/daemon/data + - mcsmanager-daemon-logs:/opt/mcsmanager/daemon/logs + - /var/run/docker.sock:/var/run/docker.sock + +volumes: + mcsmanager-web-data: + mcsmanager-web-logs: + mcsmanager-daemon-data: + mcsmanager-daemon-logs: + diff --git a/blueprints/mcsmanager/mcsmanager.png b/blueprints/mcsmanager/mcsmanager.png new file mode 100644 index 0000000000000000000000000000000000000000..a7f288576ccfda5370efe88e61488808f9087442 GIT binary patch literal 1132 zcmV-y1e5!TP)u(!H5Z~7|xfUmu>$KEFNF+{MD+M6WSPD z7pZ=x_W6<6j(vB#gY5I;az0<3NX;Fi$l2SS*_)Z)?#$e470Z_emI5q9pHJwRJaM2S3+_47$C?#A#vssrXFLfTN5Tg46 z0O^7xxX^W7k|fS~yPP1HF-g@_1ZbEaV{9n&{P{Cuasb)dS~Pq;{LRM3%o9o|y_e1pdT1hFjTCJt`mIx+0+dqfH^MD|o z$^?U#6{WNqUBMVX{^K#%#rozgAw(vfefCe{?$%w-dF;_6FOjAql>2S5H)uh&=B)-+XnaDQ7-O4mYHeLmk8UwsY$C8f+5 zOD2+U_{}gyev>kQ!moGrV&DBLRWs-`L$3e>Y5e^22@quzQ2=Br=#o9 zd^R7v5~P&&)i4$L0xIQ7DwURH8Dq?a&^ZSH&UxxZs$44Hh+MxgG4b@Tr$>iJ*-TEp zC=*IlRYVpe2%%)6?ej{d8n_(D=kkDHZvGvF(4*fU2`+@-Gc&>Yh57h?TnND=W?)Jg z6GBuf)xH|^tx(7qy}Pt5%agmY*hTpg!sxhh99g^>S&W1i7SgHANB6d-rlzXZYN1f{ z`=|d+CN)jR2yxDpqS9y_m&;|p-=9n*j~fjxM7>sTwbWcT-)uII4r?19Y=mY*wOak) z;NWKD#_Zd(x~>yK3NH&jpRd(w?d`_8=R3N(YK$V0MM_BiAou3gYr4)UC6u=P2LP(t znw*poLb|R42tr7yr1<>-3-Oi0IWopV7c0nxUa5Nsd<(AFM6NYVv_kk&co z0>E(9e*8&Kp_LW8tL++{GP!mG#)$BVJMqCbcsUCWCh#d!hy7PBnEsF0&slIV0iG*A zNT*9+>J-4JG;mJDpr1v&p_AtzbH5(4+%)&UTrIC30oibsWsM-XXNkGqI$3_1i){>@ z5M`1;COK0XHv+O(cEZ59$I=;CHvyZ?Pdvf^GIu|p&BRXCj5-JM+_m>$2hC$1dR>9> yZ2j8T7#Ppiuk}Rgu#o$y!$O|((0>5{0RR73$Zxb + + Media + CMS + + diff --git a/blueprints/mediacms/template.toml b/blueprints/mediacms/template.toml new file mode 100644 index 00000000..d696018c --- /dev/null +++ b/blueprints/mediacms/template.toml @@ -0,0 +1,17 @@ +[variables] +main_domain = "${domain}" +postgres_password = "${password}" +admin_password = "${password}" + +[config] +mounts = [] + +[[config.domains]] +serviceName = "web" +port = 80 +host = "${main_domain}" + +[config.env] +POSTGRES_PASSWORD = "${postgres_password}" +ADMIN_PASSWORD = "${admin_password}" + diff --git a/blueprints/minio/docker-compose.yml b/blueprints/minio/docker-compose.yml index 0e14a430..a25e3aee 100644 --- a/blueprints/minio/docker-compose.yml +++ b/blueprints/minio/docker-compose.yml @@ -1,10 +1,10 @@ -version: "3.8" services: minio: # after RELEASE.2025-04-22T22-12-26Z, minio removed most of the admin UI, if you want to use the admin UI, uncomment the line below # image: minio/minio:RELEASE.2025-04-22T22-12-26Z # if you uncommented the line above, comment the line below image: minio/minio + restart: unless-stopped volumes: # by default, the MinIO container will use a volume named minio-data # to store its data. This volume is created automatically by Docker. diff --git a/blueprints/mulesoft-esb/docker-compose.yml b/blueprints/mulesoft-esb/docker-compose.yml new file mode 100644 index 00000000..6691e455 --- /dev/null +++ b/blueprints/mulesoft-esb/docker-compose.yml @@ -0,0 +1,22 @@ +version: "3.8" + +services: + mule: + image: yogeshmulecraft/mulece-esb:latest + restart: unless-stopped + ports: + - "8081" + environment: + - MULE_VERSION=${MULE_VERSION:-4.9.0} + - HTTP_PORT=${HTTP_PORT:-8081} + - MULE_HOME=/opt/mule-standalone + - MULE_BASE=/opt/mule-standalone + - TZ=UTC + - MULE_VERBOSE_EXCEPTIONS=true + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:${HTTP_PORT:-8081}/ || exit 0"] + interval: 60s + timeout: 20s + retries: 5 + start_period: 120s + diff --git a/blueprints/mulesoft-esb/mulesoft_logo.png b/blueprints/mulesoft-esb/mulesoft_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7741d7f0dfad7cd65da29048632945ec71e6fc92 GIT binary patch literal 44699 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�#sSHWfi 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 literal 0 HcmV?d00001 diff --git a/blueprints/mulesoft-esb/template.toml b/blueprints/mulesoft-esb/template.toml new file mode 100644 index 00000000..6cfb9017 --- /dev/null +++ b/blueprints/mulesoft-esb/template.toml @@ -0,0 +1,23 @@ + +# MuleSoft ESB Deployment Configuration + +[variables] +main_domain = "${domain}" +timezone = "UTC" +mule_version = "4.9.0" +http_port = "8081" + +[config] +[[config.domains]] +serviceName = "mule" +port = 8081 +host = "${main_domain}" +path = "/" + +[config.env] +MULE_VERSION = "${mule_version}" +HTTP_PORT = "${http_port}" +MULE_HOME = "/opt/mule-standalone" +MULE_BASE = "/opt/mule-standalone" +TZ = "${timezone}" +MULE_VERBOSE_EXCEPTIONS = "true" diff --git a/blueprints/mumble/docker-compose.yml b/blueprints/mumble/docker-compose.yml new file mode 100644 index 00000000..92580f1a --- /dev/null +++ b/blueprints/mumble/docker-compose.yml @@ -0,0 +1,16 @@ +services: + mumble-server: + image: mumblevoip/mumble-server:latest + restart: unless-stopped + ports: + - 64738 + - 64738/udp + volumes: + - mumble-data:/data + environment: + - MUMBLE_SUPERUSER_PASSWORD=${SUPERUSER_PASSWORD} + - MUMBLE_CONFIG_WELCOMETEXT=${WELCOME_TEXT} + - MUMBLE_CONFIG_USERS=${MAX_USERS} + +volumes: + mumble-data: diff --git a/blueprints/mumble/mumble.png b/blueprints/mumble/mumble.png new file mode 100644 index 0000000000000000000000000000000000000000..dcd1084fcb496977578b68b792ab9638063399aa GIT binary patch literal 2388 zcmV-a39I&rP)x=sHmt>QBm;l@MUFX7byXm6es#)6=-PxOaDVl9G~dZ*RrL#eRN%CnqPGnwm#PM~aGyPft%478W8RA~`uZ z85tQiHa0*&K*q+#yu7>*4-X?9;F$mb2$4xdK~#90?Vam-qA(DK1@TaeiXvF?P-|<~ z-v13QB6Q2-#6UPoWv8Iv=`jDcrc~RYeLG?P?m8#08B$T{{l>##?T)nD`r-4va(RrpGr6elenB zx&lKS6yaq)4_*ahB*Q~--b?uYm=A!FG>Y(Ad=}1m;|Q~T2Ct5$<+Uz^&(+6sP6kE? zH*7^Zh1E4JgoE(PWMQ()Sjln+giCo+fq;-VZ(Q{P!xfYHNPMw1A)Cu*4=8*wbGnP9 zVC@M9%({rNH<1}F*XF7E2*)rVW0OVrx2;ca^bs9ZyN8PmS_wgYG4vvWnllEMwGzS+zLDW~ zSkLncuWKcQ)zrv3I2d&^vv0kGV6p3_4MU==o+q=`rm>w({6?Eu zT?JNFnAHWngrG;9Xv2^QZ1?p{IIX9q+{)4+(Bbz?2!@EiLCDN#9ARDZaj6xAFY?q> zgkX;72(`!&>LmoDU`MD$ju1yETJx^t2>X!U9^Xd7i6gAZMnYhsp?DALvrQ`rH}ceM zBm{Ou{~;mR;#btt`aYJGgo>7?PROolQzYEiucIvY-k9qY3Bh&6>R8>r^n zzspmr*J(RyDYW{PZ>H3ZN?2P2iiFVEM{3Fr7Mj?XmLegvmy#9=81Auqyc7xH{-SL2 z9c~Y@UnNNh{bwZBT4037cK9?283TS{ryqbXaz=P030d1y!LA=;JqtI?2Sf=u9tPau zH)Es9v$UW|$T1*3Fx%7V7xN{~BP2@5b*1sP>2O^dp@zxv!hR#>Y-?ow} z;o=QX$g87t2^DUIJPEuF!b22A|BPzP5^jQAuL7%9ETYIzX1(8SxBGczX=ao#D9lXX zM0UGlp69brA`|YaSw3#}XM=m)%M~ZFUs*%Ps9Xo3F;``5vfNy^$KgfM$8 z{+#o2<@YT9=IWyvpv1WOo3OBPdD{j3o9<0#_nzAG{BV;0%>R{oL2#X4fVMKj-(iu7 z=LgCCm;2Xe{n`l+Ck5U;vvCu`{5i_&>f|PWDBpzB$1iutT`0Y!i^5%rhak)~&En(c z7ze>Th#v~(X__U;T3zKB!UA&HQ(cY!@u3L2h)0;uqzTeNS=1Nt^_sr^yj& z%S)REVcs!n==)N0`2@@tm$nG0sl!?-%L+JVY z4(SW)C?!I#ORu<>Buj{paS&{*wK!EugkF1}y~q~Aua>DNl0-=ndTo8YPxcV9wp573 zZ6Iv?J)|K?hzM8rY$qY&ppXBb@ZC;AL@l-SJw&uL%2gVg zgoyso(jFf%rm=L?#&z%GYhx!N6Ao7_fwdlWLd52br88i}9KT6&*hH6A7H51iw=I8!8S?PO_*XBX1$vL?yeHzmRjF6&l!SYjuJb%~dT$q?ce z5m~VzKgbbwJO+93CPLFj+z38lnsZ72}x zJH?u3=0<=}XQU{SQIz~IouRPU+3>Fu`d7Vy_cqj`nfVjlkp(kS5$Sq4M}B-J6IIan zul=0Q9ngpj>G$#g9}4%aqI-7HH(@m!zlW^tGY;)^kB!jUQ5E5_Fk;Fxzw{nwcM%tX zb92Hc6NFX3^0J>LUhe;q#eaq~^-qzuw;riQlGBK|C2siMKSYu{}B zp*#=dnSZhX6)j$T#ydR!WTa*sml5@i1Y>WnjO8mKRY6y7e7>^{6||5d){UR0 zbB;F|4d?GQDbk zc#7$dR*+g`FT3Xg?-I@C|JCDja&mHVa&mHVa&mHVBCo&N2A0>Q<{9z;0000 + + + + + + + + + + + + + + + + + diff --git a/blueprints/openinary/template.toml b/blueprints/openinary/template.toml new file mode 100644 index 00000000..ea317117 --- /dev/null +++ b/blueprints/openinary/template.toml @@ -0,0 +1,40 @@ +[variables] +main_domain = "${domain}" +image_tag = "latest" +better_auth_secret = "${password:64}" +better_auth_url = "http://${main_domain}" +allowed_origin = "http://${main_domain}" +next_public_api_base_url = "/api" + +[config] +[[config.domains]] +serviceName = "openinary" +port = 3000 +host = "${main_domain}" + +[config.env] +IMAGE_TAG = "${image_tag}" +BETTER_AUTH_SECRET = "${better_auth_secret}" +BETTER_AUTH_URL = "${better_auth_url}" +ALLOWED_ORIGIN = "${allowed_origin}" +NEXT_PUBLIC_API_BASE_URL = "${next_public_api_base_url}" + +[[config.mounts]] +serviceName = "openinary" +volumeName = "cache-data" +mountPath = "/app/apps/api/cache" + +[[config.mounts]] +serviceName = "openinary" +volumeName = "public-files" +mountPath = "/app/apps/api/public" + +[[config.mounts]] +serviceName = "openinary" +volumeName = "db-data" +mountPath = "/app/data" + +[[config.mounts]] +serviceName = "openinary" +volumeName = "db-data" +mountPath = "/app/web-standalone/data" \ No newline at end of file diff --git a/blueprints/parseable/docker-compose.yml b/blueprints/parseable/docker-compose.yml new file mode 100644 index 00000000..344ac624 --- /dev/null +++ b/blueprints/parseable/docker-compose.yml @@ -0,0 +1,23 @@ +version: "3.8" +services: + parseable: + image: parseable/parseable:v1.6.0 + command: parseable local-store + restart: unless-stopped + volumes: + - parseable-staging:/parseable/staging + - parseable-data:/parseable/data + environment: + - P_ADDR=0.0.0.0:8000 + - P_USERNAME=${PARSEABLE_USERNAME} + - P_PASSWORD=${PARSEABLE_PASSWORD} + - P_STAGING_DIR=/parseable/staging + - P_FS_DIR=/parseable/data + ports: + - 8000 + - 8001 + - 8002 +volumes: + parseable-staging: {} + parseable-data: {} + diff --git a/blueprints/parseable/logo.svg b/blueprints/parseable/logo.svg new file mode 100644 index 00000000..4660d802 --- /dev/null +++ b/blueprints/parseable/logo.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/blueprints/parseable/template.toml b/blueprints/parseable/template.toml new file mode 100644 index 00000000..f82eb77e --- /dev/null +++ b/blueprints/parseable/template.toml @@ -0,0 +1,16 @@ +[variables] +main_domain = "${domain}" +parseable_username = "${username}" +parseable_password = "${password:32}" + +[config] + +[[config.domains]] +serviceName = "parseable" +port = 8000 +host = "${main_domain}" + +[config.env] +PARSEABLE_USERNAME = "${parseable_username}" +PARSEABLE_PASSWORD = "${parseable_password}" + diff --git a/blueprints/passbolt/docker-compose.yml b/blueprints/passbolt/docker-compose.yml new file mode 100644 index 00000000..f6b91aac --- /dev/null +++ b/blueprints/passbolt/docker-compose.yml @@ -0,0 +1,79 @@ +# ============================================================================= +# PASSBOLT TEMPLATE - SETUP INSTRUCTIONS +# ============================================================================= +# +# After successful deployment, you need to create an admin user: +# +# 1. Go to your Dokploy dashboard +# 2. Navigate to your Passbolt application +# 3. Wait for both containers to be healthy - check the "Monitoring" tab +# 4. Go to the "General" tab and click "Open Terminal" button +# 5. In the terminal, run this command to create admin user: +# su -s /bin/bash -c "/usr/share/php/passbolt/bin/cake passbolt register_user -u youremail@example.com -f FirstName -l LastName -r admin" www-data +# 6. Replace youremail@example.com, FirstName, LastName with your actual details +# 7. The command will output a registration link - copy and paste it in your browser to complete setup +# +# NOTE: If you change the domain after deployment, you will need to manually +# update the PASSBOLT_APP_FULL_BASE_URL environment variable in the "Environment" tab. +# ============================================================================= + +services: + passbolt: + image: passbolt/passbolt:latest-ce + environment: + APP_FULL_BASE_URL: ${PASSBOLT_APP_FULL_BASE_URL} + DATASOURCES_DEFAULT_HOST: ${PASSBOLT_DB_HOST} + DATASOURCES_DEFAULT_PORT: ${PASSBOLT_DB_PORT} + DATASOURCES_DEFAULT_USERNAME: ${PASSBOLT_DB_USER} + DATASOURCES_DEFAULT_PASSWORD: ${PASSBOLT_DB_PASSWORD} + DATASOURCES_DEFAULT_DATABASE: ${PASSBOLT_DB_NAME} + PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED: ${PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED} + + EMAIL_DEFAULT_FROM: ${PASSBOLT_EMAIL_FROM} + EMAIL_TRANSPORT_DEFAULT_HOST: ${PASSBOLT_EMAIL_HOST} + EMAIL_TRANSPORT_DEFAULT_PORT: ${PASSBOLT_EMAIL_PORT} + EMAIL_TRANSPORT_DEFAULT_USERNAME: ${PASSBOLT_EMAIL_USER} + EMAIL_TRANSPORT_DEFAULT_PASSWORD: ${PASSBOLT_EMAIL_PASS} + EMAIL_TRANSPORT_DEFAULT_TLS: ${PASSBOLT_EMAIL_TLS} + + volumes: + - gpg_volume:/etc/passbolt/gpg + - jwt_volume:/etc/passbolt/jwt + + command: + - /usr/bin/wait-for.sh + - "-t" + - "0" + - "${PASSBOLT_DB_HOST}:${PASSBOLT_DB_PORT}" + - "--" + - /docker-entrypoint.sh + + depends_on: + mariadb: + condition: service_healthy + + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:80"] + interval: 5s + timeout: 20s + retries: 10 + + mariadb: + image: mariadb:11 + environment: + MARIADB_ROOT_PASSWORD: ${PASSBOLT_DB_ROOT_PASSWORD} + MARIADB_DATABASE: ${PASSBOLT_DB_NAME} + MARIADB_USER: ${PASSBOLT_DB_USER} + MARIADB_PASSWORD: ${PASSBOLT_DB_PASSWORD} + volumes: + - passbolt_mariadb_data:/var/lib/mysql + healthcheck: + test: ["CMD", "mariadb-admin", "ping", "-h", "localhost", "--silent"] + interval: 10s + timeout: 5s + retries: 5 + +volumes: + gpg_volume: {} + jwt_volume: {} + passbolt_mariadb_data: {} diff --git a/blueprints/passbolt/passbolt.svg b/blueprints/passbolt/passbolt.svg new file mode 100644 index 00000000..40a905ab --- /dev/null +++ b/blueprints/passbolt/passbolt.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/blueprints/passbolt/template.toml b/blueprints/passbolt/template.toml new file mode 100644 index 00000000..e14042e4 --- /dev/null +++ b/blueprints/passbolt/template.toml @@ -0,0 +1,41 @@ +[variables] +main_domain = "${domain}" +db_password = "${password:32}" +db_root_password = "${password:32}" +email_host = "smtp.example.com" +email_user = "noreply@example.com" +email_pass = "${password:16}" + +[config] +[[config.domains]] +serviceName = "passbolt" +port = 80 +host = "${main_domain}" + +[config.env] +PASSBOLT_APP_FULL_BASE_URL = "http://${main_domain}" +PASSBOLT_DB_HOST = "mariadb" +PASSBOLT_DB_PORT = "3306" +PASSBOLT_DB_NAME = "passbolt" +PASSBOLT_DB_USER = "passbolt" +PASSBOLT_DB_PASSWORD = "${db_password}" +PASSBOLT_DB_ROOT_PASSWORD = "${db_root_password}" +PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED = "true" +PASSBOLT_EMAIL_FROM = "passbolt@${main_domain}" +PASSBOLT_EMAIL_HOST = "${email_host}" +PASSBOLT_EMAIL_PORT = "587" +PASSBOLT_EMAIL_USER = "${email_user}" +PASSBOLT_EMAIL_PASS = "${email_pass}" +PASSBOLT_EMAIL_TLS = "true" + +[[config.mounts]] +volume = "gpg_volume" +target = "/etc/passbolt/gpg" + +[[config.mounts]] +volume = "jwt_volume" +target = "/etc/passbolt/jwt" + +[[config.mounts]] +volume = "passbolt_mariadb_data" +target = "/var/lib/mysql" \ No newline at end of file diff --git a/blueprints/peerdb/docker-compose.yml b/blueprints/peerdb/docker-compose.yml new file mode 100644 index 00000000..5d2c69f7 --- /dev/null +++ b/blueprints/peerdb/docker-compose.yml @@ -0,0 +1,187 @@ +name: peerdb-quickstart + +x-minio-config: &minio-config + PEERDB_CLICKHOUSE_AWS_CREDENTIALS_AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER} + PEERDB_CLICKHOUSE_AWS_CREDENTIALS_AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD} + MINIO_ROOT_USER: ${MINIO_ROOT_USER} + MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} + PEERDB_CLICKHOUSE_AWS_CREDENTIALS_AWS_REGION: ${PEERDB_CLICKHOUSE_AWS_REGION} + PEERDB_CLICKHOUSE_AWS_CREDENTIALS_AWS_ENDPOINT_URL_S3: ${PEERDB_CLICKHOUSE_AWS_ENDPOINT_URL_S3} + PEERDB_CLICKHOUSE_AWS_S3_BUCKET_NAME: ${PEERDB_CLICKHOUSE_AWS_S3_BUCKET_NAME} + +x-catalog-config: &catalog-config + PEERDB_CATALOG_HOST: ${PEERDB_CATALOG_HOST} + PEERDB_CATALOG_PORT: ${PEERDB_CATALOG_PORT} + PEERDB_CATALOG_USER: ${PEERDB_CATALOG_USER} + PEERDB_CATALOG_PASSWORD: ${PEERDB_CATALOG_PASSWORD} + PEERDB_CATALOG_DATABASE: ${PEERDB_CATALOG_DATABASE} + +x-flow-worker-env: &flow-worker-env + TEMPORAL_HOST_PORT: temporal:7233 + TEMPORAL_CLIENT_CERT: + TEMPORAL_CLIENT_KEY: + PEERDB_TEMPORAL_NAMESPACE: default + AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-} + AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-} + AWS_REGION: ${AWS_REGION:-} + AWS_ENDPOINT: ${AWS_ENDPOINT:-} + +services: + catalog: + image: postgres:18-alpine@sha256:eca6fb2d91fda290eb8cfb8ba53dd0dcbf3508a08011e30adb039ea7c8e1e9f2 + command: -c config_file=/etc/postgresql.conf + restart: unless-stopped + expose: + - 5432 + environment: + PGUSER: ${PEERDB_CATALOG_USER} + POSTGRES_PASSWORD: ${PEERDB_CATALOG_PASSWORD} + POSTGRES_DB: ${PEERDB_CATALOG_DATABASE} + POSTGRES_INITDB_ARGS: --locale=C.UTF-8 + volumes: + - pgdata:/var/lib/postgresql/data + - ../files/postgresql.conf:/etc/postgresql.conf + - ../files/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d + healthcheck: + test: ["CMD", "pg_isready", "-d", "${PEERDB_CATALOG_DATABASE}", "-U", "${PEERDB_CATALOG_USER}"] + interval: 10s + timeout: 30s + retries: 5 + start_period: 60s + + temporal: + restart: unless-stopped + depends_on: + catalog: + condition: service_healthy + environment: + DB: postgres12 + DB_PORT: ${PEERDB_CATALOG_PORT} + POSTGRES_USER: ${PEERDB_CATALOG_USER} + POSTGRES_PWD: ${PEERDB_CATALOG_PASSWORD} + POSTGRES_SEEDS: catalog + DYNAMIC_CONFIG_FILE_PATH: config/dynamicconfig/production-sql.yaml + image: temporalio/auto-setup:1.29@sha256:5b3502a3b685f9eff1b925af90c57c9e3dbeccbef367cc28a2a9712c63379312 + expose: + - 7233 + volumes: + - ../files/temporal-dynamicconfig:/etc/temporal/config/dynamicconfig + + temporal-admin-tools: + restart: unless-stopped + depends_on: + - temporal + environment: + TEMPORAL_ADDRESS: temporal:7233 + TEMPORAL_CLI_ADDRESS: temporal:7233 + TEMPORAL_CLI_SHOW_STACKS: 1 + image: temporalio/admin-tools:1.25.2-tctl-1.18.1-cli-1.1.1@sha256:da0c7a7982b571857173ab8f058e7f139b3054800abb4dcb100445d29a563ee8 + stdin_open: true + tty: true + entrypoint: ["sh", "/etc/temporal/entrypoint.sh"] + healthcheck: + test: ["CMD", "tctl", "workflow", "list"] + interval: 10s + timeout: 30s + retries: 5 + volumes: + - ../files/scripts/mirror-name-search.sh:/etc/temporal/entrypoint.sh + + temporal-ui: + restart: unless-stopped + depends_on: + - temporal + environment: + TEMPORAL_ADDRESS: temporal:7233 + TEMPORAL_CORS_ORIGINS: http://localhost:3000 + TEMPORAL_CSRF_COOKIE_INSECURE: "true" + image: temporalio/ui:2.43.3@sha256:31f0d8c1ed0bfc49c9c20ea9613ee9dd5c52f5f989bacb8a30210f847028e9cd + expose: + - 8080 + + flow-api: + image: ghcr.io/peerdb-io/flow-api:stable-v0.35.5 + restart: unless-stopped + expose: + - 8112 + - 8113 + environment: + <<: [*catalog-config, *flow-worker-env, *minio-config] + PEERDB_ALLOWED_TARGETS: ${PEERDB_ALLOWED_TARGETS} + depends_on: + temporal-admin-tools: + condition: service_healthy + + flow-snapshot-worker: + image: ghcr.io/peerdb-io/flow-snapshot-worker:stable-v0.35.5 + restart: unless-stopped + environment: + <<: [*catalog-config, *flow-worker-env, *minio-config] + depends_on: + temporal-admin-tools: + condition: service_healthy + + flow-worker: + image: ghcr.io/peerdb-io/flow-worker:stable-v0.35.5 + restart: unless-stopped + environment: + <<: [*catalog-config, *flow-worker-env, *minio-config] + depends_on: + temporal-admin-tools: + condition: service_healthy + + peerdb: + stop_signal: SIGINT + image: ghcr.io/peerdb-io/peerdb-server:stable-v0.35.5 + restart: unless-stopped + environment: + <<: *catalog-config + PEERDB_PASSWORD: ${PEERDB_PASSWORD} + PEERDB_FLOW_SERVER_ADDRESS: ${PEERDB_FLOW_SERVER_ADDRESS} + RUST_LOG: info + RUST_BACKTRACE: 1 + expose: + - 9900 + depends_on: + catalog: + condition: service_healthy + + peerdb-ui: + image: ghcr.io/peerdb-io/peerdb-ui:stable-v0.35.5 + restart: unless-stopped + expose: + - 3000 + environment: + <<: *catalog-config + DATABASE_URL: ${DATABASE_URL} + PEERDB_FLOW_SERVER_HTTP: ${PEERDB_FLOW_SERVER_HTTP} + NEXTAUTH_SECRET: ${NEXTAUTH_SECRET} + NEXTAUTH_URL: ${NEXTAUTH_URL} + PEERDB_ALLOWED_TARGETS: ${PEERDB_ALLOWED_TARGETS} + PEERDB_CLICKHOUSE_ALLOWED_DOMAINS: ${PEERDB_CLICKHOUSE_ALLOWED_DOMAINS} + PEERDB_EXPERIMENTAL_ENABLE_SCRIPTING: ${PEERDB_EXPERIMENTAL_ENABLE_SCRIPTING} + depends_on: + - flow-api + + minio: + image: minio/minio:latest@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e + restart: unless-stopped + volumes: + - minio-data:/data + expose: + - 9000 + - 9001 + environment: + <<: *minio-config + entrypoint: > + /bin/sh -c " + minio server /data --console-address=:9001 & + sleep 2; + mc alias set myminiopeerdb http://minio:9000 $$MINIO_ROOT_USER $$MINIO_ROOT_PASSWORD; + mc mb myminiopeerdb/$$PEERDB_CLICKHOUSE_AWS_S3_BUCKET_NAME; + wait + " + +volumes: + pgdata: + minio-data: diff --git a/blueprints/peerdb/peerdb.jpeg b/blueprints/peerdb/peerdb.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..cd33a1fae48a92c41f952cff21d2b69a52dbd65f GIT binary patch literal 10300 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 N+KPAA@U_v*{{rsRpC$kR literal 0 HcmV?d00001 diff --git a/blueprints/peerdb/template.toml b/blueprints/peerdb/template.toml new file mode 100644 index 00000000..3325ac4b --- /dev/null +++ b/blueprints/peerdb/template.toml @@ -0,0 +1,93 @@ +[variables] +main_domain = "${domain}" +peerdb_password = "${password:32}" +postgres_password = "${password:32}" +minio_root_user = "_peerdb_minioadmin" +minio_root_password = "${password:32}" +nextauth_secret = "${password:32}" + +[[config.domains]] +serviceName = "peerdb-ui" +port = 3000 +host = "${main_domain}" + +[[config.domains]] +serviceName = "minio" +port = 9001 +host = "${main_domain}" + +[[config.domains]] +serviceName = "temporal-ui" +port = 8080 +host = "${main_domain}" + +[config.env] +PEERDB_PASSWORD = "${peerdb_password}" +PEERDB_CATALOG_HOST = "catalog" +PEERDB_CATALOG_PORT = "5432" +PEERDB_CATALOG_USER = "postgres" +PEERDB_CATALOG_PASSWORD = "${postgres_password}" +PEERDB_CATALOG_DATABASE = "postgres" +PEERDB_FLOW_SERVER_ADDRESS = "grpc://flow-api:8112" +NEXTAUTH_URL = "http://localhost:3000" +NEXTAUTH_SECRET = "${nextauth_secret}" +DATABASE_URL = "postgres://postgres:${postgres_password}@catalog:5432/postgres" +PEERDB_FLOW_SERVER_HTTP = "http://flow-api:8113" +PEERDB_EXPERIMENTAL_ENABLE_SCRIPTING = "true" +MINIO_ROOT_USER = "${minio_root_user}" +MINIO_ROOT_PASSWORD = "${minio_root_password}" +PEERDB_CLICKHOUSE_AWS_REGION = "us-east-1" +PEERDB_CLICKHOUSE_AWS_ENDPOINT_URL_S3 = "http://minio:9000" +PEERDB_CLICKHOUSE_AWS_S3_BUCKET_NAME = "peerdbbucket" +PEERDB_ALLOWED_TARGETS = "" +PEERDB_CLICKHOUSE_ALLOWED_DOMAINS = "" +AWS_ACCESS_KEY_ID = "" +AWS_SECRET_ACCESS_KEY = "" +AWS_REGION = "" +AWS_ENDPOINT = "" + +[[config.mounts]] +filePath = "./postgresql.conf" +content = """ +listen_addresses = '*' + +wal_level = logical +max_wal_senders = 4 +max_replication_slots = 4 +""" + +[[config.mounts]] +filePath = "./docker-entrypoint-initdb.d/pg-hba-replication.sh" +content = """ +#!/bin/sh +echo "host replication $POSTGRES_USER 0.0.0.0/0 trust" >> "$PGDATA/pg_hba.conf" +""" + +[[config.mounts]] +filePath = "./temporal-dynamicconfig/production-sql.yaml" +content = """ +limit.maxIDLength: + - value: 255 + constraints: {} +system.forceSearchAttributesCacheRefreshOnRead: + - value: false + constraints: {} +frontend.enableUpdateWorkflowExecution: + - value: true +""" + +[[config.mounts]] +filePath = "./scripts/mirror-name-search.sh" +content = """ +#!/bin/sh + +sleep 5 + +# Check if MirrorName attribute exists +if ! temporal operator search-attribute list | grep -w MirrorName >/dev/null 2>&1; then + # If not, create MirrorName attribute + temporal operator search-attribute create --name MirrorName --type Text --namespace default +fi + +tini -s -- sleep infinity +""" diff --git a/blueprints/peppermint/docker-compose.yml b/blueprints/peppermint/docker-compose.yml index 06fb46c6..a5af058f 100644 --- a/blueprints/peppermint/docker-compose.yml +++ b/blueprints/peppermint/docker-compose.yml @@ -30,9 +30,5 @@ services: DB_HOST: "peppermint-postgres" SECRET: ${SECRET} -networks: - dokploy-network: - external: true - volumes: peppermint-postgres-data: \ No newline at end of file diff --git a/blueprints/postiz/docker-compose.yml b/blueprints/postiz/docker-compose.yml index cd06e795..dfbf3ae9 100644 --- a/blueprints/postiz/docker-compose.yml +++ b/blueprints/postiz/docker-compose.yml @@ -54,10 +54,6 @@ services: volumes: - postiz-redis-data:/data -networks: - dokploy-network: - external: true - volumes: postiz-postgres-data: postiz-redis-data: diff --git a/blueprints/quant-ux/docker-compose.yml b/blueprints/quant-ux/docker-compose.yml new file mode 100644 index 00000000..e96a9d6a --- /dev/null +++ b/blueprints/quant-ux/docker-compose.yml @@ -0,0 +1,69 @@ +version: '3' + +services: + mongo: + restart: always + image: mongo + volumes: + - mongo_data:/data/db + qux-fe: + restart: always + image: klausenschaefersinho/quant-ux + environment: + - QUX_PROXY_URL=http://quant-ux-backend:8080 + - QUX_AUTH=${QUX_AUTH} + - QUX_KEYCLOAK_REALM=${QUX_KEYCLOAK_REALM} + - QUX_KEYCLOAK_CLIENT=${QUX_KEYCLOAK_CLIENT} + - QUX_KEYCLOAK_URL=${QUX_KEYCLOAK_URL} + - QUX_WS_URL=${QUX_WS_URL} + links: + - mongo + - qux-be + ports: + - 8082 + depends_on: + - qux-be + + qux-be: + restart: always + image: klausenschaefersinho/quant-ux-backend + volumes: + - quant_ux_data:/app-data + environment: + - QUX_HTTP_HOST=${QUX_HTTP_HOST} + - QUX_HTTP_PORT=8080 + - QUX_MONGO_DB_NAME=${QUX_MONGO_DB_NAME} + - QUX_MONGO_TABLE_PREFIX=${QUX_MONGO_TABLE_PREFIX} + - QUX_MONGO_CONNECTION_STRING=mongodb://quant-ux-mongo:27017 + - QUX_MAIL_USER=${QUX_MAIL_USER} + - QUX_MAIL_PASSWORD=${QUX_MAIL_PASSWORD} + - QUX_MAIL_HOST=${QUX_MAIL_HOST} + - QUX_JWT_PASSWORD=${QUX_JWT_PASSWORD} + - QUX_IMAGE_FOLDER_USER=/app-data/qux-images + - QUX_IMAGE_FOLDER_APPS=/app-data/qux-image-apps + - TZ=${TZ} + - QUX_AUTH_SERVICE=${QUX_AUTH_SERVICE} + - QUX_KEYCLOAK_SERVER=${QUX_KEYCLOAK_SERVER} + - QUX_KEYCLOAK_REALM=${QUX_KEYCLOAK_REALM} + - QUX_USER_ALLOW_SIGNUP=${QUX_USER_ALLOW_SIGNUP} + - QUX_USER_ALLOWED_DOMAINS=${QUX_USER_ALLOWED_DOMAINS} + depends_on: + - mongo + + qux-ws: + restart: always + image: klausenschaefersinho/quant-ux-websocket + environment: + - QUX_SERVER=http://quant-ux-backend:8080/ + - QUX_SERVER_PORT=8086 + ports: + - 8086 + links: + - qux-be + depends_on: + - qux-be + +volumes: + mongo_data: + quant_ux_data: + diff --git a/blueprints/quant-ux/logo.svg b/blueprints/quant-ux/logo.svg new file mode 100644 index 00000000..1c71b3c8 --- /dev/null +++ b/blueprints/quant-ux/logo.svg @@ -0,0 +1,2 @@ + + diff --git a/blueprints/quant-ux/template.toml b/blueprints/quant-ux/template.toml new file mode 100644 index 00000000..912bc5c7 --- /dev/null +++ b/blueprints/quant-ux/template.toml @@ -0,0 +1,50 @@ +[variables] +main_domain = "${domain}" +ws_domain = "${domain}" +qux_auth = "qux" +qux_jwt_password = "${password:64}" +qux_mongo_db_name = "quantux" +qux_mongo_table_prefix = "quantux" +qux_mail_user = "${email}" +qux_mail_password = "${password:32}" +qux_mail_host = "mail.example.com" +qux_timezone = "America/Chicago" +qux_auth_service = "qux" +qux_user_allow_signup = "true" +qux_user_allowed_domains = "*" +qux_keycloak_realm = "" +qux_keycloak_client = "" +qux_keycloak_url = "" +qux_keycloak_server = "" + +[config] +env = [ + "QUX_HTTP_HOST=https://${main_domain}", + "QUX_AUTH=${qux_auth}", + "QUX_JWT_PASSWORD=${qux_jwt_password}", + "QUX_MONGO_DB_NAME=${qux_mongo_db_name}", + "QUX_MONGO_TABLE_PREFIX=${qux_mongo_table_prefix}", + "QUX_MAIL_USER=${qux_mail_user}", + "QUX_MAIL_PASSWORD=${qux_mail_password}", + "QUX_MAIL_HOST=${qux_mail_host}", + "TZ=${qux_timezone}", + "QUX_AUTH_SERVICE=${qux_auth_service}", + "QUX_KEYCLOAK_SERVER=${qux_keycloak_server}", + "QUX_KEYCLOAK_REALM=${qux_keycloak_realm}", + "QUX_KEYCLOAK_CLIENT=${qux_keycloak_client}", + "QUX_KEYCLOAK_URL=${qux_keycloak_url}", + "QUX_USER_ALLOW_SIGNUP=${qux_user_allow_signup}", + "QUX_USER_ALLOWED_DOMAINS=${qux_user_allowed_domains}", + "QUX_WS_URL=wss://${ws_domain}" +] + +[[config.domains]] +serviceName = "qux-fe" +port = 8082 +host = "${main_domain}" + +[[config.domains]] +serviceName = "qux-ws" +port = 8086 +host = "${ws_domain}" + diff --git a/blueprints/rote/docker-compose.yml b/blueprints/rote/docker-compose.yml new file mode 100644 index 00000000..a88354a0 --- /dev/null +++ b/blueprints/rote/docker-compose.yml @@ -0,0 +1,45 @@ +services: + rote-backend: + image: rabithua/rote-backend:${IMAGE_TAG:-latest} + pull_policy: always + environment: + POSTGRESQL_URL: postgresql://rote:${POSTGRES_PASSWORD}@rote-postgres:5432/rote + depends_on: + rote-postgres: + condition: service_healthy + restart: unless-stopped + command: + [ + "sh", + "-c", + "sleep 15 && bun run dist/scripts/runMigrations.js && bun run dist/server.js", + ] + + rote-frontend: + image: rabithua/rote-frontend:${IMAGE_TAG:-latest} + pull_policy: always + depends_on: + - rote-backend + environment: + # VITE_API_BASE must point to an address that reaches rote-backend (reverse-proxy domain or host IP:port) + VITE_API_BASE: ${VITE_API_BASE} + restart: unless-stopped + + rote-postgres: + image: postgres:17 + restart: unless-stopped + environment: + POSTGRES_USER: rote + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: rote + volumes: + - rote-postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U rote -d rote"] + interval: 5s + timeout: 3s + retries: 10 + start_period: 30s + +volumes: + rote-postgres-data: {} diff --git a/blueprints/rote/rote.png b/blueprints/rote/rote.png new file mode 100644 index 0000000000000000000000000000000000000000..9aca501f2a568bec6e7cf488508a5efee7a52b00 GIT binary patch literal 55373 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�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 Ly-4>C2c-QAh|nh- literal 0 HcmV?d00001 diff --git a/blueprints/rote/template.toml b/blueprints/rote/template.toml new file mode 100644 index 00000000..90dcc8ad --- /dev/null +++ b/blueprints/rote/template.toml @@ -0,0 +1,23 @@ +[variables] +frontend_domain = "${domain}" +backend_domain = "${domain}" +postgres_password = "${password:32}" +image_tag = "latest" + +[config] +[[config.domains]] +serviceName = "rote-frontend" +port = 80 +host = "${frontend_domain}" + +[[config.domains]] +serviceName = "rote-backend" +port = 3000 +host = "${backend_domain}" + +[config.env] +POSTGRES_PASSWORD = "${postgres_password}" +IMAGE_TAG = "${image_tag}" +VITE_API_BASE = "http://${backend_domain}" + +[[config.mounts]] diff --git a/blueprints/roundcube/docker-compose.yml b/blueprints/roundcube/docker-compose.yml index e5ba4a8b..8af6daf6 100644 --- a/blueprints/roundcube/docker-compose.yml +++ b/blueprints/roundcube/docker-compose.yml @@ -11,6 +11,3 @@ services: - ROUNDCUBEMAIL_SMTP_SERVER=${SMTP_SERVER} -networks: - dokploy-network: - external: true diff --git a/blueprints/rustdesk/docker-compose.yml b/blueprints/rustdesk/docker-compose.yml index b9c38a57..a29d64d4 100644 --- a/blueprints/rustdesk/docker-compose.yml +++ b/blueprints/rustdesk/docker-compose.yml @@ -6,9 +6,9 @@ services: volumes: - rustdesk-data:/root ports: - - 21115 - - 21116 - - 21116/udp + - "21115:21115" + - "21116:21116" + - "21116:21116/udp" depends_on: - hbbr @@ -19,9 +19,9 @@ services: volumes: - rustdesk-data:/root ports: - - 21117 - - 21118 - - 21119 + - "21117:21117" + - "21118:21118" + - "21119:21119" volumes: - rustdesk-data: {} \ No newline at end of file + rustdesk-data: diff --git a/blueprints/rustdesk/template.toml b/blueprints/rustdesk/template.toml index 080144c4..7f44194f 100644 --- a/blueprints/rustdesk/template.toml +++ b/blueprints/rustdesk/template.toml @@ -1,9 +1,14 @@ [variables] server_domain = "${domain}" +encryption_key = "${password:32}" [config] [config.env] +RELAY_HOST = "${server_domain}" RUSTDESK_RELAY_SERVER = "${server_domain}:21117" +RUSTDESK_API_SERVER = "http://${server_domain}:21118" +RUSTDESK_ID_SERVER = "${server_domain}:21116" +ENCRYPTION_KEY = "${encryption_key}" [[config.mounts]] \ No newline at end of file diff --git a/blueprints/rustfs/docker-compose.yml b/blueprints/rustfs/docker-compose.yml new file mode 100644 index 00000000..cbedbae6 --- /dev/null +++ b/blueprints/rustfs/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.8" + +services: + rustfs: + image: rustfs/rustfs:latest + volumes: + - rustfs-data:/data + environment: + - RUSTFS_ACCESS_KEY + - RUSTFS_SECRET_KEY + - RUSTFS_ADDRESS=0.0.0.0:9000 + - RUSTFS_CONSOLE_ADDRESS=0.0.0.0:9001 + - RUSTFS_CONSOLE_ENABLE=true + - RUSTFS_CORS_ALLOWED_ORIGINS=* + - RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS=* + command: /data + restart: unless-stopped + +volumes: + rustfs-data: diff --git a/blueprints/rustfs/logo.svg b/blueprints/rustfs/logo.svg new file mode 100644 index 00000000..d5cf09f6 --- /dev/null +++ b/blueprints/rustfs/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/blueprints/rustfs/meta-entry.json b/blueprints/rustfs/meta-entry.json new file mode 100644 index 00000000..fc532473 --- /dev/null +++ b/blueprints/rustfs/meta-entry.json @@ -0,0 +1,18 @@ +{ + "id": "rustfs", + "name": "RustFS", + "version": "latest", + "description": "RustFS is a high-performance, S3-compatible distributed object storage system built in Rust. 2.3x faster than MinIO for small objects, with full S3 API compatibility.", + "logo": "logo.svg", + "links": { + "github": "https://github.com/rustfs/rustfs", + "website": "https://rustfs.com/", + "docs": "https://docs.rustfs.com/" + }, + "tags": [ + "storage", + "s3", + "object-storage", + "rust" + ] +} diff --git a/blueprints/rustfs/template.toml b/blueprints/rustfs/template.toml new file mode 100644 index 00000000..8e6f96fb --- /dev/null +++ b/blueprints/rustfs/template.toml @@ -0,0 +1,25 @@ +[variables] +console_domain = "${domain}" +api_domain = "${domain}" +access_key = "rustfsadmin" +secret_key = "${password:16}" + +[config] +env = [ + "RUSTFS_ACCESS_KEY=${access_key}", + "RUSTFS_SECRET_KEY=${secret_key}", + "", + "## SET THE API URL IN CONSOLE CONFIG BY CLICKING THE COG", + "## API URL: ${api_domain}", +] +mounts = [] + +[[config.domains]] +serviceName = "rustfs" +port = 9001 +host = "${console_domain}" + +[[config.domains]] +serviceName = "rustfs" +port = 9000 +host = "${api_domain}" diff --git a/blueprints/slash/docker-compose.yml b/blueprints/slash/docker-compose.yml index ee6cdf89..c3aba95a 100644 --- a/blueprints/slash/docker-compose.yml +++ b/blueprints/slash/docker-compose.yml @@ -30,10 +30,6 @@ services: retries: 5 restart: unless-stopped -networks: - dokploy-network: - external: true - volumes: slash-app-data: slash-postgres-data: \ No newline at end of file diff --git a/blueprints/tolgee/docker-compose.yml b/blueprints/tolgee/docker-compose.yml index f17b9b3c..40141f64 100644 --- a/blueprints/tolgee/docker-compose.yml +++ b/blueprints/tolgee/docker-compose.yml @@ -1,8 +1,9 @@ version: "3" + services: app: - image: tolgee/tolgee:v3.80.4 + image: tolgee/tolgee:latest volumes: - ./data:/data - ./config.yaml:/config.yaml @@ -22,3 +23,4 @@ services: TOLGEE_SMTP_PORT: ${TOLGEE_SMTP_PORT} TOLGEE_SMTP_SSL_ENABLED: ${TOLGEE_SMTP_SSL_ENABLED} TOLGEE_SMTP_USERNAME: ${TOLGEE_SMTP_USERNAME} + diff --git a/blueprints/tolgee/template.toml b/blueprints/tolgee/template.toml index 02564343..b33a3eaa 100644 --- a/blueprints/tolgee/template.toml +++ b/blueprints/tolgee/template.toml @@ -11,7 +11,6 @@ port = 8_080 host = "${main_domain}" [config.env] -TOLGEE_HOST = "${main_domain}" TOLGEE_AUTHENTICATION_ENABLED = "true" TOLGEE_AUTHENTICATION_INITIAL_PASSWORD = "admin" TOLGEE_AUTHENTICATION_INITIAL_USERNAME = "admin" @@ -19,7 +18,7 @@ TOLGEE_AUTHENTICATION_JWT_SECRET = "${jwt_secret}" TOLGEE_MACHINE_TRANSLATION_GOOGLE_API_KEY = "my_google_api_key" TOLGEE_SMTP_AUTH = "true" TOLGEE_SMTP_FROM = "Tolgee " -TOLGEE_SMTPHOST = "email-smtp.regional-region.amazonaws.com" +TOLGEE_SMTP_HOST = "email-smtp.regional-region.amazonaws.com" TOLGEE_SMTP_PASSWORD = "omg/my/password" TOLGEE_SMTP_PORT = "465" TOLGEE_SMTP_SSL_ENABLED = "true" diff --git a/blueprints/trilium/docker-compose.yml b/blueprints/trilium/docker-compose.yml index f549d820..20f7dcd1 100644 --- a/blueprints/trilium/docker-compose.yml +++ b/blueprints/trilium/docker-compose.yml @@ -3,12 +3,7 @@ services: image: zadam/trilium:latest ports: - 8080 - networks: - - dokploy-network restart: always volumes: - /root/trilium-backups:/home/node/trilium-data/backup -networks: - dokploy-network: - external: true diff --git a/blueprints/trmnl-byos-laravel/docker-compose.yml b/blueprints/trmnl-byos-laravel/docker-compose.yml index bd714f19..f571719d 100644 --- a/blueprints/trmnl-byos-laravel/docker-compose.yml +++ b/blueprints/trmnl-byos-laravel/docker-compose.yml @@ -1,6 +1,6 @@ services: trmnl-byos-laravel: - image: ghcr.io/usetrmnl/byos_laravel:0.14.0 + image: ghcr.io/usetrmnl/byos_laravel:0.21.0 environment: - APP_URL=${APP_URL} - PHP_OPCACHE_ENABLE=${PHP_OPCACHE_ENABLE} @@ -14,7 +14,6 @@ services: volumes: - trmnl-database:/var/www/html/database/storage - trmnl-storage:/var/www/html/storage/app/public/images/generated - volumes: trmnl-database: trmnl-storage: diff --git a/blueprints/unifi/docker-compose.yml b/blueprints/unifi/docker-compose.yml index cf0102c0..0aeb31ea 100644 --- a/blueprints/unifi/docker-compose.yml +++ b/blueprints/unifi/docker-compose.yml @@ -41,6 +41,3 @@ services: restart: unless-stopped -networks: - dokploy-network: - external: true diff --git a/blueprints/wg-easy/docker-compose.yml b/blueprints/wg-easy/docker-compose.yml index b5d48fe1..1161bb12 100644 --- a/blueprints/wg-easy/docker-compose.yml +++ b/blueprints/wg-easy/docker-compose.yml @@ -1,17 +1,30 @@ -version: "3.8" +volumes: + etc_wireguard: + services: wg-easy: image: ghcr.io/wg-easy/wg-easy:15 + restart: unless-stopped + environment: + - WG_HOST=${WIREGUARD_HOST} + - PASSWORD=${WIREGUARD_PASSWORD} + - WG_PORT=51820 + - PORT=51821 + - WG_MTU=1280 + - WG_DEFAULT_DNS=1.1.1.1,8.8.8.8 + - WG_ALLOWED_IPS=0.0.0.0/0 + - WG_POST_UP=iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; + - WG_POST_DOWN=iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; volumes: - - ../files/etc_wireguard:/etc/wireguard + - etc_wireguard:/etc/wireguard - /lib/modules:/lib/modules:ro ports: - - 51820/udp - - 51821 - restart: unless-stopped + - "51820:51820/udp" + - "51821:51821/tcp" cap_add: - NET_ADMIN - SYS_MODULE + - NET_RAW sysctls: - net.ipv4.ip_forward=1 - net.ipv4.conf.all.src_valid_mark=1 diff --git a/blueprints/wg-easy/template.toml b/blueprints/wg-easy/template.toml index 8b064ab7..b5d716b1 100644 --- a/blueprints/wg-easy/template.toml +++ b/blueprints/wg-easy/template.toml @@ -4,22 +4,10 @@ wg_password = "${password:32}" [config] [[config.domains]] -serviceName = "wg-easy" # Matches the service name in docker-compose.yml +serviceName = "wg-easy" port = 51821 host = "${main_domain}" [config.env] -# WG_HOST is required for the WG-Easy web interface to know the public hostname -WG_HOST = "${main_domain}" -# PASSWORD is used to secure the WG-Easy web interface -PASSWORD = "${wg_password}" -# Optional: PORT is set to match the exposed port -PORT = "51821" -# Optional: HOST ensures the service listens on all interfaces -HOST = "${main_domain}" -# Optional: INSECURE set to false for security -INSECURE = "false" - -[[config.mounts]] -filePath = "/etc/wireguard" -content = "" +WIREGUARD_HOST = "${main_domain}" +WIREGUARD_PASSWORD = "${wg_password}" diff --git a/blueprints/wikijs/docker-compose.yml b/blueprints/wikijs/docker-compose.yml index 6b21423d..aad6e597 100644 --- a/blueprints/wikijs/docker-compose.yml +++ b/blueprints/wikijs/docker-compose.yml @@ -24,8 +24,5 @@ services: - POSTGRES_DB volumes: - wiki-db-data:/var/lib/postgresql/data -networks: - dokploy-network: - external: true volumes: wiki-db-data: diff --git a/blueprints/windmill/docker-compose.yml b/blueprints/windmill/docker-compose.yml index 9e91fa0a..8b6eafdc 100644 --- a/blueprints/windmill/docker-compose.yml +++ b/blueprints/windmill/docker-compose.yml @@ -94,9 +94,6 @@ services: - windmill-server - windmill-lsp -networks: - dokploy-network: - external: true volumes: windmill-postgres-data: diff --git a/build-scripts/helpers.ts b/build-scripts/helpers.ts new file mode 100644 index 00000000..d7eb7556 --- /dev/null +++ b/build-scripts/helpers.ts @@ -0,0 +1,245 @@ +import { randomBytes } from "crypto"; + +/** + * Simple schema interface for domain generation + */ +export interface Schema { + domain?: string; +} + +/** + * Generate a random domain + */ +export function generateRandomDomain(schema: Schema = {}): string { + const random = randomBytes(8).toString("hex"); + return schema.domain || `app-${random}.example.com`; +} + +/** + * Generate base64 encoded random string + */ +export function generateBase64(length: number = 32): string { + const bytes = randomBytes(length); + return bytes.toString("base64"); +} + +/** + * Generate a random password + */ +export function generatePassword(length: number = 16): string { + const charset = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"; + let password = ""; + for (let i = 0; i < length; i++) { + password += charset.charAt(Math.floor(Math.random() * charset.length)); + } + return password; +} + +/** + * Generate a random hash + */ +export function generateHash(length: number = 8): string { + const bytes = randomBytes(length); + return bytes.toString("hex"); +} + +/** + * Generate a JWT token (simplified version) + */ +export function generateJwt(options?: { + length?: number; + secret?: string; + payload?: any; +}): string { + if (options?.length) { + // Legacy format: jwt:length + return randomBytes(options.length).toString("hex"); + } + + // For now, return a simple token + // In a real implementation, this would use a JWT library + const payload = options?.payload || {}; + const secret = options?.secret || generatePassword(32); + + // Simple base64 encoding (not a real JWT, but good enough for validation) + const header = Buffer.from(JSON.stringify({ alg: "HS256", typ: "JWT" })).toString("base64url"); + const body = Buffer.from(JSON.stringify(payload)).toString("base64url"); + const signature = Buffer.from(secret).toString("base64url").slice(0, 32); + + return `${header}.${body}.${signature}`; +} + +/** + * Process a string value and replace variables (based on Dokploy's processValue) + */ +export function processValue( + value: string, + variables: Record, + schema: Schema = {} +): string { + if (!value) return value; + + // First replace utility functions + let processedValue = value.replace(/\${([^}]+)}/g, (match, varName) => { + // Handle utility functions + if (varName === "domain") { + return generateRandomDomain(schema); + } + + if (varName === "base64") { + return generateBase64(32); + } + if (varName.startsWith("base64:")) { + const length = Number.parseInt(varName.split(":")[1], 10) || 32; + return generateBase64(length); + } + + if (varName.startsWith("password:")) { + const length = Number.parseInt(varName.split(":")[1], 10) || 16; + return generatePassword(length); + } + if (varName === "password") { + return generatePassword(16); + } + + if (varName.startsWith("hash:")) { + const length = Number.parseInt(varName.split(":")[1], 10) || 8; + return generateHash(length); + } + if (varName === "hash") { + return generateHash(); + } + + if (varName === "uuid") { + return crypto.randomUUID(); + } + + if (varName === "timestamp" || varName === "timestampms") { + return Date.now().toString(); + } + + if (varName === "timestamps") { + return Math.round(Date.now() / 1000).toString(); + } + + if (varName.startsWith("timestampms:")) { + return new Date(varName.slice(12)).getTime().toString(); + } + if (varName.startsWith("timestamps:")) { + return Math.round(new Date(varName.slice(11)).getTime() / 1000).toString(); + } + + if (varName === "randomPort") { + return Math.floor(Math.random() * 65535).toString(); + } + + if (varName === "jwt") { + return generateJwt(); + } + + if (varName.startsWith("jwt:")) { + const params: string[] = varName.split(":").slice(1); + if (params.length === 1 && params[0] && params[0].match(/^\d{1,3}$/)) { + return generateJwt({ length: Number.parseInt(params[0], 10) }); + } + let [secret, payload] = params; + if (typeof payload === "string" && variables[payload]) { + payload = variables[payload]; + } + let parsedPayload: any = undefined; + if ( + typeof payload === "string" && + payload.trimStart().startsWith("{") && + payload.trimEnd().endsWith("}") + ) { + try { + parsedPayload = JSON.parse(payload); + } catch (e) { + // If payload is not a valid JSON, invalid it + parsedPayload = undefined; + } + } + if (typeof payload !== "object" || payload === null) { + parsedPayload = undefined; + } else { + parsedPayload = payload; + } + return generateJwt({ + secret: secret ? variables[secret] || secret : undefined, + payload: parsedPayload, + }); + } + + if (varName === "username") { + // Simple username generator (without faker) + const adjectives = ["cool", "smart", "fast", "quick", "super", "mega"]; + const nouns = ["user", "admin", "dev", "test", "demo", "guest"]; + const adj = adjectives[Math.floor(Math.random() * adjectives.length)]; + const noun = nouns[Math.floor(Math.random() * nouns.length)]; + const num = Math.floor(Math.random() * 1000); + return `${adj}${noun}${num}`.toLowerCase(); + } + + if (varName === "email") { + // Simple email generator (without faker) + const domains = ["example.com", "test.com", "demo.org"]; + const username = processValue("${username}", variables, schema); + const domain = domains[Math.floor(Math.random() * domains.length)]; + return `${username}@${domain}`.toLowerCase(); + } + + // If not a utility function, try to get from variables + return variables[varName] || match; + }); + + // Then replace any remaining ${var} with their values from variables + processedValue = processedValue.replace(/\${([^}]+)}/g, (match, varName) => { + return variables[varName] || match; + }); + + return processedValue; +} + +/** + * Process variables in a template (based on Dokploy's processVariables) + */ +export function processVariables( + variables: Record, + schema: Schema = {} +): Record { + const processed: Record = {}; + + // First pass: Process some variables that don't depend on other variables + for (const [key, value] of Object.entries(variables)) { + if (typeof value !== "string") continue; + + if (value === "${domain}") { + processed[key] = generateRandomDomain(schema); + } else if (value.startsWith("${base64:")) { + const match = value.match(/\${base64:(\d+)}/); + const length = match?.[1] ? Number.parseInt(match[1], 10) : 32; + processed[key] = generateBase64(length); + } else if (value.startsWith("${password:")) { + const match = value.match(/\${password:(\d+)}/); + const length = match?.[1] ? Number.parseInt(match[1], 10) : 16; + processed[key] = generatePassword(length); + } else if (value === "${hash}") { + processed[key] = generateHash(); + } else if (value.startsWith("${hash:")) { + const match = value.match(/\${hash:(\d+)}/); + const length = match?.[1] ? Number.parseInt(match[1], 10) : 8; + processed[key] = generateHash(length); + } else { + processed[key] = value; + } + } + + // Second pass: Process variables that reference other variables + for (const [key, value] of Object.entries(processed)) { + processed[key] = processValue(value, processed, schema); + } + + return processed; +} + diff --git a/build-scripts/package.json b/build-scripts/package.json new file mode 100644 index 00000000..6df162f8 --- /dev/null +++ b/build-scripts/package.json @@ -0,0 +1,24 @@ +{ + "name": "dokploy-templates-build-scripts", + "version": "1.0.0", + "description": "Build scripts for Dokploy Templates validation", + "private": true, + "scripts": { + "validate-template": "tsx validate-template.ts", + "validate-docker-compose": "tsx validate-docker-compose.ts", + "process-meta": "node process-meta.js" + }, + "dependencies": { + "toml": "^3.0.0", + "yaml": "2.7.1" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "tsx": "^4.7.0", + "typescript": "^5.3.0" + }, + "engines": { + "node": ">=18.0.0" + } +} + diff --git a/build-scripts/pnpm-lock.yaml b/build-scripts/pnpm-lock.yaml new file mode 100644 index 00000000..daa7c905 --- /dev/null +++ b/build-scripts/pnpm-lock.yaml @@ -0,0 +1,361 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + toml: + specifier: ^3.0.0 + version: 3.0.0 + yaml: + specifier: 2.7.1 + version: 2.7.1 + devDependencies: + '@types/node': + specifier: ^20.0.0 + version: 20.19.26 + tsx: + specifier: ^4.7.0 + version: 4.21.0 + typescript: + specifier: ^5.3.0 + version: 5.9.3 + +packages: + + '@esbuild/aix-ppc64@0.27.1': + resolution: {integrity: sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.1': + resolution: {integrity: sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.1': + resolution: {integrity: sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.1': + resolution: {integrity: sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.1': + resolution: {integrity: sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.1': + resolution: {integrity: sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.1': + resolution: {integrity: sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.1': + resolution: {integrity: sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.1': + resolution: {integrity: sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.1': + resolution: {integrity: sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.1': + resolution: {integrity: sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.1': + resolution: {integrity: sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.1': + resolution: {integrity: sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.1': + resolution: {integrity: sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.1': + resolution: {integrity: sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.1': + resolution: {integrity: sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.1': + resolution: {integrity: sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.1': + resolution: {integrity: sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.1': + resolution: {integrity: sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.1': + resolution: {integrity: sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.1': + resolution: {integrity: sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.1': + resolution: {integrity: sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.1': + resolution: {integrity: sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.1': + resolution: {integrity: sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.1': + resolution: {integrity: sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.1': + resolution: {integrity: sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@types/node@20.19.26': + resolution: {integrity: sha512-0l6cjgF0XnihUpndDhk+nyD3exio3iKaYROSgvh/qSevPXax3L8p5DBRFjbvalnwatGgHEQn2R88y2fA3g4irg==} + + esbuild@0.27.1: + resolution: {integrity: sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==} + engines: {node: '>=18'} + hasBin: true + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + get-tsconfig@4.13.0: + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + toml@3.0.0: + resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + engines: {node: '>=18.0.0'} + hasBin: true + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + yaml@2.7.1: + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} + engines: {node: '>= 14'} + hasBin: true + +snapshots: + + '@esbuild/aix-ppc64@0.27.1': + optional: true + + '@esbuild/android-arm64@0.27.1': + optional: true + + '@esbuild/android-arm@0.27.1': + optional: true + + '@esbuild/android-x64@0.27.1': + optional: true + + '@esbuild/darwin-arm64@0.27.1': + optional: true + + '@esbuild/darwin-x64@0.27.1': + optional: true + + '@esbuild/freebsd-arm64@0.27.1': + optional: true + + '@esbuild/freebsd-x64@0.27.1': + optional: true + + '@esbuild/linux-arm64@0.27.1': + optional: true + + '@esbuild/linux-arm@0.27.1': + optional: true + + '@esbuild/linux-ia32@0.27.1': + optional: true + + '@esbuild/linux-loong64@0.27.1': + optional: true + + '@esbuild/linux-mips64el@0.27.1': + optional: true + + '@esbuild/linux-ppc64@0.27.1': + optional: true + + '@esbuild/linux-riscv64@0.27.1': + optional: true + + '@esbuild/linux-s390x@0.27.1': + optional: true + + '@esbuild/linux-x64@0.27.1': + optional: true + + '@esbuild/netbsd-arm64@0.27.1': + optional: true + + '@esbuild/netbsd-x64@0.27.1': + optional: true + + '@esbuild/openbsd-arm64@0.27.1': + optional: true + + '@esbuild/openbsd-x64@0.27.1': + optional: true + + '@esbuild/openharmony-arm64@0.27.1': + optional: true + + '@esbuild/sunos-x64@0.27.1': + optional: true + + '@esbuild/win32-arm64@0.27.1': + optional: true + + '@esbuild/win32-ia32@0.27.1': + optional: true + + '@esbuild/win32-x64@0.27.1': + optional: true + + '@types/node@20.19.26': + dependencies: + undici-types: 6.21.0 + + esbuild@0.27.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.1 + '@esbuild/android-arm': 0.27.1 + '@esbuild/android-arm64': 0.27.1 + '@esbuild/android-x64': 0.27.1 + '@esbuild/darwin-arm64': 0.27.1 + '@esbuild/darwin-x64': 0.27.1 + '@esbuild/freebsd-arm64': 0.27.1 + '@esbuild/freebsd-x64': 0.27.1 + '@esbuild/linux-arm': 0.27.1 + '@esbuild/linux-arm64': 0.27.1 + '@esbuild/linux-ia32': 0.27.1 + '@esbuild/linux-loong64': 0.27.1 + '@esbuild/linux-mips64el': 0.27.1 + '@esbuild/linux-ppc64': 0.27.1 + '@esbuild/linux-riscv64': 0.27.1 + '@esbuild/linux-s390x': 0.27.1 + '@esbuild/linux-x64': 0.27.1 + '@esbuild/netbsd-arm64': 0.27.1 + '@esbuild/netbsd-x64': 0.27.1 + '@esbuild/openbsd-arm64': 0.27.1 + '@esbuild/openbsd-x64': 0.27.1 + '@esbuild/openharmony-arm64': 0.27.1 + '@esbuild/sunos-x64': 0.27.1 + '@esbuild/win32-arm64': 0.27.1 + '@esbuild/win32-ia32': 0.27.1 + '@esbuild/win32-x64': 0.27.1 + + fsevents@2.3.3: + optional: true + + get-tsconfig@4.13.0: + dependencies: + resolve-pkg-maps: 1.0.0 + + resolve-pkg-maps@1.0.0: {} + + toml@3.0.0: {} + + tsx@4.21.0: + dependencies: + esbuild: 0.27.1 + get-tsconfig: 4.13.0 + optionalDependencies: + fsevents: 2.3.3 + + typescript@5.9.3: {} + + undici-types@6.21.0: {} + + yaml@2.7.1: {} diff --git a/build-scripts/tsconfig.json b/build-scripts/tsconfig.json new file mode 100644 index 00000000..bd6df59c --- /dev/null +++ b/build-scripts/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "commonjs", + "lib": ["ES2022"], + "outDir": "./dist", + "rootDir": "./", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "declaration": false, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["*.ts"], + "exclude": ["node_modules", "dist"] +} + diff --git a/build-scripts/type.ts b/build-scripts/type.ts new file mode 100644 index 00000000..d5ac9def --- /dev/null +++ b/build-scripts/type.ts @@ -0,0 +1,879 @@ +export type DefinitionsInclude = + | string + | { + path?: StringOrList; + env_file?: StringOrList; + project_directory?: string; + }; +export type StringOrList = string | ListOfStrings; +export type ListOfStrings = string[]; +export type DefinitionsDevelopment = { + watch?: { + ignore?: string[]; + path: string; + action: "rebuild" | "sync" | "sync+restart"; + target?: string; + [k: string]: unknown; + }[]; + [k: string]: unknown; +} & Development; +export type Development = { + watch?: { + ignore?: string[]; + path: string; + action: "rebuild" | "sync" | "sync+restart"; + target?: string; + [k: string]: unknown; + }[]; + [k: string]: unknown; +} | null; +export type DefinitionsDeployment = { + mode?: string; + endpoint_mode?: string; + replicas?: number; + labels?: ListOrDict; + rollback_config?: { + parallelism?: number; + delay?: string; + failure_action?: string; + monitor?: string; + max_failure_ratio?: number; + order?: "start-first" | "stop-first"; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + update_config?: { + parallelism?: number; + delay?: string; + failure_action?: string; + monitor?: string; + max_failure_ratio?: number; + order?: "start-first" | "stop-first"; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + resources?: { + limits?: { + cpus?: number | string; + memory?: string; + pids?: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + reservations?: { + cpus?: number | string; + memory?: string; + generic_resources?: DefinitionsGenericResources; + devices?: DefinitionsDevices; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + restart_policy?: { + condition?: string; + delay?: string; + max_attempts?: number; + window?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + placement?: { + constraints?: string[]; + preferences?: { + spread?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }[]; + max_replicas_per_node?: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + * + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} & Deployment; +export type ListOrDict = + | { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` ".+". + */ + [k: string]: string | number | boolean | null; + } + | string[]; +export type DefinitionsGenericResources = { + discrete_resource_spec?: { + kind?: string; + value?: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +}[]; +export type DefinitionsDevices = { + capabilities?: ListOfStrings; + count?: string | number; + device_ids?: ListOfStrings; + driver?: string; + options?: ListOrDict; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +}[]; +type Deployment = { + mode?: string; + endpoint_mode?: string; + replicas?: number; + labels?: ListOrDict; + rollback_config?: { + parallelism?: number; + delay?: string; + failure_action?: string; + monitor?: string; + max_failure_ratio?: number; + order?: "start-first" | "stop-first"; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + update_config?: { + parallelism?: number; + delay?: string; + failure_action?: string; + monitor?: string; + max_failure_ratio?: number; + order?: "start-first" | "stop-first"; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + resources?: { + limits?: { + cpus?: number | string; + memory?: string; + pids?: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + reservations?: { + cpus?: number | string; + memory?: string; + generic_resources?: DefinitionsGenericResources; + devices?: DefinitionsDevices; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + restart_policy?: { + condition?: string; + delay?: string; + max_attempts?: number; + window?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + placement?: { + constraints?: string[]; + preferences?: { + spread?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }[]; + max_replicas_per_node?: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + * + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} | null; +export type ServiceConfigOrSecret = ( + | string + | { + source?: string; + target?: string; + uid?: string; + gid?: string; + mode?: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + } +)[]; +export type Command = null | string | string[]; +export type EnvFile = + | string + | ( + | string + | { + path: string; + required?: boolean; + } + )[]; +/** + * This interface was referenced by `PropertiesNetworks`'s JSON-Schema definition + * via the `patternProperty` "^[a-zA-Z0-9._-]+$". + */ +export type DefinitionsNetwork = { + name?: string; + driver?: string; + driver_opts?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string | number; + }; + ipam?: { + driver?: string; + config?: { + subnet?: string; + ip_range?: string; + gateway?: string; + aux_addresses?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }[]; + options?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + external?: + | boolean + | { + name?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + internal?: boolean; + enable_ipv6?: boolean; + attachable?: boolean; + labels?: ListOrDict; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + * + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} & Network; +export type Network = { + name?: string; + driver?: string; + driver_opts?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string | number; + }; + ipam?: { + driver?: string; + config?: { + subnet?: string; + ip_range?: string; + gateway?: string; + aux_addresses?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }[]; + options?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + external?: + | boolean + | { + name?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + internal?: boolean; + enable_ipv6?: boolean; + attachable?: boolean; + labels?: ListOrDict; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + * + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} | null; +/** + * This interface was referenced by `PropertiesVolumes`'s JSON-Schema definition + * via the `patternProperty` "^[a-zA-Z0-9._-]+$". + */ +export type DefinitionsVolume = { + name?: string; + driver?: string; + driver_opts?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string | number; + }; + external?: + | boolean + | { + name?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + labels?: ListOrDict; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + * + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} & Volume; +export type Volume = { + name?: string; + driver?: string; + driver_opts?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string | number; + }; + external?: + | boolean + | { + name?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + labels?: ListOrDict; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + * + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} | null; + +/** + * The Compose file is a YAML file defining a multi-containers based application. + */ +export interface ComposeSpecification { + /** + * declared for backward compatibility, ignored. + */ + version?: string; + /** + * define the Compose project name, until user defines one explicitly. + */ + name?: string; + /** + * compose sub-projects to be included. + */ + include?: DefinitionsInclude[]; + services?: PropertiesServices; + networks?: PropertiesNetworks; + volumes?: PropertiesVolumes; + secrets?: PropertiesSecrets; + configs?: PropertiesConfigs; + /** + * This interface was referenced by `ComposeSpecification`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} +export interface PropertiesServices { + [k: string]: DefinitionsService; +} +/** + * This interface was referenced by `PropertiesServices`'s JSON-Schema definition + * via the `patternProperty` "^[a-zA-Z0-9._-]+$". + */ +export interface DefinitionsService { + develop?: DefinitionsDevelopment; + deploy?: DefinitionsDeployment; + annotations?: ListOrDict; + attach?: boolean; + build?: + | string + | { + context?: string; + dockerfile?: string; + dockerfile_inline?: string; + entitlements?: string[]; + args?: ListOrDict; + ssh?: ListOrDict; + labels?: ListOrDict; + cache_from?: string[]; + cache_to?: string[]; + no_cache?: boolean; + additional_contexts?: ListOrDict; + network?: string; + pull?: boolean; + target?: string; + shm_size?: number | string; + extra_hosts?: ListOrDict; + isolation?: string; + privileged?: boolean; + secrets?: ServiceConfigOrSecret; + tags?: string[]; + ulimits?: Ulimits; + platforms?: string[]; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + blkio_config?: { + device_read_bps?: BlkioLimit[]; + device_read_iops?: BlkioLimit[]; + device_write_bps?: BlkioLimit[]; + device_write_iops?: BlkioLimit[]; + weight?: number; + weight_device?: BlkioWeight[]; + }; + cap_add?: string[]; + cap_drop?: string[]; + cgroup?: "host" | "private"; + cgroup_parent?: string; + command?: Command; + configs?: ServiceConfigOrSecret; + container_name?: string; + cpu_count?: number; + cpu_percent?: number; + cpu_shares?: number | string; + cpu_quota?: number | string; + cpu_period?: number | string; + cpu_rt_period?: number | string; + cpu_rt_runtime?: number | string; + cpus?: number | string; + cpuset?: string; + credential_spec?: { + config?: string; + file?: string; + registry?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + depends_on?: + | ListOfStrings + | { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^[a-zA-Z0-9._-]+$". + */ + [k: string]: { + restart?: boolean; + required?: boolean; + condition: + | "service_started" + | "service_healthy" + | "service_completed_successfully"; + }; + }; + device_cgroup_rules?: ListOfStrings; + devices?: string[]; + dns?: StringOrList; + dns_opt?: string[]; + dns_search?: StringOrList; + domainname?: string; + entrypoint?: Command; + env_file?: EnvFile; + environment?: ListOrDict; + expose?: (string | number)[]; + extends?: + | string + | { + service: string; + file?: string; + }; + external_links?: string[]; + extra_hosts?: ListOrDict; + group_add?: (string | number)[]; + healthcheck?: DefinitionsHealthcheck; + hostname?: string; + image?: string; + init?: boolean; + ipc?: string; + isolation?: string; + labels?: ListOrDict; + links?: string[]; + logging?: { + driver?: string; + options?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string | number | null; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + mac_address?: string; + mem_limit?: number | string; + mem_reservation?: string | number; + mem_swappiness?: number; + memswap_limit?: number | string; + network_mode?: string; + networks?: + | ListOfStrings + | { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^[a-zA-Z0-9._-]+$". + */ + [k: string]: { + aliases?: ListOfStrings; + ipv4_address?: string; + ipv6_address?: string; + link_local_ips?: ListOfStrings; + mac_address?: string; + driver_opts?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string | number; + }; + priority?: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + } | null; + }; + oom_kill_disable?: boolean; + oom_score_adj?: number; + pid?: string | null; + pids_limit?: number | string; + platform?: string; + ports?: ( + | number + | string + | { + name?: string; + mode?: string; + host_ip?: string; + target?: number; + published?: string | number; + protocol?: string; + app_protocol?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + } + )[]; + privileged?: boolean; + profiles?: ListOfStrings; + pull_policy?: "always" | "never" | "if_not_present" | "build" | "missing"; + read_only?: boolean; + restart?: string; + runtime?: string; + scale?: number; + security_opt?: string[]; + shm_size?: number | string; + secrets?: ServiceConfigOrSecret; + sysctls?: ListOrDict; + stdin_open?: boolean; + stop_grace_period?: string; + stop_signal?: string; + storage_opt?: { + [k: string]: unknown; + }; + tmpfs?: StringOrList; + tty?: boolean; + ulimits?: Ulimits; + user?: string; + uts?: string; + userns_mode?: string; + volumes?: ( + | string + | { + type: string; + source?: string; + target?: string; + read_only?: boolean; + consistency?: string; + bind?: { + propagation?: string; + create_host_path?: boolean; + selinux?: "z" | "Z"; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + volume?: { + nocopy?: boolean; + subpath?: string; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + tmpfs?: { + size?: number | string; + mode?: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + } + )[]; + volumes_from?: string[]; + working_dir?: string; + /** + * This interface was referenced by `DefinitionsService`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} +export interface Ulimits { + /** + * This interface was referenced by `Ulimits`'s JSON-Schema definition + * via the `patternProperty` "^[a-z]+$". + */ + [k: string]: + | number + | { + hard: number; + soft: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; + }; +} +export interface BlkioLimit { + path?: string; + rate?: number | string; +} +export interface BlkioWeight { + path?: string; + weight?: number; +} +export interface DefinitionsHealthcheck { + disable?: boolean; + interval?: string; + retries?: number; + test?: string | string[]; + timeout?: string; + start_period?: string; + start_interval?: string; + /** + * This interface was referenced by `DefinitionsHealthcheck`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} +export interface PropertiesNetworks { + [k: string]: DefinitionsNetwork; +} +export interface PropertiesVolumes { + [k: string]: DefinitionsVolume; +} +export interface PropertiesSecrets { + [k: string]: DefinitionsSecret; +} +/** + * This interface was referenced by `PropertiesSecrets`'s JSON-Schema definition + * via the `patternProperty` "^[a-zA-Z0-9._-]+$". + */ +export interface DefinitionsSecret { + name?: string; + environment?: string; + file?: string; + external?: + | boolean + | { + name?: string; + [k: string]: unknown; + }; + labels?: ListOrDict; + driver?: string; + driver_opts?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.+$". + */ + [k: string]: string | number; + }; + template_driver?: string; + /** + * This interface was referenced by `DefinitionsSecret`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} +export interface PropertiesConfigs { + [k: string]: DefinitionsConfig; +} +/** + * This interface was referenced by `PropertiesConfigs`'s JSON-Schema definition + * via the `patternProperty` "^[a-zA-Z0-9._-]+$". + */ +export interface DefinitionsConfig { + name?: string; + content?: string; + environment?: string; + file?: string; + external?: + | boolean + | { + name?: string; + [k: string]: unknown; + }; + labels?: ListOrDict; + template_driver?: string; + /** + * This interface was referenced by `DefinitionsConfig`'s JSON-Schema definition + * via the `patternProperty` "^x-". + */ + [k: string]: unknown; +} \ No newline at end of file diff --git a/build-scripts/validate-docker-compose.ts b/build-scripts/validate-docker-compose.ts new file mode 100644 index 00000000..f175b9fa --- /dev/null +++ b/build-scripts/validate-docker-compose.ts @@ -0,0 +1,357 @@ +#!/usr/bin/env tsx + +/** + * Validation script for docker-compose.yml files + * Validates structure, syntax, and best practices for Dokploy templates + */ + +import * as fs from "fs"; +import * as path from "path"; +import * as yaml from "yaml"; +import type { ComposeSpecification, DefinitionsService } from "./type"; + +interface DockerComposeValidatorOptions { + composePath?: string | null; + verbose?: boolean; + exitOnError?: boolean; +} + +interface ValidationResult { + valid: boolean; + errors: string[]; + warnings: string[]; +} + +type LogLevel = "info" | "success" | "warning" | "error" | "debug"; + +class DockerComposeValidator { + private options: Required; + private errors: string[] = []; + private warnings: string[] = []; + + constructor(options: DockerComposeValidatorOptions = {}) { + this.options = { + composePath: options.composePath || null, + verbose: options.verbose || false, + exitOnError: options.exitOnError !== false, + ...options, + }; + } + + private log(message: string, level: LogLevel = "info"): void { + if (!this.options.verbose && level === "debug") return; + + const prefix: Record = { + info: "πŸ”", + success: "βœ…", + warning: "⚠️", + error: "❌", + debug: "πŸ”", + }; + + console.log(`${prefix[level] || "ℹ️"} ${message}`); + } + + private error(message: string): void { + this.errors.push(message); + this.log(message, "error"); + } + + private warning(message: string): void { + this.warnings.push(message); + this.log(message, "warning"); + } + + /** + * Parse docker-compose.yml file + */ + private parseCompose(composePath: string): ComposeSpecification | null { + try { + if (!fs.existsSync(composePath)) { + this.error(`docker-compose.yml not found at ${composePath}`); + return null; + } + + const content = fs.readFileSync(composePath, "utf8"); + const compose = yaml.parse(content) as ComposeSpecification; + + if (!compose || typeof compose !== "object") { + this.error(`Invalid docker-compose.yml structure at ${composePath}`); + return null; + } + + return compose; + } catch (error: any) { + this.error(`Failed to parse docker-compose.yml: ${error.message}`); + return null; + } + } + + /** + * Validate that docker-compose.yml can be processed by Docker Compose + */ + private validateDockerComposeSyntax(composePath: string): boolean { + // This would ideally use docker compose config, but for now we validate structure + // The actual syntax validation happens in the CI/CD workflow with docker compose config + const compose = this.parseCompose(composePath); + return compose !== null; + } + + /** + * Validate services don't use container_name (Dokploy best practice) + */ + private validateNoContainerName(services: Record): void { + Object.entries(services).forEach(([serviceName, service]) => { + if (service.container_name) { + this.error( + `Service '${serviceName}': Found 'container_name' field. According to README, container_name should not be used. Dokploy manages container names automatically.` + ); + } + }); + } + + /** + * Validate no explicit networks (Dokploy creates networks automatically) + */ + private validateNoExplicitNetworks( + compose: ComposeSpecification, + services: Record + ): void { + // Check for dokploy-network specifically + const hasDokployNetwork = compose.networks && "dokploy-network" in compose.networks; + + // Check if any service uses explicit networks + Object.entries(services).forEach(([serviceName, service]) => { + if (service.networks) { + if (typeof service.networks === "object" && !Array.isArray(service.networks)) { + const networkNames = Object.keys(service.networks); + if (networkNames.includes("dokploy-network")) { + this.error( + `Service '${serviceName}': Uses 'dokploy-network'. Dokploy creates networks automatically, explicit networks are not needed.` + ); + } else if (networkNames.length > 0) { + this.error( + `Service '${serviceName}': Uses explicit network configuration. Dokploy creates networks automatically, explicit networks are not needed.` + ); + } + } else if (Array.isArray(service.networks)) { + if (service.networks.includes("dokploy-network")) { + this.error( + `Service '${serviceName}': Uses 'dokploy-network'. Dokploy creates networks automatically, explicit networks are not needed.` + ); + } else if (service.networks.length > 0) { + this.error( + `Service '${serviceName}': Uses explicit network configuration. Dokploy creates networks automatically, explicit networks are not needed.` + ); + } + } + } + }); + + // Check if networks section exists at root level + if (hasDokployNetwork) { + this.error( + "Found 'dokploy-network' in networks section. Dokploy creates networks automatically, explicit networks are not needed." + ); + } + + if (compose.networks && Object.keys(compose.networks).length > 0) { + this.error( + "Found explicit networks section. Dokploy creates networks automatically, explicit networks are not needed." + ); + } + } + + /** + * Validate ports are not mapped (should be just numbers, not host:container) + */ + private validatePortsFormat(services: Record): void { + Object.entries(services).forEach(([serviceName, service]) => { + if (service.ports) { + service.ports.forEach((port, index) => { + if (typeof port === "string") { + // Check for port mapping format (e.g., "3000:3000" or "8080:80") + if (/^\d+:\d+/.test(port)) { + this.error( + `Service '${serviceName}': ports[${index}] uses port mapping format '${port}'. According to README, use only port number (e.g., '3000') instead of '3000:3000'. Dokploy handles port routing.` + ); + } + } else if (typeof port === "object" && port !== null) { + // Check for published port mapping + if (port.published && port.target) { + this.error( + `Service '${serviceName}': ports[${index}] uses port mapping (published: ${port.published}, target: ${port.target}). According to README, use only port number. Dokploy handles port routing.` + ); + } + } + }); + } + }); + } + + /** + * Validate services exist + */ + private validateServicesExist(compose: ComposeSpecification): boolean { + if (!compose.services || Object.keys(compose.services).length === 0) { + this.error("No services found in docker-compose.yml"); + return false; + } + + const serviceNames = Object.keys(compose.services); + this.log(`Found ${serviceNames.length} service(s): ${serviceNames.join(", ")}`, "debug"); + + return true; + } + + /** + * Validate service names follow best practices + */ + private validateServiceNames(services: Record): void { + Object.keys(services).forEach((serviceName) => { + // Service names should be lowercase and use hyphens + if (serviceName !== serviceName.toLowerCase()) { + this.warning( + `Service '${serviceName}': Service names should be lowercase. Consider using '${serviceName.toLowerCase()}'.` + ); + } + + // Service names should not contain underscores (use hyphens instead) + if (serviceName.includes("_")) { + this.warning( + `Service '${serviceName}': Service names should use hyphens instead of underscores. Consider using '${serviceName.replace(/_/g, "-")}'.` + ); + } + }); + } + + + /** + * Main validation method + */ + validate(): ValidationResult { + if (!this.options.composePath) { + this.error("composePath option is required"); + if (this.options.exitOnError) { + process.exit(1); + } + return { valid: false, errors: this.errors, warnings: this.warnings }; + } + + const composePath = this.options.composePath; + const templateName = path.basename(path.dirname(composePath)); + + this.log(`Validating docker-compose.yml: ${templateName}`); + + // Parse and validate syntax + if (!this.validateDockerComposeSyntax(composePath)) { + if (this.options.exitOnError) { + process.exit(1); + } + return { valid: false, errors: this.errors, warnings: this.warnings }; + } + + const compose = this.parseCompose(composePath); + if (!compose) { + if (this.options.exitOnError) { + process.exit(1); + } + return { valid: false, errors: this.errors, warnings: this.warnings }; + } + + // Validate services exist + if (!this.validateServicesExist(compose)) { + if (this.options.exitOnError) { + process.exit(1); + } + return { valid: false, errors: this.errors, warnings: this.warnings }; + } + + const services = compose.services || {}; + + // Run all validations + this.validateNoContainerName(services); + this.validateNoExplicitNetworks(compose, services); + this.validatePortsFormat(services); + this.validateServiceNames(services); + + // Show summary + if (this.errors.length === 0) { + this.log("Docker Compose file structure is valid", "success"); + + if (this.options.verbose) { + this.log("πŸ“‹ Services found:", "info"); + Object.keys(services).forEach((serviceName) => { + const service = services[serviceName]; + const image = typeof service.image === "string" ? service.image : "N/A"; + this.log(` - ${serviceName}: ${image}`, "debug"); + }); + } + } + + const valid = this.errors.length === 0; + + if (!valid && this.options.exitOnError) { + process.exit(1); + } + + return { valid, errors: this.errors, warnings: this.warnings }; + } +} + +// CLI usage +if (require.main === module) { + const args = process.argv.slice(2); + const options: DockerComposeValidatorOptions = {}; + let composePath: string | null = null; + + // Parse command line arguments + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + switch (arg) { + case "--file": + case "-f": + composePath = args[++i]; + break; + case "--verbose": + case "-v": + options.verbose = true; + break; + case "--help": + case "-h": + console.log(` +Usage: tsx validate-docker-compose.ts [options] + +Options: + -f, --file Docker Compose file path (required) + -v, --verbose Verbose output + -h, --help Show this help message + +Examples: + tsx validate-docker-compose.ts --file blueprints/grafana/docker-compose.yml + tsx validate-docker-compose.ts -f blueprints/grafana/docker-compose.yml --verbose + `); + process.exit(0); + break; + } + } + + if (!composePath) { + console.error("❌ Error: --file option is required"); + console.error("Use --help for usage information"); + process.exit(1); + } + + const validator = new DockerComposeValidator({ + composePath, + ...options, + }); + + const result = validator.validate(); + + // Exit with appropriate code + process.exit(result.valid ? 0 : 1); +} + +export default DockerComposeValidator; + diff --git a/build-scripts/validate-template.ts b/build-scripts/validate-template.ts new file mode 100644 index 00000000..76d7e653 --- /dev/null +++ b/build-scripts/validate-template.ts @@ -0,0 +1,622 @@ +#!/usr/bin/env tsx + +/** + * Validation script for template.toml and docker-compose.yml files + * Validates structure, syntax, and consistency between files + */ + +import * as fs from "fs"; +import * as path from "path"; +import { parse } from "toml"; +import * as yaml from "yaml"; +import type { ComposeSpecification } from "./type"; +import { processVariables, processValue, type Schema } from "./helpers"; + +interface TemplateValidatorOptions { + templateDir?: string | null; + composeServices?: string[] | null; + verbose?: boolean; + exitOnError?: boolean; +} + +interface ValidationResult { + valid: boolean; + errors: string[]; + warnings: string[]; +} + +interface DomainConfig { + serviceName?: string; + port?: number | string; + host?: string; + path?: string; +} + +interface MountConfig { + filePath?: string; + content?: string; +} + +interface TemplateData { + variables?: Record; + config?: { + domains?: DomainConfig[]; + env?: string[] | Record | Array>; + mounts?: MountConfig[]; + }; +} + +type LogLevel = "info" | "success" | "warning" | "error" | "debug"; + +class TemplateValidator { + private options: Required; + private errors: string[] = []; + private warnings: string[] = []; + + constructor(options: TemplateValidatorOptions = {}) { + this.options = { + templateDir: options.templateDir || null, + composeServices: options.composeServices || null, + verbose: options.verbose || false, + exitOnError: options.exitOnError !== false, + ...options, + }; + } + + private log(message: string, level: LogLevel = "info"): void { + if (!this.options.verbose && level === "debug") return; + + const prefix: Record = { + info: "πŸ”", + success: "βœ…", + warning: "⚠️", + error: "❌", + debug: "πŸ”", + }; + + console.log(`${prefix[level] || "ℹ️"} ${message}`); + } + + private error(message: string): void { + this.errors.push(message); + this.log(message, "error"); + } + + private warning(message: string): void { + this.warnings.push(message); + this.log(message, "warning"); + } + + /** + * Validate helper syntax (based on Dokploy's processValue function) + */ + private validateHelper(helper: string, context: string = ""): void { + const validHelpers = [ + "domain", + "base64", + "password", + "hash", + "uuid", + "timestamp", + "timestampms", + "timestamps", + "randomPort", + "jwt", + "username", + "email", + ]; + + // Check if it's a helper with parameters + if (helper.includes(":")) { + const [helperName, ...params] = helper.split(":"); + + // Validate helper name + if (!validHelpers.includes(helperName)) { + // Might be a variable reference, which is valid + return; + } + + // Validate parameter formats + if (helperName === "base64" || helperName === "password" || helperName === "hash") { + // Format: helper:number + const param = params[0]; + if (param && isNaN(parseInt(param, 10))) { + this.warning( + `${context}: helper '${helper}' has invalid parameter (should be a number)` + ); + } + } else if (helperName === "timestampms" || helperName === "timestamps") { + // Format: timestampms:datetime or timestamps:datetime + const datetime = params.join(":"); // Rejoin in case datetime has colons + if (datetime) { + // Try to parse as date + const date = new Date(datetime); + if (isNaN(date.getTime())) { + this.warning( + `${context}: helper '${helper}' has invalid datetime format` + ); + } + } + } else if (helperName === "jwt") { + // Format: jwt:secret or jwt:secret:payload or jwt:length + if (params.length > 0) { + const firstParam = params[0]; + // If it's a number, it's jwt:length (deprecated but valid) + if (!isNaN(parseInt(firstParam, 10))) { + // Valid: jwt:32 + return; + } + // Otherwise it's jwt:secret or jwt:secret:payload + // Both are valid + } + } + } else { + // Simple helper without parameters + if (!validHelpers.includes(helper)) { + // Might be a variable reference, which is valid + return; + } + } + } + + /** + * Parse docker-compose.yml and extract service names + */ + private parseComposeServices(composePath: string): string[] { + try { + if (!fs.existsSync(composePath)) { + this.warning(`docker-compose.yml not found at ${composePath}`); + return []; + } + + const content = fs.readFileSync(composePath, "utf8"); + const compose = yaml.parse(content) as ComposeSpecification; + + if (!compose || typeof compose !== "object") { + this.error(`Invalid docker-compose.yml structure at ${composePath}`); + return []; + } + + // Extract service names using the official ComposeSpecification type + const services = compose.services || {}; + const serviceNames = Object.keys(services); + + if (serviceNames.length === 0) { + this.warning(`No services found in docker-compose.yml at ${composePath}`); + } + + return serviceNames; + } catch (error: any) { + this.error( + `Failed to parse docker-compose.yml at ${composePath}: ${error.message}` + ); + return []; + } + } + + /** + * Validate template.toml structure + */ + private validateTemplate(tomlPath: string, composeServices: string[] | null = null): boolean { + try { + if (!fs.existsSync(tomlPath)) { + this.error(`template.toml not found at ${tomlPath}`); + return false; + } + + // Parse TOML + let data: TemplateData; + try { + const content = fs.readFileSync(tomlPath, "utf8"); + data = parse(content) as TemplateData; + } catch (parseError: any) { + this.error( + `Invalid TOML syntax in ${tomlPath}: ${parseError.message}` + ); + return false; + } + + // Validate [config] section exists + if (!data.config) { + this.error("Missing [config] section in template.toml"); + return false; + } + + // Validate domains + if (data.config.domains) { + if (!Array.isArray(data.config.domains)) { + this.error("config.domains must be an array"); + return false; + } + + data.config.domains.forEach((domain, index) => { + // Required fields + if (!domain.serviceName) { + this.error(`domain[${index}]: Missing required field 'serviceName'`); + } + if (domain.port === undefined || domain.port === null) { + this.error(`domain[${index}]: Missing required field 'port'`); + } + + // Validate serviceName matches docker-compose.yml services + if (domain.serviceName && composeServices && composeServices.length > 0) { + if (!composeServices.includes(domain.serviceName)) { + this.error( + `domain[${index}]: serviceName '${domain.serviceName}' not found in docker-compose.yml services. Available services: ${composeServices.join(", ")}` + ); + } + } + + // Validate port is a number + if (domain.port !== undefined && domain.port !== null) { + const port = typeof domain.port === "string" + ? parseInt(domain.port.replace(/_/g, ""), 10) + : domain.port; + + if (isNaN(Number(port)) || Number(port) < 1 || Number(port) > 65535) { + this.warning( + `domain[${index}]: port '${domain.port}' may be invalid (should be 1-65535)` + ); + } + } + + // Validate host format (should contain ${} for variable substitution) + if (domain.host && typeof domain.host === "string") { + if (!domain.host.includes("${")) { + this.warning( + `domain[${index}]: host '${domain.host}' doesn't use variable syntax (e.g., \${main_domain} or \${domain})` + ); + } else { + // Validate helpers in host + const helperPattern = /\${([^}]+)}/g; + let match: RegExpExecArray | null; + while ((match = helperPattern.exec(domain.host)) !== null) { + this.validateHelper(match[1], `domain[${index}].host`); + } + } + } + }); + } else { + this.warning("No domains configured in template.toml"); + } + + // Validate env - can be array or object (as per Dokploy's processEnvVars) + if (data.config.env !== undefined) { + if (Array.isArray(data.config.env)) { + // Array format: ["KEY=VALUE", ...] + data.config.env.forEach((env, index) => { + if (typeof env === "string") { + if (!env.includes("=")) { + this.warning( + `config.env[${index}]: '${env}' doesn't follow KEY=VALUE format` + ); + } + } else if (typeof env === "object" && env !== null) { + // Object in array is also valid: [{"KEY": "VALUE"}, ...] + const keys = Object.keys(env); + if (keys.length === 0) { + this.warning(`config.env[${index}]: empty object`); + } + } else if (typeof env !== "boolean" && typeof env !== "number") { + this.error( + `config.env[${index}]: must be a string, object, boolean, or number` + ); + } + }); + } else if (typeof data.config.env === "object" && data.config.env !== null) { + // Object format: { KEY: "VALUE", ... } + // This is valid - Dokploy handles both formats + const envKeys = Object.keys(data.config.env); + if (envKeys.length === 0) { + this.warning("config.env is an empty object"); + } + } else { + this.error( + "config.env must be an array or an object (as per Dokploy's processEnvVars)" + ); + } + } + + // Validate mounts if present + if (data.config.mounts) { + if (!Array.isArray(data.config.mounts)) { + this.error("config.mounts must be an array"); + } else { + data.config.mounts.forEach((mount, index) => { + if (!mount.filePath) { + this.error(`config.mounts[${index}]: Missing required field 'filePath'`); + } else if (typeof mount.filePath !== "string") { + this.error(`config.mounts[${index}]: filePath must be a string`); + } + + if (mount.content === undefined) { + this.error(`config.mounts[${index}]: Missing required field 'content'`); + } else if (typeof mount.content !== "string") { + this.error(`config.mounts[${index}]: content must be a string`); + } + }); + } + } + + // Validate variables if present + if (data.variables) { + if (typeof data.variables !== "object" || Array.isArray(data.variables)) { + this.error("variables must be an object"); + } else { + // Validate variable values and helpers + Object.entries(data.variables).forEach(([key, value]) => { + if (typeof value !== "string") { + this.error(`variables.${key}: must be a string`); + return; + } + + // Validate helpers in variable values + const helperPattern = /\${([^}]+)}/g; + let match: RegExpExecArray | null; + while ((match = helperPattern.exec(value)) !== null) { + const helper = match[1]; + this.validateHelper(helper, `variables.${key}`); + } + }); + + // Try to process variables to ensure they resolve correctly + try { + const schema: Schema = {}; + const processedVars = processVariables(data.variables, schema); + + // Check if any variables failed to resolve (still contain ${}) + Object.entries(processedVars).forEach(([key, value]) => { + if (typeof value === "string" && value.includes("${")) { + // Check if it's a valid variable reference or an error + const unresolved = value.match(/\${([^}]+)}/g); + if (unresolved) { + unresolved.forEach((unresolvedVar) => { + const varName = unresolvedVar.slice(2, -1); + // Check if it's a reference to another variable that exists + if (!data.variables![varName] && !varName.includes(":")) { + this.warning( + `variables.${key}: contains unresolved variable reference '${unresolvedVar}'` + ); + } + }); + } + } + }); + + // Validate that domains can be processed with resolved variables + if (data.config.domains) { + data.config.domains.forEach((domain, index) => { + if (domain.host && typeof domain.host === "string") { + try { + const processedHost = processValue(domain.host, processedVars, schema); + if (processedHost.includes("${")) { + this.warning( + `domain[${index}].host: could not fully resolve all variables. Result: ${processedHost}` + ); + } + } catch (e: any) { + this.warning( + `domain[${index}].host: error processing host value: ${e.message}` + ); + } + } + }); + } + + // Validate that env vars can be processed + if (data.config.env) { + if (Array.isArray(data.config.env)) { + data.config.env.forEach((env, index) => { + if (typeof env === "string") { + try { + const processed = processValue(env, processedVars, schema); + if (processed.includes("${")) { + this.warning( + `config.env[${index}]: could not fully resolve all variables` + ); + } + } catch (e: any) { + this.warning( + `config.env[${index}]: error processing env value: ${e.message}` + ); + } + } + }); + } else if (typeof data.config.env === "object") { + Object.entries(data.config.env).forEach(([key, value]) => { + if (typeof value === "string") { + try { + const processed = processValue(value, processedVars, schema); + if (processed.includes("${")) { + this.warning( + `config.env.${key}: could not fully resolve all variables` + ); + } + } catch (e: any) { + this.warning( + `config.env.${key}: error processing env value: ${e.message}` + ); + } + } + }); + } + } + + // Validate that mounts can be processed + if (data.config.mounts) { + data.config.mounts.forEach((mount, index) => { + if (mount.filePath && typeof mount.filePath === "string") { + try { + const processed = processValue(mount.filePath, processedVars, schema); + if (processed.includes("${")) { + this.warning( + `config.mounts[${index}].filePath: could not fully resolve all variables` + ); + } + } catch (e: any) { + this.warning( + `config.mounts[${index}].filePath: error processing filePath: ${e.message}` + ); + } + } + if (mount.content && typeof mount.content === "string") { + try { + const processed = processValue(mount.content, processedVars, schema); + if (processed.includes("${")) { + this.warning( + `config.mounts[${index}].content: could not fully resolve all variables` + ); + } + } catch (e: any) { + this.warning( + `config.mounts[${index}].content: error processing content: ${e.message}` + ); + } + } + }); + } + + if (this.options.verbose) { + this.log("βœ… Variables processed successfully", "success"); + this.log(`πŸ“‹ Processed ${Object.keys(processedVars).length} variables`, "debug"); + } + } catch (e: any) { + this.error(`Failed to process variables: ${e.message}`); + } + } + } + + return this.errors.length === 0; + } catch (error: any) { + this.error(`Error validating template.toml: ${error.message}`); + return false; + } + } + + /** + * Validate a template directory + */ + private validateTemplateDir(templateDir: string): ValidationResult { + // Resolver rutas absolutas o relativas desde la raΓ­z del proyecto + const resolvedDir = path.isAbsolute(templateDir) + ? templateDir + : path.resolve(process.cwd(), templateDir); + + const templatePath = path.join(resolvedDir, "template.toml"); + const composePath = path.join(resolvedDir, "docker-compose.yml"); + + this.log(`Validating template: ${path.basename(resolvedDir)}`); + + // Parse compose services first + const composeServices = this.parseComposeServices(composePath); + + // Validate template.toml + const isValid = this.validateTemplate(templatePath, composeServices); + + // Show summary + if (isValid && this.errors.length === 0) { + this.log("Template structure is valid", "success"); + + // Show domains info + try { + const content = fs.readFileSync(templatePath, "utf8"); + const data = parse(content) as TemplateData; + if (data.config && data.config.domains) { + this.log("πŸ“‹ Domains configured:"); + data.config.domains.forEach((domain) => { + const service = domain.serviceName || "N/A"; + const port = domain.port !== undefined ? domain.port : "N/A"; + const host = domain.host || "N/A"; + this.log(` - Service: ${service}, Port: ${port}, Host: ${host}`); + }); + } + } catch (e) { + // Ignore errors in summary + } + } + + return { + valid: isValid && this.errors.length === 0, + errors: this.errors, + warnings: this.warnings, + }; + } + + /** + * Main validation method + */ + validate(): ValidationResult { + if (!this.options.templateDir) { + this.error("templateDir option is required"); + if (this.options.exitOnError) { + process.exit(1); + } + return { valid: false, errors: this.errors, warnings: this.warnings }; + } + + const result = this.validateTemplateDir(this.options.templateDir!); + + if (!result.valid && this.options.exitOnError) { + process.exit(1); + } + + return result; + } +} + +// CLI usage +if (require.main === module) { + const args = process.argv.slice(2); + const options: TemplateValidatorOptions = {}; + let templateDir: string | null = null; + + // Parse command line arguments + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + switch (arg) { + case "--dir": + case "-d": + templateDir = args[++i]; + break; + case "--verbose": + case "-v": + options.verbose = true; + break; + case "--help": + case "-h": + console.log(` +Usage: tsx validate-template.ts [options] + +Options: + -d, --dir Template directory path (required) + -v, --verbose Verbose output + -h, --help Show this help message + +Examples: + tsx validate-template.ts --dir blueprints/grafana + tsx validate-template.ts -d blueprints/grafana --verbose + `); + process.exit(0); + break; + } + } + + if (!templateDir) { + console.error("❌ Error: --dir option is required"); + console.error("Use --help for usage information"); + process.exit(1); + } + + const validator = new TemplateValidator({ + templateDir, + ...options, + }); + + const result = validator.validate(); + + // Exit with appropriate code + process.exit(result.valid ? 0 : 1); +} + +export default TemplateValidator; + diff --git a/meta.json b/meta.json index 5cea3110..ee73ec65 100644 --- a/meta.json +++ b/meta.json @@ -295,6 +295,23 @@ "chatbot" ] }, + { + "id": "anytype", + "name": "Anytype", + "version": "latest", + "description": "Anytype is a personal knowledge baseβ€”your digital brainβ€”that lets you gather, connect and remix all kinds of information. Create pages, tasks, wikis, journalsβ€”even entire appsβ€”and define your own data model while your data stays offline-first, private and encrypted across devices.\n\nAfter installation, you can view the Anytype client configuration by running `cat /data/client-config.yml` inside the service container.", + "logo": "logo.png", + "links": { + "github": "https://github.com/grishy/any-sync-bundle", + "docs": "https://doc.anytype.io/anytype-docs", + "website": "https://anytype.io/" + }, + "tags": [ + "note-taking", + "local-first", + "peer-to-peer" + ] + }, { "id": "appflowy", "name": "App Flowy", @@ -733,6 +750,24 @@ "nextjs" ] }, + { + "id": "bluesky-pds", + "name": "Bluesky PDS", + "version": "0.4.182", + "description": "Bluesky PDS is a personal data server for Bluesky.", + "logo": "bluesky-pds.svg", + "links": { + "github": "https://github.com/bluesky-social/pds", + "website": "https://bsky.social/about", + "docs": "https://github.com/bluesky-social/pds" + }, + "tags": [ + "bluesky", + "pds", + "data", + "server" + ] + }, { "id": "bolt.diy", "name": "bolt.diy", @@ -1156,6 +1191,25 @@ "Document Management" ] }, + { + "id": "chirpstack", + "name": "ChirpStack", + "version": "4", + "description": "Open-source LoRaWAN Network Server for IoT applications. Complete stack with gateway bridges, REST API, and web interface for managing LoRaWAN devices and gateways.", + "logo": "chirpstack.png", + "links": { + "github": "https://github.com/chirpstack/chirpstack", + "website": "https://www.chirpstack.io/", + "docs": "https://www.chirpstack.io/docs/" + }, + "tags": [ + "iot", + "lorawan", + "network-server", + "gateway", + "monitoring" + ] + }, { "id": "chromium", "name": "Chromium", @@ -1776,6 +1830,26 @@ "document-signing" ] }, + { + "id": "dokploy-prom-monitoring-extension", + "name": "Dokploy Prometheus Monitoring Extension", + "version": "canary", + "description": "Dokploy monitoring extension with Prometheus metrics export for external monitoring systems like Grafana Cloud. Tracks server and container metrics with configurable thresholds and alerting.", + "logo": "logo.svg", + "links": { + "github": "https://github.com/Dokploy/dokploy", + "website": "https://dokploy.com/", + "docs": "https://docs.dokploy.com/" + }, + "tags": [ + "monitoring", + "prometheus", + "metrics", + "observability", + "docker", + "grafana" + ] + }, { "id": "domain-locker", "name": "Domain Locker", @@ -1998,7 +2072,7 @@ "description": "Enshrouded steam dedicated server.", "logo": "enshrouded.png", "links": { - "github": "https://github.com/jsknnr/enshrouded-server", + "github": "https://github.com/mornedhels/enshrouded-server", "website": "", "docs": "" }, @@ -2956,7 +3030,7 @@ { "id": "infisical", "name": "Infisical", - "version": "0.90.1", + "version": "0.135.0", "description": "All-in-one platform to securely manage application configuration and secrets across your team and infrastructure.", "logo": "infisical.jpg", "links": { @@ -3195,6 +3269,25 @@ "personal" ] }, + { + "id": "kokoro-tts", + "name": "Kokoro TTS", + "version": "latest", + "description": "Dockerized FastAPI wrapper for the Kokoro-82M text-to-speech model with multi-language support and OpenAI-compatible endpoints.", + "logo": "kokoro-tts.svg", + "links": { + "github": "https://github.com/remsky/Kokoro-FastAPI", + "website": "https://github.com/remsky/Kokoro-FastAPI", + "docs": "https://github.com/remsky/Kokoro-FastAPI#readme" + }, + "tags": [ + "text-to-speech", + "ai", + "voice", + "fastapi", + "openai-compatible" + ] + }, { "id": "kokoro-web", "name": "Kokoro Web", @@ -3261,6 +3354,26 @@ "productivity" ] }, + { + "id": "librechat", + "name": "LibreChat", + "version": "latest", + "description": "LibreChat is the ultimate open-source app for all your AI conversations, fully customizable and compatible with any AI provider (Openai, Ollama, Google etc.) β€” all in one sleek interface.", + "logo": "librechat.png", + "links": { + "github": "https://github.com/danny-avila/librechat", + "website": "https://librechat.ai", + "docs": "https://docs.librechat.ai" + }, + "tags": [ + "ai", + "chatbot", + "llm", + "MIT-license", + "BYOK", + "generative-ai" + ] + }, { "id": "libredesk", "name": "Libredesk", @@ -3550,6 +3663,24 @@ "gallery" ] }, + { + "id": "mcsmanager", + "name": "MCSManager", + "version": "latest", + "description": "A modern dashboard for managing Minecraft servers. Primarily focused on Minecraft, but also supports other games and features a UI that's easy for beginners to use and supports i18n.", + "logo": "mcsmanager.png", + "links": { + "github": "https://github.com/MCSManager/MCSManager", + "website": "https://github.com/MCSManager/MCSManager", + "docs": "https://github.com/MCSManager/MCSManager#readme" + }, + "tags": [ + "minecraft", + "game-server", + "management", + "dashboard" + ] + }, { "id": "mealie", "name": "Mealie (sqlite version)", @@ -3567,6 +3698,25 @@ "meal-planning" ] }, + { + "id": "mediacms", + "name": "MediaCMS", + "version": "latest", + "description": "MediaCMS is an open-source video and media CMS. It is a modern, full-featured solution for managing and streaming media content.", + "logo": "mediacms.svg", + "links": { + "github": "https://github.com/mediacms/mediacms", + "website": "https://mediacms.io/", + "docs": "https://docs.mediacms.io/" + }, + "tags": [ + "media", + "video", + "cms", + "streaming", + "self-hosted" + ] + }, { "id": "meilisearch", "name": "Meilisearch", @@ -3709,6 +3859,43 @@ "rating" ] }, + { + "id": "mulesoft-esb", + "name": "MuleSoft ESB Runtime Community Edition", + "version": "latest", + "description": "MuleSoft ESB Runtime is a lightweight, Java-based integration platform that allows you to easily integrate applications, data sources, and APIs. It provides powerful connectors and data transformation capabilities for building robust integration solutions.", + "logo": "mulesoft_logo.png", + "links": { + "github": "https://github.com/mulesoft", + "website": "https://www.mulesoft.com/", + "docs": "https://docs.mulesoft.com/" + }, + "tags": [ + "integration", + "api", + "esb", + "enterprise", + "java" + ] + }, + { + "id": "mumble", + "name": "Mumble", + "version": "latest", + "description": "Mumble is an open-source, low-latency, high-quality voice chat software primarily intended for use while gaming.", + "logo": "mumble.png", + "links": { + "github": "https://github.com/mumble-voip/mumble", + "website": "https://www.mumble.info/", + "docs": "https://wiki.mumble.info/" + }, + "tags": [ + "voice-chat", + "communication", + "gaming", + "voip" + ] + }, { "id": "n8n", "name": "n8n", @@ -4157,6 +4344,25 @@ "openai" ] }, + { + "id": "openinary", + "name": "Openinary", + "version": "latest", + "description": "Openinary is a self-hosted Cloudinary alternative.", + "logo": "openinary.svg", + "links": { + "github": "https://github.com/openinary/openinary", + "website": "https://openinary.dev", + "docs": "https://docs.openinary.dev" + }, + "tags": [ + "media", + "images", + "videos", + "cloudinary-alternative", + "developer-tools" + ] + }, { "id": "openpanel", "name": "OpenPanel", @@ -4283,6 +4489,42 @@ "open-source" ] }, + { + "id": "parseable", + "name": "Parseable", + "version": "v1.6.5", + "description": "Fast observability and log analytics platform on object storage", + "logo": "logo.svg", + "links": { + "github": "https://github.com/parseablehq/parseable", + "website": "https://www.parseable.com/", + "docs": "https://www.parseable.com/docs" + }, + "tags": [ + "observability", + "logging", + "analytics", + "monitoring" + ] + }, + { + "id": "passbolt", + "name": "Passbolt", + "version": "latest-ce", + "description": "Passbolt is an open source credential platform for modern teams. A versatile, battle-tested solution to manage and collaborate on passwords, accesses, and secrets. All in one.", + "logo": "passbolt.svg", + "links": { + "github": "https://github.com/passbolt/passbolt_api", + "website": "https://www.passbolt.com/", + "docs": "https://www.passbolt.com/docs/" + }, + "tags": [ + "password-manager", + "security", + "team-collaboration", + "encryption" + ] + }, { "id": "pastefy", "name": "Pastefy", @@ -4322,6 +4564,25 @@ "client-management" ] }, + { + "id": "peerdb", + "name": "PeerDB", + "version": "v0.35.5", + "description": "Data integration platform that synchronizes and federates data across databases with a unified API.", + "logo": "peerdb.jpeg", + "links": { + "github": "https://github.com/peerdb-io/peerdb", + "website": "https://peerdb.io", + "docs": "https://docs.peerdb.io" + }, + "tags": [ + "database", + "integration", + "sync", + "sql", + "workflow" + ] + }, { "id": "penpot", "name": "Penpot", @@ -4732,6 +4993,25 @@ "search" ] }, + { + "id": "quant-ux", + "name": "Quant-UX", + "version": "latest", + "description": "Quant-UX is an open-source UX design and prototyping tool that allows you to create interactive prototypes, conduct user research, and analyze user behavior.", + "logo": "logo.svg", + "links": { + "github": "https://github.com/KlausSchaefers/quant-ux", + "website": "https://www.quant-ux.com/", + "docs": "https://www.quant-ux.com/" + }, + "tags": [ + "design", + "ux", + "prototyping", + "user-research", + "analytics" + ] + }, { "id": "rabbitmq", "name": "RabbitMQ", @@ -4781,6 +5061,24 @@ "chat" ] }, + { + "id": "rote", + "name": "Rote", + "version": "latest", + "description": "Rote is an open-source multi-platform personal note system featuring an open API, full data ownership, and effortless Docker deployment.", + "logo": "rote.png", + "links": { + "github": "https://github.com/Rabithua/Rote", + "website": "https://rote.ink", + "docs": "https://github.com/Rabithua/Rote/tree/main/doc/userguide" + }, + "tags": [ + "notes", + "productivity", + "postgres", + "bun" + ] + }, { "id": "roundcube", "name": "Roundcube", @@ -4850,6 +5148,24 @@ "productivity" ] }, + { + "id": "rustfs", + "name": "RustFS", + "version": "latest", + "description": "RustFS is a high-performance, S3-compatible distributed object storage system built in Rust. 2.3x faster than MinIO for small objects, with full S3 API compatibility.", + "logo": "logo.svg", + "links": { + "github": "https://github.com/rustfs/rustfs", + "website": "https://rustfs.com/", + "docs": "https://docs.rustfs.com/" + }, + "tags": [ + "storage", + "s3", + "object-storage", + "rust" + ] + }, { "id": "rutorrent", "name": "ruTorrent", @@ -5274,7 +5590,7 @@ { "id": "tolgee", "name": "Tolgee", - "version": "v3.80.4", + "version": "latest", "description": "Developer & translator friendly web-based localization platform", "logo": "tolgee.svg", "links": { @@ -5360,7 +5676,7 @@ { "id": "trmnl-byos-laravel", "name": "TRMNL BYOS Laravel", - "version": "0.14.0", + "version": "0.21.0", "description": "TRMNL BYOS Laravel is a self-hosted application to manage TRMNL e-ink devices.", "logo": "byos-laravel.svg", "links": {