From ddcf83aa69bfb6d1e2a7d91a5a30507c298d1e3f Mon Sep 17 00:00:00 2001 From: Yuvraj Date: Sun, 6 Oct 2024 01:31:45 +0530 Subject: [PATCH] init --- .dockerignore | 4 + .env | 12 + .env.docker | 11 + .env.template | 8 + .gitattributes | 3 + .github/workflows/go.yaml | 52 + .github/workflows/release.yaml | 67 + .gitignore | 136 + .golangci.yml | 15 + .goreleaser.yml | 99 + 2024-10-05_tasks.docx | Bin 0 -> 18272 bytes Dockerfile | 43 + Dockerfile.client | 45 + Makefile | 129 + README.md | 621 + buf.gen.yaml | 31 + buf.work.yaml | 3 + charts/task/Chart.lock | 6 + charts/task/Chart.yaml | 18 + charts/task/README.md | 79 + charts/task/templates/_helpers.tpl | 135 + charts/task/templates/dashboard.yaml | 58 + charts/task/templates/deployment.yaml | 71 + charts/task/templates/hpa.yaml | 30 + charts/task/templates/secret.yaml | 12 + charts/task/templates/service.yaml | 17 + charts/task/templates/serviceaccount.yaml | 12 + charts/task/values.yaml | 120 + cli/cmd/end2end.go | 195 + cli/cmd/history.go | 96 + cli/cmd/root.go | 56 + cli/cmd/task.go | 329 + cli/main.go | 9 + clients/dashboard/.env | 2 + clients/dashboard/commitlint.config.js | 24 + clients/dashboard/components.json | 20 + clients/dashboard/jest.config.js | 30 + clients/dashboard/jest.setup.js | 5 + clients/dashboard/next-env.d.ts | 5 + clients/dashboard/next-sitemap.config.js | 13 + clients/dashboard/next.config.js | 55 + clients/dashboard/package.json | 88 + clients/dashboard/postcss.config.js | 6 + clients/dashboard/public/favicon.ico | Bin 0 -> 10990 bytes .../public/favicon/android-chrome-192x192.png | Bin 0 -> 8899 bytes .../public/favicon/android-chrome-512x512.png | Bin 0 -> 50301 bytes .../public/favicon/apple-touch-icon.png | Bin 0 -> 8545 bytes .../public/favicon/favicon-16x16.png | Bin 0 -> 937 bytes .../public/favicon/favicon-32x32.png | Bin 0 -> 1583 bytes clients/dashboard/public/favicon/favicon.ico | Bin 0 -> 10990 bytes .../dashboard/public/favicon/site.webmanifest | 19 + .../public/fonts/inter-var-latin.woff2 | Bin 0 -> 36532 bytes clients/dashboard/public/images/new-tab.png | Bin 0 -> 565 bytes clients/dashboard/public/images/og.jpg | Bin 0 -> 149123 bytes clients/dashboard/public/robots.txt | 9 + clients/dashboard/public/sitemap-0.xml | 4 + clients/dashboard/public/sitemap.xml | 4 + clients/dashboard/public/svg/Logo.svg | 1 + clients/dashboard/public/svg/Vercel.svg | 1 + clients/dashboard/renovate.json | 9 + clients/dashboard/src/app/error.tsx | 35 + clients/dashboard/src/app/layout.tsx | 66 + clients/dashboard/src/app/not-found.tsx | 24 + clients/dashboard/src/app/page.tsx | 38 + .../dashboard/src/components/task/create.tsx | 141 + .../dashboard/src/components/task/editor.tsx | 67 + .../dashboard/src/components/task/history.tsx | 117 + .../dashboard/src/components/task/list.tsx | 344 + clients/dashboard/src/components/task/util.ts | 70 + .../dashboard/src/components/ui/button.tsx | 57 + clients/dashboard/src/components/ui/card.tsx | 76 + .../dashboard/src/components/ui/dialog.tsx | 122 + clients/dashboard/src/components/ui/input.tsx | 25 + clients/dashboard/src/components/ui/label.tsx | 26 + .../dashboard/src/components/ui/select.tsx | 160 + clients/dashboard/src/components/ui/sheet.tsx | 140 + clients/dashboard/src/components/ui/table.tsx | 120 + clients/dashboard/src/constant/config.ts | 7 + clients/dashboard/src/constant/env.ts | 6 + clients/dashboard/src/lib/env.ts | 20 + clients/dashboard/src/lib/helper.ts | 13 + clients/dashboard/src/lib/logger.ts | 19 + clients/dashboard/src/lib/og.ts | 27 + clients/dashboard/src/lib/utils.ts | 6 + clients/dashboard/src/styles/colors.css | 550 + clients/dashboard/src/styles/globals.css | 180 + clients/dashboard/src/validate/validate_pb.ts | 2621 +++ clients/dashboard/tailwind.config.ts | 98 + clients/dashboard/tsconfig.json | 51 + clients/dashboard/vercel.json | 13 + docker-compose.demo.yaml | 74 + docker-compose.yaml | 12 + go.mod | 87 + go.sum | 191 + idl/buf.lock | 13 + idl/buf.md | 15 + idl/buf.yaml | 11 + idl/cloud/v1/cloud.proto | 219 + package-lock.json | 18062 ++++++++++++++++ package.json | 59 + pixi.lock | 2122 ++ pixi.toml | 21 + pkg/config/config.go | 45 + pkg/config/config_test.go | 43 + pkg/gen/cloud/v1/cloud.pb.go | 1312 ++ pkg/gen/cloud/v1/cloud.swagger.json | 197 + .../cloud/v1/cloudv1connect/cloud.connect.go | 265 + pkg/gen/index.html | 3718 ++++ pkg/gen/validate/validate.pb.go | 4111 ++++ pkg/gen/validate/validate.swagger.json | 44 + pkg/plugins/email/email.go | 24 + pkg/plugins/email/email_test.go | 31 + pkg/plugins/plugins.go | 24 + pkg/plugins/plugins_test.go | 55 + pkg/plugins/query/query.go | 33 + pkg/plugins/query/query_test.go | 46 + pkg/worker/cron.go | 124 + pkg/worker/error.go | 24 + pkg/worker/worker.go | 133 + pkg/x/x.go | 222 + pkg/x/x_test.go | 145 + server/repository/factory.go | 145 + server/repository/gormimpl/history.go | 78 + server/repository/gormimpl/history_test.go | 39 + server/repository/gormimpl/task.go | 185 + server/repository/gormimpl/task_test.go | 57 + server/repository/interface/history.go | 25 + server/repository/interface/repo.go | 7 + server/repository/interface/task.go | 39 + server/repository/mocks/task_history_repo.go | 213 + .../mocks/task_managment_interface.go | 130 + server/repository/mocks/task_repo.go | 322 + server/repository/model/task/history.go | 27 + server/repository/model/task/task.go | 51 + server/repository/postgres.go | 32 + server/root/main.go | 213 + server/route/mocks/task_management_handler.go | 334 + server/route/route.go | 20 + server/route/task.go | 394 + server/route/task_test.go | 252 + turbo.json | 31 + 141 files changed, 42132 insertions(+) create mode 100644 .dockerignore create mode 100644 .env create mode 100644 .env.docker create mode 100644 .env.template create mode 100644 .gitattributes create mode 100644 .github/workflows/go.yaml create mode 100644 .github/workflows/release.yaml create mode 100644 .gitignore create mode 100644 .golangci.yml create mode 100644 .goreleaser.yml create mode 100644 2024-10-05_tasks.docx create mode 100644 Dockerfile create mode 100644 Dockerfile.client create mode 100644 Makefile create mode 100644 README.md create mode 100644 buf.gen.yaml create mode 100644 buf.work.yaml create mode 100644 charts/task/Chart.lock create mode 100644 charts/task/Chart.yaml create mode 100644 charts/task/README.md create mode 100644 charts/task/templates/_helpers.tpl create mode 100644 charts/task/templates/dashboard.yaml create mode 100644 charts/task/templates/deployment.yaml create mode 100644 charts/task/templates/hpa.yaml create mode 100644 charts/task/templates/secret.yaml create mode 100644 charts/task/templates/service.yaml create mode 100644 charts/task/templates/serviceaccount.yaml create mode 100644 charts/task/values.yaml create mode 100644 cli/cmd/end2end.go create mode 100644 cli/cmd/history.go create mode 100644 cli/cmd/root.go create mode 100644 cli/cmd/task.go create mode 100644 cli/main.go create mode 100644 clients/dashboard/.env create mode 100644 clients/dashboard/commitlint.config.js create mode 100644 clients/dashboard/components.json create mode 100644 clients/dashboard/jest.config.js create mode 100644 clients/dashboard/jest.setup.js create mode 100644 clients/dashboard/next-env.d.ts create mode 100644 clients/dashboard/next-sitemap.config.js create mode 100644 clients/dashboard/next.config.js create mode 100644 clients/dashboard/package.json create mode 100644 clients/dashboard/postcss.config.js create mode 100644 clients/dashboard/public/favicon.ico create mode 100644 clients/dashboard/public/favicon/android-chrome-192x192.png create mode 100644 clients/dashboard/public/favicon/android-chrome-512x512.png create mode 100644 clients/dashboard/public/favicon/apple-touch-icon.png create mode 100644 clients/dashboard/public/favicon/favicon-16x16.png create mode 100644 clients/dashboard/public/favicon/favicon-32x32.png create mode 100644 clients/dashboard/public/favicon/favicon.ico create mode 100644 clients/dashboard/public/favicon/site.webmanifest create mode 100644 clients/dashboard/public/fonts/inter-var-latin.woff2 create mode 100644 clients/dashboard/public/images/new-tab.png create mode 100644 clients/dashboard/public/images/og.jpg create mode 100644 clients/dashboard/public/robots.txt create mode 100644 clients/dashboard/public/sitemap-0.xml create mode 100644 clients/dashboard/public/sitemap.xml create mode 100644 clients/dashboard/public/svg/Logo.svg create mode 100644 clients/dashboard/public/svg/Vercel.svg create mode 100644 clients/dashboard/renovate.json create mode 100644 clients/dashboard/src/app/error.tsx create mode 100644 clients/dashboard/src/app/layout.tsx create mode 100644 clients/dashboard/src/app/not-found.tsx create mode 100644 clients/dashboard/src/app/page.tsx create mode 100644 clients/dashboard/src/components/task/create.tsx create mode 100644 clients/dashboard/src/components/task/editor.tsx create mode 100644 clients/dashboard/src/components/task/history.tsx create mode 100644 clients/dashboard/src/components/task/list.tsx create mode 100644 clients/dashboard/src/components/task/util.ts create mode 100644 clients/dashboard/src/components/ui/button.tsx create mode 100644 clients/dashboard/src/components/ui/card.tsx create mode 100644 clients/dashboard/src/components/ui/dialog.tsx create mode 100644 clients/dashboard/src/components/ui/input.tsx create mode 100644 clients/dashboard/src/components/ui/label.tsx create mode 100644 clients/dashboard/src/components/ui/select.tsx create mode 100644 clients/dashboard/src/components/ui/sheet.tsx create mode 100644 clients/dashboard/src/components/ui/table.tsx create mode 100644 clients/dashboard/src/constant/config.ts create mode 100644 clients/dashboard/src/constant/env.ts create mode 100644 clients/dashboard/src/lib/env.ts create mode 100644 clients/dashboard/src/lib/helper.ts create mode 100644 clients/dashboard/src/lib/logger.ts create mode 100644 clients/dashboard/src/lib/og.ts create mode 100644 clients/dashboard/src/lib/utils.ts create mode 100644 clients/dashboard/src/styles/colors.css create mode 100644 clients/dashboard/src/styles/globals.css create mode 100644 clients/dashboard/src/validate/validate_pb.ts create mode 100644 clients/dashboard/tailwind.config.ts create mode 100644 clients/dashboard/tsconfig.json create mode 100644 clients/dashboard/vercel.json create mode 100644 docker-compose.demo.yaml create mode 100644 docker-compose.yaml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 idl/buf.lock create mode 100644 idl/buf.md create mode 100644 idl/buf.yaml create mode 100644 idl/cloud/v1/cloud.proto create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 pixi.lock create mode 100644 pixi.toml create mode 100644 pkg/config/config.go create mode 100644 pkg/config/config_test.go create mode 100644 pkg/gen/cloud/v1/cloud.pb.go create mode 100644 pkg/gen/cloud/v1/cloud.swagger.json create mode 100644 pkg/gen/cloud/v1/cloudv1connect/cloud.connect.go create mode 100644 pkg/gen/index.html create mode 100644 pkg/gen/validate/validate.pb.go create mode 100644 pkg/gen/validate/validate.swagger.json create mode 100644 pkg/plugins/email/email.go create mode 100644 pkg/plugins/email/email_test.go create mode 100644 pkg/plugins/plugins.go create mode 100644 pkg/plugins/plugins_test.go create mode 100644 pkg/plugins/query/query.go create mode 100644 pkg/plugins/query/query_test.go create mode 100644 pkg/worker/cron.go create mode 100644 pkg/worker/error.go create mode 100644 pkg/worker/worker.go create mode 100644 pkg/x/x.go create mode 100644 pkg/x/x_test.go create mode 100644 server/repository/factory.go create mode 100644 server/repository/gormimpl/history.go create mode 100644 server/repository/gormimpl/history_test.go create mode 100644 server/repository/gormimpl/task.go create mode 100644 server/repository/gormimpl/task_test.go create mode 100644 server/repository/interface/history.go create mode 100644 server/repository/interface/repo.go create mode 100644 server/repository/interface/task.go create mode 100644 server/repository/mocks/task_history_repo.go create mode 100644 server/repository/mocks/task_managment_interface.go create mode 100644 server/repository/mocks/task_repo.go create mode 100644 server/repository/model/task/history.go create mode 100644 server/repository/model/task/task.go create mode 100644 server/repository/postgres.go create mode 100644 server/root/main.go create mode 100644 server/route/mocks/task_management_handler.go create mode 100644 server/route/route.go create mode 100644 server/route/task.go create mode 100644 server/route/task_test.go create mode 100644 turbo.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b6cf61d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +bin +deployment +localclients.json +.env \ No newline at end of file diff --git a/.env b/.env new file mode 100644 index 0000000..7e92530 --- /dev/null +++ b/.env @@ -0,0 +1,12 @@ +SERVER_PORT=8080 +WORKER_COUNT=500 +SERVER_ENDPOINT="http://127.0.0.1:8080" +NEXT_PUBLIC_SERVER_ENDPOINT="http://127.0.0.1:8080" +DB_HOST=127.0.0.1 +DB_PORT=5432 +DB_DATABASE=tasks +DB_USERNAME=admin +DB_PASSWORD="admin" +DB_SSL_MODE=disable +DB_POOL_MAX_CONNS=50 +TASK_TIME_OUT=3 \ No newline at end of file diff --git a/.env.docker b/.env.docker new file mode 100644 index 0000000..a6d7060 --- /dev/null +++ b/.env.docker @@ -0,0 +1,11 @@ +SERVER_PORT=8080 +SERVER_ENDPOINT="http://task:8080" +NEXT_PUBLIC_SERVER_ENDPOINT="http://task:8080" +DB_HOST=db +DB_PORT=5432 +DB_DATABASE=tasks +DB_USERNAME=admin +DB_PASSWORD="admin" +DB_SSL_MODE=disable +DB_POOL_MAX_CONNS=30 +WORKER_COUNT=100 \ No newline at end of file diff --git a/.env.template b/.env.template new file mode 100644 index 0000000..4189016 --- /dev/null +++ b/.env.template @@ -0,0 +1,8 @@ +SERVER_PORT=8086 +DB_HOST=localhost +DB_PORT=8848 +DB_DATABASE=tasks +DB_USERNAME=admin +DB_PASSWORD=admin +DB_SSL_MODE=disable +DB_POOL_MAX_CONNS=30 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..16ef5c5 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# GitHub syntax highlighting +pixi.lock linguist-language=YAML + diff --git a/.github/workflows/go.yaml b/.github/workflows/go.yaml new file mode 100644 index 0000000..23fa78f --- /dev/null +++ b/.github/workflows/go.yaml @@ -0,0 +1,52 @@ +# This workflow will build a golang project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go + +name: Go Checks + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + go: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.22" + + - name: Setup + run: | + go mod tidy + go install github.com/vektra/mockery/v2@v2.46.0 + + - name: Build Server + run: go generate -v ./... + + - name: Test + run: go test -v ./... + + - name: Build Server + run: make build-server + + - name: Build Server + run: make build-cli + + container: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Publish Image + run: | + make docker-build-server + make docker-build-cli + make docker-build-dashboard diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..98a2591 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,67 @@ +name: 🚀 Release + +on: + push: + # run only against tags + tags: + - "*" + +permissions: + actions: write + contents: read + +jobs: + container: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Get Version from Tag + id: version + run: | + version=$(echo "${GITHUB_REF#refs/tags/}") + echo "Tagged version: $version" + echo "::set-output name=version::$version" + + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: yindia + password: ${{ secrets.GH_TOKEN }} + - name: Publish Image + run: | + VERSION="${{ steps.version.outputs.version }}" make push + + buf: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: bufbuild/buf-setup-action@v1 + with: + buf_user: yindia + buf_api_token: ${{ secrets.BUF_API_TOKEN }} + - uses: bufbuild/buf-push-action@v1 + with: + input: idl + buf_token: ${{ secrets.BUF_API_TOKEN }} + + goreleaser: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - run: git fetch --force --tags + - uses: actions/setup-go@v4 + with: + go-version: stable + - uses: goreleaser/goreleaser-action@v4 + with: + distribution: goreleaser + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b2ecd6f --- /dev/null +++ b/.gitignore @@ -0,0 +1,136 @@ +# Created by https://www.toptal.com/developers/gitignore/api/goland,go,macos +# Edit at https://www.toptal.com/developers/gitignore?templates=goland,go,macos + +### Go ### +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +### Go Patch ### +/vendor/ +/Godeps/ + +### Goland ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm, Rider and Goland +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Ignores the whole .idea folder and all .iml files +.idea/ + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# End of https://www.toptal.com/developers/gitignore/api/goland,go,macos + + + +bin +__pycache__/ + +.pixi/ +.turbo/ +clients/dashboard/.next/ +clients/dashboard/node_modules/ +clients/dashboard/pkg/ +clients/dashboard/src/cloud/ +dist/ +node_modules/ +test +charts/task/charts/ \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..6c7710b --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,15 @@ +linters: + disable-all: true + enable: + - deadcode + - gas + - goimports + - gosimple + - ineffassign + - misspell + - nakedret + - structcheck + - typecheck + - unparam + - unused + - varcheck \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..73a0ebb --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,99 @@ +version: 2 +before: + hooks: + - go mod download + +builds: + - env: + - CGO_ENABLED=0 + main: ./cli/main.go + binary: task-cli + id: task-darwin + goos: + - darwin + goarch: + - arm64 + - amd64 + ldflags: + - -s -w -X github.com/flyteorg/flytestdlib/version.Version={{.Version}} -X github.com/flyteorg/flytestdlib/version.Build={{.ShortCommit}} -X github.com/flyteorg/flytestdlib/version.BuildTime={{.Date}} + - env: + - CGO_ENABLED=0 + main: ./cli/main.go + binary: task-cli + id: task-linux + goos: + - linux + goarch: + - arm64 + - amd64 + ldflags: + - -s -w -X github.com/flyteorg/flytestdlib/version.Version={{.Version}} -X github.com/flyteorg/flytestdlib/version.Build={{.ShortCommit}} -X github.com/flyteorg/flytestdlib/version.BuildTime={{.Date}} + - env: + - CGO_ENABLED=0 + main: ./cli/main.go + binary: task-cli + id: task-windows + goos: + - windows + goarch: + - arm64 + - amd64 + ldflags: + - -s -w -X github.com/flyteorg/flytestdlib/version.Version={{.Version}} -X github.com/flyteorg/flytestdlib/version.Build={{.ShortCommit}} -X github.com/flyteorg/flytestdlib/version.BuildTime={{.Date}} + +archives: + - name_template: |- + {{ .ProjectName }}_ + {{- if eq .Os "darwin" }}Darwin + {{- else if eq .Os "linux" }}Linux + {{- else if eq .Os "windows" }}Windows + {{- else }}{{ .Os }}{{ end }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} + {{- if .Arm }}v{{ .Arm }}{{ end }} + strip_binary_directory: true + format_overrides: + - goos: windows + format: zip + +checksum: + name_template: "checksums.txt" + +snapshot: + name_template: "{{ .Tag }}-next" + +changelog: + disable: true + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" + +brews: + - name: task-cli + directory: Formula + repository: + owner: yindia + name: iteration + commit_author: + name: Yuvraj + email: evalsocket@gmail.com + homepage: "https://github.com" + description: "" + skip_upload: auto + +release: + github: + owner: yindia + name: iteration + draft: false + ids: + - task-darwin + - task-linux + - task-windows + disable: false + extra_files: + - glob: ./dist/*.tar.gz + - glob: ./dist/*.zip diff --git a/2024-10-05_tasks.docx b/2024-10-05_tasks.docx new file mode 100644 index 0000000000000000000000000000000000000000..6d8b87ab70d269f13e192d9a96e866ffbcdcc745 GIT binary patch literal 18272 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 literal 0 HcmV?d00001 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8810f8c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,43 @@ +# syntax=docker/dockerfile:1.2 +FROM cgr.dev/chainguard/go as build + +WORKDIR /work + +# Use build args for cache keys +ARG CACHEBUST=1 + +# Copy only go.mod and go.sum for dependency caching +COPY go.mod go.sum ./ +RUN --mount=type=cache,target=/go/pkg/mod go mod download + +# Copy the rest of the application code +COPY . ./ + +# Build CLI +FROM build as cli +RUN go build -o /usr/local/bin/task-cli ./cli/main.go + +# Build CLI +FROM cgr.dev/chainguard/go as river +RUN go install github.com/riverqueue/river/cmd/river@latest + + +# Build Server +FROM build as server +RUN go build -o /usr/local/bin/task-server ./server/root/main.go + +# Final image for CLI +FROM cgr.dev/chainguard/go as cli-final +COPY --from=cli /usr/local/bin/task-cli /usr/local/bin/task-cli +ENTRYPOINT ["task-cli"] + +# Final image for Server +FROM cgr.dev/chainguard/go as server-final +COPY --from=server /usr/local/bin/task-server /usr/local/bin/task-server +EXPOSE 8080 +ENTRYPOINT ["task-server"] + + +FROM cgr.dev/chainguard/go as river-final +COPY --from=river /root/go/bin/river /usr/local/bin/river +ENTRYPOINT ["river"] \ No newline at end of file diff --git a/Dockerfile.client b/Dockerfile.client new file mode 100644 index 0000000..0aac188 --- /dev/null +++ b/Dockerfile.client @@ -0,0 +1,45 @@ +# Stage 1: Building the Next.js application +FROM node:20.9.0-alpine AS builder + +WORKDIR /app + +# Copy package.json and package-lock.json +COPY clients/dashboard/package*.json ./ + +# Install dependencies with caching +RUN npm config set @buf:registry https://buf.build/gen/npm/v1/ +RUN --mount=type=cache,target=/root/.npm \ + npm install --force + +# Copy the rest of the application code +COPY clients/dashboard . + +# Build the Next.js application +RUN --mount=type=cache,target=/root/.npm \ + npm run build + +# Stage 2: Running the Next.js application +FROM node:20.9.0-alpine AS runner + +WORKDIR /app + +# Copy built assets from the builder stage +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/package.json ./package.json +COPY --from=builder /app/public ./public + +# Set environment variables +ENV NODE_ENV production +ENV NEXT_TELEMETRY_DISABLED 1 + +# Add non-root user +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs +USER nextjs + +# Expose the port the app runs on +EXPOSE 3000 + +# Start the application +CMD ["npm", "start"] \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3c2077e --- /dev/null +++ b/Makefile @@ -0,0 +1,129 @@ +# Project configuration +CLI_NAME := task-cli +SERVER_NAME := task-server +DASHBOARD_NAME := dashboard +BUILD_DIR := bin +CLI_SRC := ./cli +SERVER_SRC := ./server/root +DASHBOARD_SRC := ./clients/dashboard + +# Docker configuration +DOCKER_REPO := ghcr.io/yindia +VERSION := $(shell git describe --tags --always --dirty) +DOCKER_CLI_NAME := task-cli +DOCKER_SERVER_NAME := task-server +DOCKER_DASHBOARD_NAME := task-dashboard + +# Colors for output +NO_COLOR := \033[0m +OK_COLOR := \033[32;01m +ERROR_COLOR := \033[31;01m +WARN_COLOR := \033[33;01m + +.PHONY: all bootstrap deps check-go check-npm build test docker-build docker-push helm-template helm-lint helm-fmt helm-install helm helm-dep-update +all: deps test build + + +deps: check-go check-npm + go mod download + go fmt ./... + go generate ./... + npm config set @buf:registry https://buf.build/gen/npm/v1/ + npm install --force + +check-go: + @which go > /dev/null || (echo "$(ERROR_COLOR)Go is not installed$(NO_COLOR)" && exit 1) + +check-npm: + @which npm > /dev/null || (echo "$(ERROR_COLOR)npm is not installed$(NO_COLOR)" && exit 1) + +# CLI targets +build-cli: deps + @echo "$(OK_COLOR)==> Building the CLI...$(NO_COLOR)" + @CGO_ENABLED=0 go build -v -ldflags="-s -w" -o "$(BUILD_DIR)/$(CLI_NAME)" "$(CLI_SRC)" + +run-cli: build-cli + @echo "$(OK_COLOR)==> Running the CLI...$(NO_COLOR)" + @$(BUILD_DIR)/$(CLI_NAME) --help + +docker-build-cli: + @echo "$(OK_COLOR)==> Building Docker image for CLI...$(NO_COLOR)" + docker build --target cli-final -t $(DOCKER_REPO)/$(DOCKER_CLI_NAME):$(VERSION) . + +docker-push-cli: docker-build-cli + @echo "$(OK_COLOR)==> Pushing Docker image for CLI...$(NO_COLOR)" + docker push $(DOCKER_REPO)/$(DOCKER_CLI_NAME):$(VERSION) + +# Server targets +build-server: deps + @echo "$(OK_COLOR)==> Building the server...$(NO_COLOR)" + @CGO_ENABLED=0 go build -v -ldflags="-s -w" -o "$(BUILD_DIR)/$(SERVER_NAME)" "$(SERVER_SRC)" + +run-server: build-server + @echo "$(OK_COLOR)==> Running the server...$(NO_COLOR)" + @$(BUILD_DIR)/$(SERVER_NAME) + +docker-build-server: + @echo "$(OK_COLOR)==> Building Docker image for server...$(NO_COLOR)" + docker build --target server-final -t $(DOCKER_REPO)/$(DOCKER_SERVER_NAME):$(VERSION) . + +docker-push-server: docker-build-server + @echo "$(OK_COLOR)==> Pushing Docker image for server...$(NO_COLOR)" + docker push $(DOCKER_REPO)/$(DOCKER_SERVER_NAME):$(VERSION) + +# Dashboard targets +build-dashboard: deps + @echo "$(OK_COLOR)==> Building the dashboard...$(NO_COLOR)" + npm run build + +run-dashboard: deps + @echo "$(OK_COLOR)==> Running the dashboard...$(NO_COLOR)" + npm run dev + +docker-build-dashboard: + @echo "$(OK_COLOR)==> Building Docker image for dashboard...$(NO_COLOR)" + docker build -f Dockerfile.client -t $(DOCKER_REPO)/$(DOCKER_DASHBOARD_NAME):$(VERSION) . + +docker-push-dashboard: docker-build-dashboard + @echo "$(OK_COLOR)==> Pushing Docker image for dashboard...$(NO_COLOR)" + docker push $(DOCKER_REPO)/$(DOCKER_DASHBOARD_NAME):$(VERSION) + +# Test targets +test: deps + @echo "$(OK_COLOR)==> Running the unit tests$(NO_COLOR)" + @go test -race -tags unit -cover ./... + cd $(DASHBOARD_SRC) && npm test + +# Combined targets +build: build-cli build-server build-dashboard +docker-build: docker-build-cli docker-build-server docker-build-dashboard +docker-push: docker-push-cli docker-push-server docker-push-dashboard + +# Helm targets +helm-template: + @echo "$(OK_COLOR)==> Generating Helm templates...$(NO_COLOR)" + helm template charts/task + +helm-lint: + @echo "$(OK_COLOR)==> Linting Helm charts...$(NO_COLOR)" + helm lint charts/task + +helm-fmt: + @echo "$(OK_COLOR)==> Formatting Helm charts...$(NO_COLOR)" + helm lint --strict charts/task + +helm-install: + @echo "$(OK_COLOR)==> Installing Helm charts...$(NO_COLOR)" + helm install my-release charts/task + +helm-dep-update: + @echo "$(OK_COLOR)==> Updating Helm dependencies...$(NO_COLOR)" + helm dependency update ./charts/task/ + +helm: helm-dep-update helm-template helm-lint helm-fmt + @echo "$(OK_COLOR)==> Helm template, lint, and format completed.$(NO_COLOR)" + +bootstrap: + curl -fsSL https://pixi.sh/install.sh | bash + brew install bufbuild/buf/buf + pixi shell diff --git a/README.md b/README.md new file mode 100644 index 0000000..0c21132 --- /dev/null +++ b/README.md @@ -0,0 +1,621 @@ +# Task Service - Case Study + + + Task Service + + +## Table of Contents +- [Quick Start](#quick-start) +- [Manual Setup](#manual-setup) +- [Project Structure](#project-structure) +- [Architecture](#architecture) +- [Database Schema](#database-schema) +- [API Documentation](#api-documentation) +- [CLI Usage](#cli-usage) +- [Additional Information](#additional-information) +- [Plugin Model](#plugin-model) +- [Testing in Kubernetes with Kind](#testing-in-kubernetes-with-kind) +- [Improvement](https://github.com/yindia/iteration/tree/postgres?tab=readme-ov-file#future-improvements) + +## Quick Start +To quickly get started with the Task Service, use the following command: + +```bash +make bootstrap + +docker-compose -f docker-compose.demo.yaml up +``` + +This will start all the necessary services, including the server, database, and worker. + +## Manual Setup + +For a more detailed setup process, follow these steps: + +### 1. Development Environment Setup +Install Pixi and activate the shell: +```bash +make bootstrap + +# Run Database +docker-compose up -d + +# Install river +go install github.com/riverqueue/river/cmd/river@latest + +# Run River migration (It will create the river resource in the database) +river migrate-up --database-url "postgres://admin:admin@127.0.0.1:5432/tasks?sslmode=disable" +``` + + +### 2. Server (Control Plane) +Start the server: +```bash +make run-server +``` +Access at https://127.0.0.1:8080 + +### 3. CLI Tool +Build and test: +```bash +make build-cli +./bin/task-cli --help +``` + +### 4. Dashboard Setup +Install dependencies and build: +```bash +npm install +npm run dev +``` +Access at https://127.0.0.1:3000 + +Screenshot 2024-09-29 at 4 22 37 PM + +### 5. Worker (Data Plane) +Start worker instances: +```bash +./bin/task-cli serve -n 10 +``` + +## Project Structure +``` +task/ +├── cmd/ +│ ├── cli/ # CLI for task management +│ └── server/ # Server entry point +├── pkg/ +│ ├── config/ # Configuration management +│ ├── gen/ # GRPC generated code +│ ├── plugins/ # Plugin model +│ ├── worker/ # Worker code +│ └── x/ # Utility functions +├── idl/ +│ └── proto/ # Protocol buffer definitions +├── clients/ +│ └── dashboard/ # NextJS Dashboard +├── charts/ +│ └── task/ # Helm charts for deployment +├── server/ +│ ├── repository/ # Database ORM +│ └── root/ # Server Root +│ └── route/ # All Server Routes +└── docs/ # Documentation files +``` + +## Architecture + +The Task Service follows a distributed architecture with separate components for the control plane and data plane. Here's a high-level overview of the system: + +```mermaid +graph TD + %% Clients + A[Dashboard Client] -->|Sends Request| B(Server) + C[CLI Client] -->|Sends Request| B(Server) + + %% Server and its connections + B(Server) -->|Reads/Writes| D[(PostgreSQL Database)] + B(Server) -->|Publishes Message| E(RiverQueue) + + %% RabbitMQ and Worker + E(RiverQueue) -->|Sends Message| F(Worker) + F(Worker) -->|Consumes Data| G[Executes Work] + + %% Optional back-and-forth communication if needed + F(Worker) -->|Update Status| B[(Server)] +``` + +This architecture allows for: +- Separation of concerns between the control plane (server) and data plane (workers) +- Scalability of worker nodes to handle increased workloads +- Asynchronous task execution through message queuing +- Real-time status updates from workers to the server + + +### Database Operations + +The server interacts with the database for persistent storage of tasks and their history. Here's a summary of the database operations: + +1. **Read Operations** + - Get Task by ID + - Purpose: Retrieve details of a specific task + - Frequency: On-demand, triggered by API requests + - List All Tasks + - Purpose: Retrieve a list of all tasks + - Frequency: On-demand, typically for dashboard or reporting + - List Task History + - Purpose: Retrieve the status change history of a specific task + - Frequency: On-demand, for detailed task analysis + +2. **Write Operations** + - Create New Task + - Purpose: Store a newly created task + - Frequency: Each time a new task is submitted + - Update Task Status + - Purpose: Modify the status of an existing task + - Frequency: As task states change (e.g., from queued to running to completed) + - Create Task History Entry + - Purpose: Log task status changes and creation events + - Frequency: On task creation and each status change + + +### Database Schema + +The Task Service uses a PostgreSQL database to store task and task history information. Below is an Entity-Relationship Diagram (ERD) representing the database schema: + +```mermaid +erDiagram + %% Task Model + TASK { + int id PK + string name + int type + int status + jsonb payload + int retries + int priority + timestamp created_at + } + + %% TaskHistory Model + TASK_HISTORY { + int id PK + int task_id FK + int status + string details + timestamp created_at + } + + %% Relationships + TASK ||--o{ TASK_HISTORY : has + + %% Indexes (described as comments) + %% Indexes for TASK + %% - idx_type_status (type, status) + %% - idx_created_at (created_at) + %% - idx_status_created_at (status, created_at) + + %% Indexes for TASK_HISTORY + %% - idx_task_id_created_at (task_id, created_at) +``` + +Note: Ideally, we should create separate tables for tasks 📝 and task executions ⚙️. When a task is created, it should be added to the task table. Upon triggering an execution, a corresponding entry should be created in the execution table, and the execution data should be published to the PostgreSQL queue for processing 📬. This way, the task status remains unchanged, and only the execution status is updated in the execution table ✅. + + +### Table Descriptions + +1. **TASK** + - Stores information about individual tasks + - `id`: Unique identifier for the task (Primary Key) + - `name`: Name of the task + - `type`: Type of the task (e.g., send_email, run_query) + - `status`: Current status of the task (e.g., pending, running, completed) + - `payload`: JSON object containing task-specific parameters + - `retries`: Number of retry attempts for the task + - `priority`: Priority level of the task + - `created_at`: Timestamp of task creation + +2. **TASK_HISTORY** + - Tracks the history of status changes for tasks + - `id`: Unique identifier for the history entry (Primary Key) + - `task_id`: Foreign Key referencing the TASK table + - `status`: Status of the task at the time of the history entry + - `details`: Additional details about the status change + - `created_at`: Timestamp of the history entry creation + +### Relationships + +- One TASK can have many TASK_HISTORY entries (one-to-many relationship) + +### Indexes + +To optimize query performance, the following indexes are implemented: + +1. **TASK table** + - `idx_type_status`: Composite index on `type` and `status` columns + - `idx_created_at`: Index on `created_at` column + - `idx_status_created_at`: Composite index on `status` and `created_at` columns + +2. **TASK_HISTORY table** + - `idx_task_id_created_at`: Composite index on `task_id` and `created_at` columns + +These indexes improve the efficiency of common queries such as filtering tasks by type and status, sorting by creation time, and retrieving task history. + + +### Worker/Data Plane Process + +The worker process follows a specific flow for task execution and error handling. Here's a detailed view of the worker's operation: + +```mermaid +graph TD + A[Receive Message] --> B{Update Status: RUNNING} + B -->|Success| C[Run Task] + B -->|Failure| D[Log Error] + D --> K[Move to Next Message] + + C --> E{Task Execution} + E -->|Success| F[Update Status: SUCCEEDED] + E -->|Failure| G[Retry Logic] + + G --> H{Retry Attempt <= 3?} + H -->|Yes| I[Backoff] + I --> J[Update Status: RETRYING] + J --> C + H -->|No| K[Update Status: FAILED] + + F --> L[Move to Next Message] + K --> L +``` + +Reconciliation Job (Run in every 10 minutes) as background job + +```mermaid +graph TD + %% Reconciliation Job Flow + subgraph Reconciliation Job + M[Start Reconciliation Job] --> N[Get List of Stuck Jobs] + N --> O{Jobs Found?} + O -->|Yes| P[Update Status: Queued] + P --> Q[Enqueue Message to River Queue] + O -->|No| R[End Reconciliation Job] + Q --> R + end +``` + +## API Documentation +- [Proto Docs](https://buf.build/evalsocket/cloud) +- [Studio](https://buf.build/studio/evalsocket/cloud/cloud.v1.TaskManagementService/CreateTask) + +## CLI Usage + +### Task Management + +The Task Service CLI provides several commands to manage tasks. Here's a detailed overview of each command and its available flags: + +#### Create a Task + +Create a new task with the specified name, type, and parameters. + +```bash +task-cli task create [task name] --type [task type] --parameter [key=value] +``` + +Flags: +- `--type`, `-t`: Type of the task (e.g., send_email, run_query) +- `--parameter`, `-p`: Additional parameters for the task as key=value pairs (can be used multiple times) + +Example: +```bash +task-cli task create "Send Newsletter" --type send_email --parameter recipient=user@example.com --parameter subject="Weekly Update" +``` + +#### Get Task Details + +Retrieve and display the details of a specific task by its ID. + +```bash +task-cli task get --id [task ID] [flags] +``` + +Flags: +- `--id`, `-i`: ID of the task (required) +- `--output`, `-o`: Output format (table, json, yaml) (default: "table") + +Example: +```bash +task-cli task get --id 123 --output json +``` + +#### Get Task History + +Retrieve and display the history of a specific task by its ID. + +```bash +task-cli history --id [task ID] [flags] +``` + +Flags: +- `--id`, `-i`: ID of the task (required) +- `--output`, `-o`: Output format (table, json, yaml) (default: "table") + +Example: +```bash +task-cli history --id 123 --output yaml +``` + +#### List All Tasks + +Retrieve and display a list of all tasks. + +```bash +task-cli task list [flags] +``` + +Flags: +- `--output`, `-o`: Output format (table, json, yaml) (default: "table") +- `--pageNumber`, `-n`: Page number for pagination (default: 1) +- `--pageCount`, `-c`: Number of items per page (default: 30) + +Examples: +```bash +task-cli task list +task-cli task list --output json +task-cli task list --pageNumber 2 --pageCount 20 +``` + +#### Task Status + +Retrieve the status counts of all tasks in the system. + +```bash +task-cli task status +``` + +Aliases: `s`, `stat` + +Example: +```bash +task-cli task status +task-cli task s +``` + +This command will display the count of tasks for each status (e.g., PENDING, RUNNING, SUCCEEDED, FAILED). + +#### End-to-End Testing + +Run end-to-end tests against the system to verify its functionality. + +```bash +task-cli end2end [flags] +``` + +Flags: +- `--num-tasks`, `-n`: Number of tasks to create for the test (default: 100, max: 100) + +Example: +```bash +task-cli end2end +task-cli end2end -n 50 +``` + +This command will: +1. Create the specified number of tasks (default 100) +2. Monitor the tasks' completion status for up to 3 minutes +3. Display progress every 5 seconds +4. Report the final result (success or partial completion) + +The test creates a mix of "run_query" and "send_email" task types to simulate a realistic workload. + + +### Global Flags + +The following flag is available for all task commands: + +- `--log-level`: Set the logging level (default: "error") +- `--address`: Control Plane Address (default: "http://127.0.0.1:8080") + +Example: +```bash +task-cli task list --log-level debug +``` + +### Output Formats + +All commands that display task information support three output formats: + +- `table`: Displays the information in a formatted table (default) +- `json`: Outputs the data in JSON format +- `yaml`: Outputs the data in YAML format + +Use the `--output` or `-o` flag to specify the desired format. + +## Additional Information +- Control plane (server) manages task creation, scheduling, and status updates +- Data plane (workers) executes tasks (Currently part of same binary) +- RiverQueue used for communication between control and data planes using postgres as queue backend +- Explore the UI or CLI to create and manage tasks + +## Plugin Model + +The Task Service uses a plugin-based architecture to allow for extensibility and customization of task execution. This model enables users to create their own task types and implement custom logic for task execution. + +### How It Works + +1. **Plugin Interface**: All plugins must implement the `Plugin` interface defined in `@pkg/plugins/plugins.go`. This interface requires a `Run` method: + + ```go + type Plugin interface { + Run(parameters map[string]string) error + } + ``` + +2. **Plugin Registration**: Plugins are registered in the `NewPlugin` function in `@pkg/plugins/plugins.go`. This function acts as a factory, creating the appropriate plugin based on the task type: + + ```go + func NewPlugin(pluginType string) (Plugin, error) { + switch pluginType { + case email.PLUGIN_NAME: + return &email.Email{}, nil + case query.PLUGIN_NAME: + return &query.Query{}, nil + // Add more plugin types here + default: + return nil, fmt.Errorf("unknown plugin type: %s", pluginType) + } + } + ``` + +3. **Custom Plugin Implementation**: Users can create their own plugins by implementing the `Plugin` interface. For example, the `Email` plugin in `@pkg/email/email.go`: + + ```go + var PLUGIN_NAME = "send_email" + type Email struct {} + + func (e *Email) Run(parameters map[string]string) error { + // Implementation of email sending logic + return nil + } + ``` + +4. **Task Execution**: When a task is executed, the system uses the `NewPlugin` function to create the appropriate plugin based on the task type. It then calls the `Run` method of the plugin, passing any necessary parameters. + +### Creating a New Plugin + +To create a new plugin: + +1. Create a new package in the `@pkg/plugins` directory for your plugin. +2. Implement the `Plugin` interface in your new package. +3. Add your plugin to the `NewPlugin` function in `@pkg/plugins/plugins.go`. + +This modular approach allows for easy extension of the Task Service with new task types and functionalities. + + +## Testing in Kubernetes with Kind + +This section guides you through setting up and testing the Task Service in a local Kubernetes cluster using Kind (Kubernetes in Docker) and Helm charts. + +### Prerequisites + +- [Docker](https://docs.docker.com/get-docker/) +- [Kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) +- [kubectl](https://kubernetes.io/docs/tasks/tools/) +- [Helm](https://helm.sh/docs/intro/install/) + +### Setup + +1. Create a Kind cluster: + +```bash +kind create cluster --name task-service +``` + +2. Set kubectl context to the new cluster: + +```bash +kubectl cluster-info --context kind-task-service +``` + +3. Add the necessary Helm repositories: + +```bash +make helm +``` + +### Deploy Task Service + +Install the Task Service Helm chart: + +```bash +helm install task-service ./charts/task -n task +``` + +### Verify Deployment + +Check that all pods are running: + +```bash +kubectl get pods +``` + +## Port Forward +``` +kubectl port-forward service/task 80 -n task +``` + +### Access the Service + +1. Port-forward the Task Service: + +```bash +kubectl port-forward -n task svc/task 8080:80 +``` + +2. Access the service at `http://127.0.0.1:8080` + +3. Use CLI to verify the connection: +```bash +./bin/task-cli task l --address http://127.0.0.1:8080 +``` + +### Clean Up + +To delete the Kind cluster and all resources: + +```bash +kind delete cluster --name task-service +``` + +This setup allows you to test the entire Task Service stack, including the server, workers, and dependencies, in a local Kubernetes environment. It's an excellent way to validate the Helm charts and ensure everything works together as expected in a Kubernetes setting. + + +## Future Improvements + +As we continue to evolve the Task Service, we are exploring several enhancements to improve its scalability, reliability, and management. + +### Kubernetes-Native Task Execution + +We are considering leveraging Kubernetes Custom Resource Definitions (CRDs) and custom controllers to manage task execution. This approach would enable us to fully utilize Kubernetes' scheduling and scaling capabilities. + +#### High-Level Architecture + +```mermaid +graph TD + %% Clients + A[Dashboard Client] -->|Sends Request| B(Server) + C[CLI Client] -->|Sends Request| B(Server) + + %% Control Plane + subgraph Control Plane + B(Server) -->|Reads/Writes| D[(PostgreSQL Database)] + end + + %% Data Plane + subgraph Data Plane + E[Agent] -->|Initiates Connection| B[Server] + E -->|Creates CRD| H[CRD] + F[Controller] -->|Watches CRD| H + F -->|Creates Pod for Task| I[Pod] + I -->|Executes Task| J[Task Execution] + F -->|Sends Status Update| B + end +``` + +In this architecture: + +1. Our agent initiates a streaming connection with the control plane and listens for events. +2. When a new task is created, the control plane generates an event for the agent. +3. Upon receiving the event, the agent creates a Custom Resource Definition (CRD) for the task in Kubernetes. +4. A custom Worker Controller watches for these CRDs and creates pods to execute the tasks. +5. Each task runs in its own pod, allowing for improved isolation and resource management. +6. The Worker Controller monitors task execution and sends status updates back to the server. + + +#### Design Advantages + +- **Separation of Concerns**: The customer does not need to open a port; our agent initiates the connection, and only the agent has permission to create resources inside the Data Plane. +- **Single Point of Setup**: Only the agent is required to set up the Data Plane, creating the necessary resources such as the controller, CRD, and other components. +- **Multiple Data Planes**: Customers can run multiple Data Planes with one Control Plane based on their requirements (from bare metal to any cloud). In the future, we can add functionality to route tasks to specific Data Planes as needed. +- **Security**: No sensitive information is stored in the Control Plane; we only retain metadata, ensuring enhanced security. +- **Infinite Scalability**: The architecture supports scaling as needed to accommodate varying workloads. +- **Co-location Flexibility**: Customers can run both the Data Plane and Control Plane together inside their VPC for easier management. +- **Secure Storage**: All input parameters are stored as S3 objects, with only references to these objects kept in the metadata, optimizing storage usage. diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 0000000..702964b --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,31 @@ +version: v1 +managed: + enabled: true + go_package_prefix: + default: task/pkg/gen + except: + - buf.build/envoyproxy/protoc-gen-validate + - buf.build/bufbuild/protovalidate +plugins: + - plugin: buf.build/connectrpc/go:v1.11.1 + out: pkg/gen/ + opt: + - paths=source_relative + - plugin: buf.build/protocolbuffers/go + out: pkg/gen/ + opt: + - paths=source_relative + - plugin: buf.build/community/pseudomuto-doc:v1.5.1 + out: pkg/gen + - plugin: buf.build/grpc-ecosystem/openapiv2:v2.17.1 + out: pkg/gen + - plugin: buf.build/connectrpc/es:v1.5.0 + out: clients/dashboard/src + opt: + - target=ts + - import_extension=none + - plugin: buf.build/bufbuild/es:v1.10.0 + out: clients/dashboard/src + opt: + - target=ts + - import_extension=none diff --git a/buf.work.yaml b/buf.work.yaml new file mode 100644 index 0000000..2e8d049 --- /dev/null +++ b/buf.work.yaml @@ -0,0 +1,3 @@ +version: v1 +directories: + - idl \ No newline at end of file diff --git a/charts/task/Chart.lock b/charts/task/Chart.lock new file mode 100644 index 0000000..8e6c640 --- /dev/null +++ b/charts/task/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 15.5.36 +digest: sha256:f6a74e7aa9ed427d76a30ce878d92d3e18596fc390df3e132db17228ac1e4ce9 +generated: "2024-09-30T05:55:23.327217+05:30" diff --git a/charts/task/Chart.yaml b/charts/task/Chart.yaml new file mode 100644 index 0000000..46278d4 --- /dev/null +++ b/charts/task/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: task +description: A Helm chart for deploying the Task application +type: application +version: 0.1.0 +appVersion: "1.0.0" +keywords: + - task + - application +maintainers: + - name: Yuvraj Yadav + email: evalsocket@gmail.com +dependencies: + - name: postgresql + alias: postgresql + version: "*" + repository: "https://charts.bitnami.com/bitnami" + condition: postgresql.enabled diff --git a/charts/task/README.md b/charts/task/README.md new file mode 100644 index 0000000..ca7e7ca --- /dev/null +++ b/charts/task/README.md @@ -0,0 +1,79 @@ +# task + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.0.0](https://img.shields.io/badge/AppVersion-1.0.0-informational?style=flat-square) + +A Helm chart for deploying the Task application + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| Yuvraj Yadav | | | + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| https://charts.bitnami.com/bitnami | postgres(postgresql) | * | +| https://charts.bitnami.com/bitnami | rabbitmq(rabbitmq) | * | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `true` | | +| autoscaling.maxReplicas | int | `2` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| env[0].name | string | `"DEMO_ENV_PROP"` | | +| env[0].value | string | `"mydemoenvproperty"` | | +| env[1].name | string | `"ENV_PROP"` | | +| env[1].value | string | `"justenvprop"` | | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"evalsocket/task"` | | +| image.tag | string | `"b3e10b3-dirty"` | | +| imagePullSecrets | list | `[]` | | +| ingress.annotations | object | `{}` | | +| ingress.enabled | bool | `false` | | +| ingress.hosts[0].host | string | `"task.local"` | | +| ingress.hosts[0].paths | list | `[]` | | +| ingress.tls | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| port.containerPort | int | `8080` | | +| postgresql.global.auth.database | string | `"tasks"` | | +| postgresql.global.auth.password | string | `"admin"` | | +| postgresql.global.auth.username | string | `"admin"` | | +| rabbitmq.auth.password | string | `"user"` | | +| rabbitmq.auth.username | string | `"user"` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | string | `"500m"` | | +| resources.limits.memory | string | `"750Mi"` | | +| resources.requests.cpu | string | `"500m"` | | +| resources.requests.memory | string | `"750Mi"` | | +| secret.data.DB_DATABASE | string | `"tasks"` | | +| secret.data.DB_HOST | string | `"task-postgres"` | | +| secret.data.DB_PASSWORD | string | `"admin"` | | +| secret.data.DB_POOL_MAX_CONNS | string | `"30"` | | +| secret.data.DB_PORT | string | `"5432"` | | +| secret.data.DB_SSL_MODE | string | `"disable"` | | +| secret.data.DB_USERNAME | string | `"admin"` | | +| secret.data.RABBITMQ_HOST | string | `"task-rabbitmq"` | | +| secret.data.RABBITMQ_PASSWORD | string | `"user"` | | +| secret.data.RABBITMQ_USER | string | `"user"` | | +| secret.data.RABBIT_MQ_QUEUE | string | `"tasks"` | | +| secret.data.SERVER_PORT | string | `"8080"` | | +| securityContext | object | `{}` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `false` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/task/templates/_helpers.tpl b/charts/task/templates/_helpers.tpl new file mode 100644 index 0000000..16e5d37 --- /dev/null +++ b/charts/task/templates/_helpers.tpl @@ -0,0 +1,135 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "task.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "task.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "task.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "task.labels" -}} +helm.sh/chart: {{ include "task.chart" . }} +{{ include "task.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "task.selectorLabels" -}} +app.kubernetes.io/name: {{ include "task.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +CLI labels +*/}} +{{- define "task.cli.labels" -}} +{{ include "task.labels" . }} +app.kubernetes.io/component: cli +{{- end }} + +{{/* +CLI selector labels +*/}} +{{- define "task.cli.selectorLabels" -}} +{{ include "task.selectorLabels" . }} +app.kubernetes.io/component: cli +{{- end }} + +{{/* +Server labels +*/}} +{{- define "task.server.labels" -}} +{{ include "task.labels" . }} +app.kubernetes.io/component: server +{{- end }} + +{{/* +Server selector labels +*/}} +{{- define "task.server.selectorLabels" -}} +{{ include "task.selectorLabels" . }} +app.kubernetes.io/component: server +{{- end }} + +{{/* +Dashboard labels +*/}} +{{- define "task.dashboard.labels" -}} +{{ include "task.labels" . }} +app.kubernetes.io/component: dashboard +{{- end }} + +{{/* +Dashboard selector labels +*/}} +{{- define "task.dashboard.selectorLabels" -}} +{{ include "task.selectorLabels" . }} +app.kubernetes.io/component: dashboard +{{- end }} + +{{/* +Selector labels (immutable) +*/}} +{{- define "task.immutableSelectorLabels" -}} +app.kubernetes.io/name: {{ include "task.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Server selector labels (immutable) +*/}} +{{- define "task.server.immutableSelectorLabels" -}} +{{ include "task.immutableSelectorLabels" . }} +app.kubernetes.io/component: server +{{- end }} + +{{/* +Dashboard selector labels (immutable) +*/}} +{{- define "task.dashboard.immutableSelectorLabels" -}} +{{ include "task.immutableSelectorLabels" . }} +app.kubernetes.io/component: dashboard +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "task.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "task.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/task/templates/dashboard.yaml b/charts/task/templates/dashboard.yaml new file mode 100644 index 0000000..eed4771 --- /dev/null +++ b/charts/task/templates/dashboard.yaml @@ -0,0 +1,58 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "task.fullname" . }}-dashboard + labels: + {{- include "task.dashboard.labels" . | nindent 4 }} +spec: +{{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} +{{- end }} + selector: + matchLabels: + {{- include "task.dashboard.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "task.dashboard.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "task.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}-dashboard:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 3000 + protocol: TCP + resources: + {{- toYaml .Values.resources | nindent 12 }} + env: + {{- toYaml .Values.env | nindent 12 }} + envFrom: + - secretRef: + name: {{ include "task.fullname" . }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} \ No newline at end of file diff --git a/charts/task/templates/deployment.yaml b/charts/task/templates/deployment.yaml new file mode 100644 index 0000000..d1c25a0 --- /dev/null +++ b/charts/task/templates/deployment.yaml @@ -0,0 +1,71 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "task.fullname" . }}-server + labels: + {{- include "task.server.labels" . | nindent 4 }} +spec: +{{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} +{{- end }} + selector: + matchLabels: + {{- include "task.server.immutableSelectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "task.server.labels" . | nindent 8 }} + app.kubernetes.io/component: server + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "task.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}-server:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 8080 + resources: + {{- toYaml .Values.resources | nindent 12 }} + env: + {{- toYaml .Values.env | nindent 12 }} + envFrom: + - secretRef: + name: {{ include "task.fullname" . }} + + initContainers: + - name: init-command + image: "evalsocket/river:latest" + command: ["river"] + args: + - migrate-up + - --database-url + - postgres://$(DB_USERNAME):$(DB_PASSWORD)@$(DB_HOST):$(DB_PORT)/$(DB_DATABASE)?sslmode=$(DB_SSL_MODE) + envFrom: + - secretRef: + name: {{ include "task.fullname" . }} + + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} \ No newline at end of file diff --git a/charts/task/templates/hpa.yaml b/charts/task/templates/hpa.yaml new file mode 100644 index 0000000..3c75643 --- /dev/null +++ b/charts/task/templates/hpa.yaml @@ -0,0 +1,30 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "task.fullname" . }} + labels: + {{- include "task.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "task.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas | default 1 }} + maxReplicas: {{ .Values.autoscaling.maxReplicas | default 100 }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/charts/task/templates/secret.yaml b/charts/task/templates/secret.yaml new file mode 100644 index 0000000..8f88afe --- /dev/null +++ b/charts/task/templates/secret.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "task.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "task.labels" . | nindent 4 }} +type: Opaque +data: + {{- range $key, $value := .Values.secret.data }} + {{ $key }}: {{ $value | b64enc | quote }} + {{- end }} \ No newline at end of file diff --git a/charts/task/templates/service.yaml b/charts/task/templates/service.yaml new file mode 100644 index 0000000..f74fa5e --- /dev/null +++ b/charts/task/templates/service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "task.fullname" . }} + labels: + {{- include "task.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.port.containerPort }} + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "task.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: server \ No newline at end of file diff --git a/charts/task/templates/serviceaccount.yaml b/charts/task/templates/serviceaccount.yaml new file mode 100644 index 0000000..6e3fbe2 --- /dev/null +++ b/charts/task/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "task.serviceAccountName" . }} + labels: + {{- include "task.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/task/values.yaml b/charts/task/values.yaml new file mode 100644 index 0000000..02a5a36 --- /dev/null +++ b/charts/task/values.yaml @@ -0,0 +1,120 @@ +# Default values for chartexample. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: evalsocket/task + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "e95c995" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: + {} + # fsGroup: 2000 + +securityContext: + {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + annotations: + {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: task.local + paths: [] + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +#resources: {} +# We usually recommend not to specify default resources and to leave this as a conscious +# choice for the user. This also increases chances charts run on environments with little +# resources, such as Minikube. If you do want to specify resources, uncomment the following +# lines, adjust them as necessary, and remove the curly braces after 'resources:'. +resources: + limits: + cpu: 500m + memory: 750Mi + requests: + cpu: 500m + memory: 750Mi + +autoscaling: + enabled: true + minReplicas: 1 + maxReplicas: 2 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +## newly added on top of default values provided by helm create. + +port: + containerPort: 8080 + +env: [] + +secret: + data: + SERVER_PORT: "8080" + WORKER_COUNT: 100 + SERVER_ENDPOINT: "http://task.task.svc.cluster.local" + NEXT_PUBLIC_SERVER_ENDPOINT: "http://task.task.svc.cluster.local" + DB_HOST: "task-postgresql" + DB_PORT: "5432" + DB_DATABASE: "task" + DB_USERNAME: "admin" + DB_PASSWORD: "notAsSecretU5erPa55word" + DB_SSL_MODE: "disable" + DB_POOL_MAX_CONNS: "30" + +postgresql: + enabled: true + global: + postgresql: + auth: + postgresPassword: "SuperSecretPGAdminPa55word!" + username: "admin" + password: "notAsSecretU5erPa55word" + database: "task" + primary: + persistence: + enabled: false + initdb: + user: "postgres" + password: "SuperSecretPGAdminPa55word!" diff --git a/cli/cmd/end2end.go b/cli/cmd/end2end.go new file mode 100644 index 0000000..d323b5e --- /dev/null +++ b/cli/cmd/end2end.go @@ -0,0 +1,195 @@ +package cmd + +import ( + "context" + "fmt" + cloudv1 "task/pkg/gen/cloud/v1" + v1 "task/pkg/gen/cloud/v1" + "task/pkg/gen/cloud/v1/cloudv1connect" + "task/pkg/x" + "time" + + "connectrpc.com/connect" + "github.com/spf13/cobra" +) + +var ( + end2endCmd = &cobra.Command{ + Use: "end2end", + Short: "Run end-to-end tests for the system", + Long: `This command executes a series of end-to-end tests to verify the entire system's functionality. +It creates a specified number of tasks and monitors their completion status for up to 3 minutes.`, + RunE: func(cmd *cobra.Command, args []string) error { + return runEnd2EndTests() + }, + } + numTasks int +) + +func init() { + rootCmd.AddCommand(end2endCmd) + end2endCmd.Flags().IntVarP(&numTasks, "count", "n", 300, "Number of tasks to create (default 100, max 100)") +} + +func runEnd2EndTests() error { + fmt.Println("Starting end-to-end tests...") + client, err := x.CreateClient(address) + if err != nil { + return fmt.Errorf("failed to create client: %w", err) + } + + initialStatus, err := checkInitialStatus(client) + if err != nil { + return fmt.Errorf("failed to check initial status: %w", err) + } + + if err := createTasks(client); err != nil { + return fmt.Errorf("failed to create tasks: %w", err) + } + + return monitorTasks(client, initialStatus) +} + +func checkInitialStatus(client cloudv1connect.TaskManagementServiceClient) (map[v1.TaskStatusEnum]int64, error) { + fmt.Println("Checking initial task status...") + response, err := checkTaskStatus(client) + if err != nil { + return nil, err + } + + initialStatus := make(map[v1.TaskStatusEnum]int64) + for status, count := range response.Msg.StatusCounts { + initialStatus[v1.TaskStatusEnum(status)] = count + } + + fmt.Printf("Initial status: %d queued, %d running, %d succeeded, %d failed\n", + initialStatus[v1.TaskStatusEnum_QUEUED], + initialStatus[v1.TaskStatusEnum_RUNNING], + initialStatus[v1.TaskStatusEnum_SUCCEEDED], + initialStatus[v1.TaskStatusEnum_FAILED]) + return initialStatus, nil +} + +func createTasks(client cloudv1connect.TaskManagementServiceClient) error { + fmt.Printf("Creating %d tasks...\n", numTasks) + createdTasks := 0 + + for i := 0; i < numTasks; i++ { + taskType := getTaskType(i) + if err := createSingleTask(client, i, taskType); err != nil { + return fmt.Errorf("failed to create task %d: %w", i+1, err) + } + createdTasks++ + + if (i+1)%50 == 0 || i+1 == numTasks { + fmt.Printf("Progress: Created %d/%d tasks\n", createdTasks, numTasks) + } + } + + fmt.Printf("Successfully created %d tasks. Now monitoring...\n", createdTasks) + return nil +} + +func getTaskType(index int) string { + if index < numTasks/2 { // 50% of tasks will be run_query + return "run_query" + } + return "send_email" // The remaining 50% will be send_email +} + +func createSingleTask(client cloudv1connect.TaskManagementServiceClient, index int, taskType string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := client.CreateTask(ctx, connect.NewRequest(&v1.CreateTaskRequest{ + Name: fmt.Sprintf("Task %d", index+1), + Description: fmt.Sprintf("Description for Task %d", index+1), + Type: taskType, + Payload: &v1.Payload{ + Parameters: map[string]string{ + "test": fmt.Sprintf("test_%d", index+1), + }, + }, + })) + + if err != nil { + return fmt.Errorf("failed to create task %d: %w", index+1, err) + } + return nil +} + +func monitorTasks(client cloudv1connect.TaskManagementServiceClient, initialStatus map[v1.TaskStatusEnum]int64) error { + if numTasks > 1000 { + return fmt.Errorf("number of tasks (%d) exceeds the maximum limit of 1000", numTasks) + } + + fmt.Println("Monitoring task completion...") + startTime := time.Now() + duration := 3 * time.Minute + ticker := time.NewTicker(5 * time.Second) + defer ticker.Stop() + + initialTotal := int64(0) + for _, count := range initialStatus { + initialTotal += count + } + + for { + response, err := checkTaskStatus(client) + if err != nil { + return err + } + + currentTotal := int64(0) + completed := int64(0) + failed := int64(0) + inProgress := int64(0) + + for status, count := range response.Msg.StatusCounts { + currentTotal += count + switch v1.TaskStatusEnum(status) { + case v1.TaskStatusEnum_QUEUED, v1.TaskStatusEnum_RUNNING: + inProgress += count + case v1.TaskStatusEnum_SUCCEEDED: + completed += count + case v1.TaskStatusEnum_FAILED: + failed += count + } + } + + newTasks := currentTotal - initialTotal + + fmt.Printf("Progress: %d new tasks, %d succeeded, %d failed, %d in progress\n", + newTasks, completed, failed, inProgress) + + if completed+failed == int64(numTasks) { + fmt.Printf("All tasks finished in %s. %d succeeded, %d failed.\n", + time.Since(startTime).Round(time.Second), completed, failed) + return nil + } + + if time.Since(startTime) > duration { + fmt.Printf("Test completed after %s. %d succeeded, %d failed, %d still in progress.\n", + duration, completed, failed, inProgress) + return nil + } + + <-ticker.C // Wait for the next tick + } +} +func checkTaskStatus(client cloudv1connect.TaskManagementServiceClient) (*connect.Response[cloudv1.GetStatusResponse], error) { + resp, err := client.GetStatus(context.Background(), connect.NewRequest(&v1.GetStatusRequest{})) + if err != nil { + return nil, fmt.Errorf("error retrieving task status counts: %w", err) + } + + return resp, nil +} + +// Add this helper function at the end of the file +func min(a, b int64) int64 { + if a < b { + return a + } + return b +} diff --git a/cli/cmd/history.go b/cli/cmd/history.go new file mode 100644 index 0000000..11485f2 --- /dev/null +++ b/cli/cmd/history.go @@ -0,0 +1,96 @@ +package cmd + +import ( + "context" + "fmt" + "os" + + v1 "task/pkg/gen/cloud/v1" + "task/pkg/x" + + "connectrpc.com/connect" + "github.com/olekukonko/tablewriter" + "github.com/spf13/cobra" +) + +// historyCmd represents the history command for tasks +var historyCmd = &cobra.Command{ + Use: "history --id ", + Aliases: []string{"h", "log"}, + Short: "Get history of a specific task", + Long: `Retrieve and display the history of a specific task by its ID. +This command shows all status changes and events related to the task over time. +You can specify the output format as table (default), json, or yaml.`, + Example: ` task history --id 123 + task history --id 456 --output json + task h -i 789 -o yaml`, + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + id, err := cmd.Flags().GetInt64("id") + if err != nil { + fmt.Fprintf(os.Stderr, "Error: Failed to get 'id' flag: %v\n", err) + os.Exit(1) + } + if id <= 0 { + fmt.Fprintln(os.Stderr, "Error: --id flag is required and must be a positive integer") + cmd.Usage() + os.Exit(1) + } + output, err := cmd.Flags().GetString("output") + if err != nil { + fmt.Fprintf(os.Stderr, "Error: Failed to get 'output' flag: %v\n", err) + os.Exit(1) + } + if err := getTaskHistory(id, output); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + }, +} + +func init() { + rootCmd.AddCommand(historyCmd) + historyCmd.Flags().Int64P("id", "i", 0, "ID of the task (required)") + historyCmd.MarkFlagRequired("id") + historyCmd.Flags().StringP("output", "o", "table", "Output format (table, json, yaml)") +} + +// getTaskHistory retrieves and prints the history of a task by its ID +func getTaskHistory(identifier int64, outputFormat string) error { + history, err := fetchTaskHistory(identifier) + if err != nil { + return fmt.Errorf("failed to retrieve task history: %w", err) + } + return printTaskHistory(history, outputFormat) +} + +// fetchTaskHistory retrieves the task history from the server +func fetchTaskHistory(identifier int64) (*v1.GetTaskHistoryResponse, error) { + client, err := x.CreateClient(address) + if err != nil { + return nil, fmt.Errorf("failed to create client: %w", err) + } + + req := connect.NewRequest(&v1.GetTaskHistoryRequest{Id: int32(identifier)}) + resp, err := client.GetTaskHistory(context.Background(), req) + if err != nil { + return nil, fmt.Errorf("failed to get task history: %w", err) + } + return resp.Msg, nil +} + +// printTaskHistory prints task history in the specified format +func printTaskHistory(history *v1.GetTaskHistoryResponse, outputFormat string) error { + switch outputFormat { + case "json": + return x.PrintJSON(history) + case "yaml": + return x.PrintYAML(history) + case "table": + table := tablewriter.NewWriter(os.Stdout) + x.PrintTaskHistoryTable(table, history) + return nil + default: + return fmt.Errorf("unsupported output format: %s", outputFormat) + } +} diff --git a/cli/cmd/root.go b/cli/cmd/root.go new file mode 100644 index 0000000..10bd09c --- /dev/null +++ b/cli/cmd/root.go @@ -0,0 +1,56 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var cfgFile string +var ( + LogLevel string + address string +) + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "task-cli", + Short: "A CLI application for managing task in a distributed system", + Long: ``, + Run: func(cmd *cobra.Command, args []string) { + // If no subcommand is provided, display the help message + cmd.Help() + }, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } +} + +func init() { + // Here you can define flags and configuration settings. + // Cobra supports persistent flags, which, if defined here, + // will be global for your application. + + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.task-cli.yaml)") + + // Add global flag for log level + rootCmd.PersistentFlags().StringVar(&LogLevel, "log-level", "error", "Set the logging level") + + // Add global flag for address + rootCmd.PersistentFlags().StringVar(&address, "address", "http://127.0.0.1:8080", "Set the server address") + + // Modify the PersistentPreRun function + rootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { + InitLogger(LogLevel) + } + // Cobra also supports local flags, which will only run + // when this action is called directly. + // rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/cli/cmd/task.go b/cli/cmd/task.go new file mode 100644 index 0000000..d4d5059 --- /dev/null +++ b/cli/cmd/task.go @@ -0,0 +1,329 @@ +package cmd + +import ( + "context" + "fmt" + "log/slog" + "os" + "strings" + v1 "task/pkg/gen/cloud/v1" + cloudv1connect "task/pkg/gen/cloud/v1/cloudv1connect" + "task/pkg/x" + + // Add this import + + "connectrpc.com/connect" + "github.com/spf13/cobra" +) + +// taskCmd represents the task command +var taskCmd = &cobra.Command{ + Use: "task", + Aliases: []string{"t"}, + Short: "Manage tasks in the system", + Long: `The task command allows you to manage tasks in the system, including creating new tasks, +retrieving task details, listing all tasks, and viewing task history. +Use subcommands to perform specific operations on tasks.`, +} + +// createTaskCmd represents the create task command +var createTaskCmd = &cobra.Command{ + Use: "create [task name] --type [task type] --parameter [key=value] --description [task description]", + Aliases: []string{"c", "new"}, + Short: "Create a new task", + Long: `Create a new task in the system with the specified name, type, parameters, and description. +You must provide a task name and type. Parameters and description are optional. + +The task type should be one of the predefined types in the system (e.g., send_email, run_query). +Multiple parameters can be added by repeating the --parameter flag. +The description flag allows you to add a detailed explanation of the task.`, + Example: ` task create "Send Newsletter" --type send_email --parameter recipient=user@example.com --parameter subject="Weekly Update" --description "Send weekly newsletter to subscribers" + task create "Generate Report" --type run_query --parameter query="SELECT * FROM sales" --parameter format=csv --description "Generate monthly sales report" + task c "Backup Database" --type system_backup --parameter target=/backups/db.sql --description "Perform full database backup"`, + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + taskName := args[0] + taskType, _ := cmd.Flags().GetString("type") + if taskType == "" { + fmt.Println("Error: --type flag is required") + cmd.Usage() + os.Exit(1) + } + parameters, _ := cmd.Flags().GetStringToString("parameter") + description, _ := cmd.Flags().GetString("description") + addTask(taskName, taskType, parameters, description) + }, +} + +// getTaskCmd represents the get task command +var getTaskCmd = &cobra.Command{ + Use: "get --id [task_id]", + Aliases: []string{"g", "show"}, + Short: "Get details of a specific task", + Long: `Retrieve and display the details of a specific task by its ID. +You can specify the output format as table (default), json, or yaml.`, + Example: ` task get --id 123 + task get --id 456 --output json + task g -i 789 -o yaml`, + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + id, _ := cmd.Flags().GetInt64("id") + if id == 0 { + fmt.Println("Error: --id flag is required") + cmd.Usage() + os.Exit(1) + } + outputFormat, _ := cmd.Flags().GetString("output") + getTask(id, outputFormat) + }, +} + +// listTaskCmd represents the list task command +var listTaskCmd = &cobra.Command{ + Use: "list", + Aliases: []string{"l", "ls"}, + Short: "List all tasks", + Long: `List all tasks in the system. This command displays a summary of all tasks, +including their IDs, names, types, and current statuses. +You can specify the output format as table (default), json, or yaml. +Use --offset and --limit flags for pagination, --status for filtering by status, +and --type for filtering by task type.`, + Example: ` task list + task list --output json + task ls -o yaml + task list --offset 20 --limit 10 + task list --status running + task list --type email_send`, + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + outputFormat, _ := cmd.Flags().GetString("output") + offset, _ := cmd.Flags().GetInt32("offset") + limit, _ := cmd.Flags().GetInt32("limit") + status, _ := cmd.Flags().GetString("status") + taskType, _ := cmd.Flags().GetString("type") + listTasks(outputFormat, offset, limit, status, taskType) + }, +} + +// taskStatusCmd represents the task status command +var taskStatusCmd = &cobra.Command{ + Use: "status", + Aliases: []string{"s", "stat"}, + Short: "Get the status counts of all tasks", + Long: `Retrieve and display the current status counts of all tasks in the system.`, + Example: ` task status + task s`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + return getTaskStatus() + }, +} + +// init function to set up commands and flags +func init() { + + taskCmd.AddCommand(createTaskCmd, getTaskCmd, listTaskCmd, taskStatusCmd) + + addCommonFlags := func(cmd *cobra.Command) { + cmd.Flags().Int64P("id", "i", 0, "ID of the task") + cmd.MarkFlagRequired("id") + cmd.Flags().StringP("output", "o", "table", "Output format (table, json, yaml)") + } + + addCommonFlags(getTaskCmd) + + // Update flags for listTaskCmd + listTaskCmd.Flags().StringP("output", "o", "table", "Output format (table, json, yaml)") + listTaskCmd.Flags().Int32P("offset", "f", 0, "Offset for pagination") + listTaskCmd.Flags().Int32P("limit", "l", 100, "Limit for pagination") + listTaskCmd.Flags().StringP("status", "s", "all", "Filter by task status (queued, running, failed, succeeded,all)") + listTaskCmd.Flags().StringP("type", "t", "all", "Filter by task type (e.g., email_send, run_query,all)") + + createTaskCmd.Flags().StringP("type", "t", "", "Type of the task (e.g., send_email, run_query)") + createTaskCmd.MarkFlagRequired("type") + createTaskCmd.Flags().StringToStringP("parameter", "p", nil, "Additional parameters for the task as key=value pairs") + createTaskCmd.Flags().StringP("description", "d", "", "Detailed description of the task") + + rootCmd.AddCommand(taskCmd) + +} + +// createClient creates a new TaskManagementServiceClient with an OpenTelemetry interceptor +func createClient(address string) (cloudv1connect.TaskManagementServiceClient, error) { + if address == "" { + return nil, fmt.Errorf("server address is empty") + } + + if !strings.HasPrefix(address, "http://") && !strings.HasPrefix(address, "https://") { + address = "http://" + address + } + + return x.CreateClient(address) +} + +// addTask creates a new task and sends it to the server +func addTask(name string, taskType string, parameters map[string]string, description string) { + slog.Info("Creating new task", "name", name, "type", taskType, "parameters", parameters, "description", description) + + client, err := createClient(address) + if err != nil { + slog.Error("Failed to create client", "error", err) + return + } + req := connect.NewRequest(&v1.CreateTaskRequest{ + Name: name, + Type: taskType, + Description: description, + Payload: &v1.Payload{ + Parameters: parameters, + }, + }) + + slog.Debug("Sending CreateTask request to server") + resp, err := client.CreateTask(context.Background(), req) + if err != nil { + slog.Error("Error creating task", "error", err) + return + } + + slog.Info("Task created successfully", "id", resp.Msg.Id) + fmt.Printf("Task created successfully:\n") + fmt.Printf(" ID: %d\n", resp.Msg.Id) + fmt.Printf(" Name: %s\n", name) + fmt.Printf(" Type: %s\n", taskType) + fmt.Printf(" Parameters: %v\n", parameters) + fmt.Printf(" Description: %s\n", description) +} + +// getTask retrieves the details of a task by its ID +func getTask(identifier int64, outputFormat string) { + task, err := fetchTask(identifier) + if err != nil { + slog.Error("Error retrieving task", "error", err, "taskID", identifier) + fmt.Printf("Error retrieving task: %v\n", err) + return + } + printOutput(task, outputFormat) +} + +// listTasks retrieves and displays all tasks +func listTasks(outputFormat string, offset, limit int32, status, taskType string) { + tasks, err := fetchTasks(offset, limit, status, taskType) + if err != nil { + fmt.Printf("Error retrieving tasks: %v\n", err) + return + } + printOutput(tasks, outputFormat) +} + +// Helper function to fetch a task +func fetchTask(identifier int64) (*v1.Task, error) { + + client, err := createClient(address) + if err != nil { + + return nil, fmt.Errorf("failed to create client: %w", err) + } + + req := connect.NewRequest(&v1.GetTaskRequest{Id: int32(identifier)}) + resp, err := client.GetTask(context.Background(), req) + if err != nil { + return nil, err + } + return resp.Msg, nil +} + +// Helper function to fetch all tasks +func fetchTasks(offset, limit int32, status, taskType string) (*v1.TaskList, error) { + client, err := createClient(address) + if err != nil { + return nil, fmt.Errorf("failed to create client: %w", err) + } + + req := &v1.TaskListRequest{ + Limit: limit, + Offset: offset, + } + // Check if status is passed and valid, if not "all" then add to request + statusInt := x.GetStatusInt(strings.ToUpper(status)) + if statusInt != -1 { + req.Status = &statusInt + } else { + return nil, fmt.Errorf("invalid status: %s", status) + } + // Check if type is passed and valid, if not "all" then add to request + if taskType != "all" { + req.Type = &taskType + } + + resp, err := client.ListTasks(context.Background(), connect.NewRequest(req)) + if err != nil { + return nil, err + } + return resp.Msg, nil +} + +// printOutput prints the data in the specified format +func printOutput(data interface{}, format string) { + slog.Info("Printing output", "format", format) + switch format { + case "table": + x.PrintTable(data) + case "json": + x.PrintJSON(data) + case "yaml": + x.PrintYAML(data) + default: + slog.Warn("Invalid output format", "format", format) + fmt.Println("Invalid output format. Use 'table', 'json', or 'yaml'.") + } +} + +var logLevel slog.Level + +// InitLogger initializes the global logger with the specified log level +func InitLogger(level string) { + + switch strings.ToLower(level) { + case "debug": + logLevel = slog.LevelDebug + case "info": + logLevel = slog.LevelInfo + case "warn": + logLevel = slog.LevelWarn + case "error": + logLevel = slog.LevelError + default: + fmt.Printf("Invalid log level: %s. Using 'info' as default.\n", level) + logLevel = slog.LevelInfo + } + + logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: logLevel})) + slog.SetDefault(logger) +} + +// getTaskStatus retrieves and displays the status counts of all tasks +func getTaskStatus() error { + slog.Info("Retrieving task status counts") + + client, err := createClient(address) + if err != nil { + slog.Error("Failed to create client", "error", err) + return fmt.Errorf("failed to create client: %w", err) + } + + resp, err := client.GetStatus(context.Background(), connect.NewRequest(&v1.GetStatusRequest{})) + if err != nil { + slog.Error("Error retrieving task status counts", "error", err) + return fmt.Errorf("error retrieving task status counts: %w", err) + } + + fmt.Println("Task Status Counts:") + for k, v := range resp.Msg.StatusCounts { + statusString := x.GetStatusString(int(k)) + fmt.Printf(" %s: %d\n", statusString, v) + } + + slog.Info("Task status counts retrieved successfully") + return nil +} diff --git a/cli/main.go b/cli/main.go new file mode 100644 index 0000000..8aec6f3 --- /dev/null +++ b/cli/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "task/cli/cmd" +) + +func main() { + cmd.Execute() +} diff --git a/clients/dashboard/.env b/clients/dashboard/.env new file mode 100644 index 0000000..d8aa3a0 --- /dev/null +++ b/clients/dashboard/.env @@ -0,0 +1,2 @@ +NEXT_PUBLIC_SERVER_ENDPOINT="http://127.0.0.1:8080" + diff --git a/clients/dashboard/commitlint.config.js b/clients/dashboard/commitlint.config.js new file mode 100644 index 0000000..3bf488d --- /dev/null +++ b/clients/dashboard/commitlint.config.js @@ -0,0 +1,24 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + // TODO Add Scope Enum Here + // 'scope-enum': [2, 'always', ['yourscope', 'yourscope']], + 'type-enum': [ + 2, + 'always', + [ + 'feat', + 'fix', + 'docs', + 'chore', + 'style', + 'refactor', + 'ci', + 'test', + 'perf', + 'revert', + 'vercel', + ], + ], + }, +}; diff --git a/clients/dashboard/components.json b/clients/dashboard/components.json new file mode 100644 index 0000000..e587754 --- /dev/null +++ b/clients/dashboard/components.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/styles/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + } +} \ No newline at end of file diff --git a/clients/dashboard/jest.config.js b/clients/dashboard/jest.config.js new file mode 100644 index 0000000..10886cb --- /dev/null +++ b/clients/dashboard/jest.config.js @@ -0,0 +1,30 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const nextJest = require('next/jest'); + +const createJestConfig = nextJest({ + // Provide the path to your Next.js app to load next.config.js and .env files in your test environment + dir: './', +}); + +// Add any custom config to be passed to Jest +const customJestConfig = { + // Add more setup options before each test is run + setupFilesAfterEnv: ['/jest.setup.js'], + + // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work + moduleDirectories: ['node_modules', '/'], + + testEnvironment: 'jest-environment-jsdom', + + /** + * Absolute imports and Module Path Aliases + */ + moduleNameMapper: { + '^@/(.*)$': '/src/$1', + '^~/(.*)$': '/public/$1', + '^.+\\.(svg)$': '/src/__mocks__/svg.tsx', + }, +}; + +// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async +module.exports = createJestConfig(customJestConfig); diff --git a/clients/dashboard/jest.setup.js b/clients/dashboard/jest.setup.js new file mode 100644 index 0000000..3f1e9e1 --- /dev/null +++ b/clients/dashboard/jest.setup.js @@ -0,0 +1,5 @@ +import '@testing-library/jest-dom/extend-expect'; + +// Allow router mocks. +// eslint-disable-next-line no-undef +jest.mock('next/router', () => require('next-router-mock')); diff --git a/clients/dashboard/next-env.d.ts b/clients/dashboard/next-env.d.ts new file mode 100644 index 0000000..40c3d68 --- /dev/null +++ b/clients/dashboard/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/clients/dashboard/next-sitemap.config.js b/clients/dashboard/next-sitemap.config.js new file mode 100644 index 0000000..5dc06e6 --- /dev/null +++ b/clients/dashboard/next-sitemap.config.js @@ -0,0 +1,13 @@ +/** + * @type {import('next-sitemap').IConfig} + * @see https://github.com/iamvishnusankar/next-sitemap#readme + */ +module.exports = { + // !STARTERCONF Change the siteUrl + /** Without additional '/' on the end, e.g. https://theodorusclarence.com */ + siteUrl: 'https://tsnext-tw.thcl.dev', + generateRobotsTxt: true, + robotsTxtOptions: { + policies: [{ userAgent: '*', allow: '/' }], + }, +}; diff --git a/clients/dashboard/next.config.js b/clients/dashboard/next.config.js new file mode 100644 index 0000000..6aeb45a --- /dev/null +++ b/clients/dashboard/next.config.js @@ -0,0 +1,55 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + eslint: { + dirs: ['src'], + }, + typescript: { + ignoreBuildErrors: true, + }, + reactStrictMode: true, + swcMinify: true, + + // Uncoment to add domain whitelist + // images: { + // remotePatterns: [ + // { + // protocol: 'https', + // hostname: 'res.cloudinary.com', + // }, + // ] + // }, + + webpack(config) { + // Grab the existing rule that handles SVG imports + const fileLoaderRule = config.module.rules.find((rule) => + rule.test?.test?.('.svg') + ); + + config.module.rules.push( + // Reapply the existing rule, but only for svg imports ending in ?url + { + ...fileLoaderRule, + test: /\.svg$/i, + resourceQuery: /url/, // *.svg?url + }, + // Convert all other *.svg imports to React components + { + test: /\.svg$/i, + issuer: { not: /\.(css|scss|sass)$/ }, + resourceQuery: { not: /url/ }, // exclude if *.svg?url + loader: '@svgr/webpack', + options: { + dimensions: false, + titleProp: true, + }, + } + ); + + // Modify the file loader rule to ignore *.svg, since we have it handled now. + fileLoaderRule.exclude = /\.svg$/i; + + return config; + }, +}; + +module.exports = nextConfig; diff --git a/clients/dashboard/package.json b/clients/dashboard/package.json new file mode 100644 index 0000000..90ebadf --- /dev/null +++ b/clients/dashboard/package.json @@ -0,0 +1,88 @@ +{ + "name": "dashboard", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "lint:fix": "eslint src --fix && pnpm format", + "lint:strict": "eslint --max-warnings=0 src", + "typecheck": "tsc --noEmit --incremental false", + "test:watch": "jest --watch", + "test": "jest", + "format": "prettier -w .", + "format:check": "prettier -c .", + "postbuild": "next-sitemap --config next-sitemap.config.js" + }, + "dependencies": { + "@buf/evalsocket_cloud.bufbuild_es": "^1.10.0-20240930090015-e8421d60e43d.1", + "@buf/evalsocket_cloud.connectrpc_es": "^1.5.0-20240930133422-6e6299195d4e.1", + "@bufbuild/protobuf": "^1.10.0", + "@connectrpc/connect": "^1.5.0", + "@connectrpc/connect-next": "^1.5.0", + "@connectrpc/connect-node": "^1.5.0", + "@connectrpc/connect-web": "^1.5.0", + "@monaco-editor/react": "^4.6.0", + "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-select": "^2.1.1", + "@radix-ui/react-slot": "^1.1.0", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "date-fns": "^4.1.0", + "install": "^0.13.0", + "lucide-react": "^0.438.0", + "monaco-editor": "^0.52.0", + "next": "^14.2.13", + "npm": "^10.8.3", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-hot-toast": "^2.4.1", + "react-icons": "^5.3.0", + "recharts": "^2.12.7", + "tailwind-merge": "^2.5.2", + "tailwindcss-animate": "^1.0.7", + "zod": "^3.22.4" + }, + "devDependencies": { + "@bufbuild/buf": "^1.39.0", + "@commitlint/cli": "^19.5.0", + "@commitlint/config-conventional": "^16.2.4", + "@connectrpc/protoc-gen-connect-es": "^1.5.0", + "@svgr/webpack": "^8.1.0", + "@tailwindcss/forms": "^0.5.9", + "@testing-library/jest-dom": "^6.3.0", + "@testing-library/react": "^13.4.0", + "@types/react": "^18.3.4", + "@types/testing-library__jest-dom": "^5.14.9", + "@typescript-eslint/eslint-plugin": "^5.62.0", + "@typescript-eslint/parser": "^5.62.0", + "autoprefixer": "^10.4.20", + "eslint": "^8.57.1", + "eslint-config-next": "^14.2.13", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-simple-import-sort": "^7.0.0", + "eslint-plugin-unused-imports": "^2.0.0", + "jest": "^29.7.0", + "lint-staged": "15.2.10", + "next-router-mock": "^0.9.0", + "next-sitemap": "^2.5.28", + "postcss": "^8.4.45", + "prettier": "^2.8.8", + "prettier-plugin-tailwindcss": "^0.5.0", + "tailwindcss": "^3.4.12", + "typescript": "5.4.5" + }, + "lint-staged": { + "**/*.{js,jsx,ts,tsx}": [ + "eslint --max-warnings=0", + "prettier -w" + ], + "**/*.{json,css,scss,md,webmanifest}": [ + "prettier -w" + ] + } +} diff --git a/clients/dashboard/postcss.config.js b/clients/dashboard/postcss.config.js new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/clients/dashboard/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/clients/dashboard/public/favicon.ico b/clients/dashboard/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..038704bd52a02feb3a858e5c0d8c1fd02a7f8cd7 GIT binary patch literal 10990 zcmeHNcU)A*7C!eb;0l6Z0TVRAwiJckrHN9aC|FTJP^@S)YnLPz6x66Ok;G^cu^@_q z3ig7EHHs2r$KGBFc!^Eo1Idcv~0;x!+ zBk(4)sVPw)5xKeXvYIxjiHcF@=%|#(SQEY4n#cq1;1e1S;@`=StHR9xE@Q%SM(K<) z7_DNI$!HCuEJo`Xt!K1>Q7#iUF<~FeP!bPI;t`{GR1%L#Vxc6yE2&OMs*^_5DWmF)q&h39&Kt!d zqj=FMUN(wXB=MRg-Y6A6WP*%`(n`gIH=6Yv=^ka!AoVU!eGD3;zC5|(Z?v3Z3>qc% zGiZ=v%Tt^|qon=@4bp(}6mQVT$$g-Kr$Gjdk_HV`0D)q{-y^)7;4bmG%9$6H0d8a7BgWfAF5^Y zscm>_+xnp;wQD`sw)y%sJidPBhor^EsJ`GUf2AuwV3iCit9&Z%uNuxnU%#MGeXkK7 zy+^tC8RZ_8;L$EvUuB=BN{&SD9~`EO8Rju|R`Y3#n@xYS>7+Ss@gv>C!nJz6Uu9H} zjt7T!_rad&cdemVp;a^P)QN~`<6Au>a zyz6!;i<@@r3{)1nz!FbQ`wMt_4E4tu$r#h^@?tTxl^7$15ZGp@5`H=VT>JHM0%W}S|l@B`XH`0CY*H#LicNt|D*+<2D zVd?6${z!PCV;61Ojz(7>3cv#qUHMLxFjj+lh{zJpqpqKt=WFgpXBewU#~JPZ%%;y^ zPrcS+nPI_n?&`DumMyGPB$zsBInK&nv&2)=`D`wq>hPe?&~R<`En5W-*3bNn&VE%L zHF)y{Y`r5+S%;j~9d??##1*q#Nj{H@2LtaF@0EAo>WD0#BR`1=FSb%9qHMidGXDTS zp8R=Io(l4*!QOZj`JlJ>@vZlliok>QlYid|@XWWfC7dcs74cMmK0hL!VN+Tj{8_+# z2YB*6w~6fCwuUpaGN3;k&(O&&518 z_2|=9S<=534^^!%e4#`2t1i?t?e`^z8U(iUt#Zr1y~X+bx2p5^tuB45%G}ei%KiR` z`wO@Ds_|eJ^nO#9KdIosd3g9c)yQcrFlyzvQ-p(4I(m?2;b%6uv*UdJkkQLaU6pNU zDIZIHfnmW!DNhi4_aP?z&hfzBK&9ygWcaF(r)=w;IwpOw=Tn<8Gn)s8>HrC?5LaA+ z$F>Xh@F757z=v?|OY44vJZr{-4@@SY>?sun zjBBk-O;E6Y-bUwwp9SdC6RgbMI1git(Iqo`1M{`9uzq-i)-;*MD7Dn63T|m1T?S<+r75d9~_^kQ*wGYuJEp^TR(i-;IY3})f3B)}=aQndi zfpCg`P%Yots7p5=Wuhy{r`Xb;fYZ3ogw_j+>%Ly1URa`DRH9y7qJFDHy`)5)R-#^3 zQg=m3-SiT5Mu~b=i8`}Hz4l{u=KFP{M|fZ$O3%uWasJHDaoKXq_Q+ROis$FVH&zGm z`QC;jCbeo84!`yr>Nfs;JAA zRSN4pYJgY#b8!1;q6d41cl8Mf;6JS(H~(7^kL7(3WBg6Yyl3+~I^pNAa^=xm?0xgs zkhjEB)A?NC!#}B5yYX0_hkud?YV6ihKD7-`ZCgJz+0QkK`44NXwewYWK3kqYf7q}e zxueSRsSW<{n`QoRVd-PU3rrz{8si0J!Gd3n7nD3gJY}6_JY|bnJY|=8JVi2(r>K4< zo+61wl6X<7GM@7L<4v$PO!20}zb)RxZI3GBP3Ez%fAW951bCd%4b&0D3ToI~pTy>Q9jaya;Co zbp`JUD*D=r+6U`t_s43w^s_)Q&$?6g!3MPQVm-<_Ri8RV`cVE4BEhz&`9~coG2=-} z1xMVA5O$-Tc+Wq;mjXb&W7`lcJes_#5y6tADd5vU(?K&pF$o@&0{-k$S9%HjIdB6g zth1IzgKs$QNMpcLjylm;@NuC0A5=5}d?IKPC=nFiyDhzpcb-Rn$i&w40(io>*0czH zzKHx}(1x3~GzEMr2xd4<2OWJ#Gy}XxbX!UW?+KoH--=R@hs8&@b<*31ooFV?vp};! zxVX@$=`AomKbnK`To5jMlz!5IuA;wv_sgqE^y*wUfzRkQ_V_&8|QS60*m9FA0i2~U3hezfF>6XDiQ z^U_=i!CDG_Mn`#g4~{cB{7D@u0Og!>pvWHH6cOc3-9b7Zf6{Z(`=cL!nz8B$f}u~@ zKZ+CtJ|AV=Y^Vch=a<&B@84>I@08%vqncg zM^EIJV{Jx(uK-U6`3GYCfC53d{_(&&kG$jed|uA4#zmf z4)>suD2H^?(ngfm;JyB+!wroN7uTiD;E2}Kdeq~-Mz7_%@VGs_x!#3G?rA3WM*>mp}+{Z+TTO0GZJSAl|At-6?GKG(u2=`80Jc;0l zqJ+-I>BV>G(Na z<@52L{RiJEC_H)Y!lf(MZ`}IV2Os_CzhB(_-&fyDKa$GYrp~UbCw%<^+O_Wx5*qeQ zc$co-di3lS)h9YOe&C>C37^`jcOPrvSl#2${Ij~db&j{IeH@1WJ?(LE{bfwQ{Qkn# z6Wz;TrlvM>-I5)bilV7Kwd2+qPY;$~NPRA9cH{LguZ_VAruGb{e&?Uc=k2L8M}L0r ztM83Jo{dN~Z-3=nC*GdAtoxk_)0?95f5y~x#fHUkXik1rvwY|;-`5BJR=01*-G8BYUT5GNdwNO3CS~|u+q?I*@voe_ z>7Jk8Ds^-3PwKtvxvy^#S-r7R{(i-nZ#M?LpLuffcDHH&cK07~=kphzJoWao;-sa@ z_**O*clhY>!ZR1HT)*{1*2?)QJMMk`gKH?&HZ-jH$x&v zr6s*JXMx%H3Wg8Hs#1Q0y=d*{(rIm!?9eM?ybO2S;#=5>lE|0PGWPt8hDI)m>{k158s6G@wDy z^}C?M%k6;yV>E=26m5r|%gAd)A<(_upu4)nwV~LlEvX~Q8Fy`DeGlg?^+x?#{7whx zTCQ)ikw<)rLXpn_AOFhJvK~d8joLwnt|+WeYp>YR_77}n+M7)&ah{v3_h!MqSOxt$ z1^S^&cOOay=lUiEyx>k9ih#W^8+mRw%mrV4-k#=z>%9GGU8zWE+ZxjXl!HQ{^U)8t z{a!~IZe!X0TZDXP*b8rg8z#4;H1LEuZnPYHIOkXGXeIL8Zs9hI7Pj7Mlm}w|#-n{b z^8Y;lNT4PO*tF^wKWNDCQKQF>pZNTgPHkF@@Q@!*`FXBOw0o@C=1}Tt_aO!9}^^cx+n5S&X+P**r?y{{d2&$?^aI literal 0 HcmV?d00001 diff --git a/clients/dashboard/public/favicon/android-chrome-192x192.png b/clients/dashboard/public/favicon/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..1826e12780024b01035b66040a0639c5149fdfbd GIT binary patch literal 8899 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 literal 0 HcmV?d00001 diff --git a/clients/dashboard/public/favicon/android-chrome-512x512.png b/clients/dashboard/public/favicon/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..05cac45ee975b989712f82182103837016b81b35 GIT binary patch literal 50301 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 literal 0 HcmV?d00001 diff --git a/clients/dashboard/public/favicon/apple-touch-icon.png b/clients/dashboard/public/favicon/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..267bb7f5b765540b43af6d6b26b453b6b206ddcf GIT binary patch literal 8545 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 literal 0 HcmV?d00001 diff --git a/clients/dashboard/public/favicon/favicon-16x16.png b/clients/dashboard/public/favicon/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..abef5bf16fc7e7455360bd693f2fca62d8502d2d GIT binary patch literal 937 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>QN&rb^OE;X>VFtRW+ zvM@KWwHDmHRA^_3k%g(Tv9Zw3#U=)ZCi;fPMn=YlMkWRZCi(`(hK52rO7vZAluJVt zt0I*uqLiv)6szNP0^M{1Jro+U6`Jz3L;Zxd7i)*Q@Exn=y4B6}a}memS=^VWDVM~k zWrTA)T+8uzGslB%>`(VA7pEDSn;BY}8`_v_MticpnJw3zVrXTd?_|q+W)APExjKGs zdY&$VyXOn;USwczs}tbN_Ij2=L%gZ3zIKoY>zj>o?YSm;1_q9Hy54Sv)|MuQMmmAc zCb|aN!5*w{H_EqW8(CTy*x48YNqcMVOY`{;P1kpI(08;GT{Br^<1E(KvlSW=luP2- zUTosJy_Wm>2DX=n6{~U$?5z~)Vzq-^HKYAy`paY{RB6P87@L?F8yTAbLttms|NsAE z_Dov%y{W;-5;PJdx@v7EBiBUeij|RU%%$^ z0)-BHx;TbNTux3%NJ&adOih0N;K`$B51&3x7Z4C(Voo#=5KI*ip6Fx3LIeSJ|XYHECsGOX)Z)9cW&WVk= zd&kzMk;y42?w;Mgx_^v~n;Z`+Dl}d&$e;hA2I`Q&6e6=(&6r>mdKI;Vst0Hpss6#xJL literal 0 HcmV?d00001 diff --git a/clients/dashboard/public/favicon/favicon-32x32.png b/clients/dashboard/public/favicon/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..cfe227cdb1dc4671d84f703b96d3a4c81f4f258e GIT binary patch literal 1583 zcmZ`&X;70_6um4KBm@IQP+vQyQUoD^Z%YUPQ7Eez3L!!lsXzdWRS6m^pi-c8taaSr zvr+*?K->@lDzaz-ilCifv?#5uMXO~TpuB$m?2rDq@0@qbUBCl?2LV3-{DWQhW>lm>Y${^Y z5W5nwUm!Lev8xcf8nJ5-yB4t-h}9xC6S3l@JU;G6W%&c%h;Kz(a^lrfC|n-_R6A`pQX#oMsrt zi}X|l%{-AI)UOxnbwd4DLVcD{pDomH64q}K>c4huC_qISlw3xW6cOMzFDpf;-(h#9 z(#~|)@yx!t1)1IRS_z>V~z(;Mb|491#G9)RE4imKRH6Q2vxeB-k z@J+zIX8+u@ye3^#Z=b>uZuM38fjDk})2igj8@?d|6t+FwxZ5rMZgpL=obe{y z6XUFgjg~L3IkX(|h!69O4WIT$J+H5dSma0f$i&f0Jk?PWWdtpix+SYD#?IKEFQPcE zi8beV+a6lVc*I9qjyCXn4$>4&y>;8yJJ8?ec7^4OCifL8PgSI#qndwB?_9NOc4@ZY zLWyK)2oV@Cv#xkn#SV!w#HPR6Y^rnmz)7bQ+nsB++1{)*o4jHD!04$`TE5`EeIF7Dk-Pq6~|j^n(7Ss=Npc-9G2FcOlYn;b)xOa+4`>w zeERr~Zp!`gY@6=BlJwr1?w%6gFUQJSUOn~R{du$d+((x$Mb>D=<#xKE#wVU}b)P=} zttIE$y$!#Q%v*2=)C4~~W8if1E2rI7O>6HPG;THKBMEKsf86Dbty!I0>*h3VVys@S z6+|xXI4Rd(7*mZQ$6hA&( zm!pXhY-l0R!lYVczFE&jr z3dw!HaS==feWt$MHvbkkURPbn$GVgxU8+K}E|mkI2#S)Bq=b~J2}Z#%3X<_82n9ii z?;O1MAHkZ8l=QUh{}&{D>z2j|;&ap=>r_b_McQ>4Y3Zv|MY?QlswiEn(*R_Z{qmQs zb!MEq`_+$3KSexIfrSgtOT%+?af~b$S~!Y=^O%b%7A~jMBGa9|%bh=UzT0VK$_uYp Z;swu~?R9?zN%wM3KtxDXa9vPh!M~K>j8p&s literal 0 HcmV?d00001 diff --git a/clients/dashboard/public/favicon/favicon.ico b/clients/dashboard/public/favicon/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..038704bd52a02feb3a858e5c0d8c1fd02a7f8cd7 GIT binary patch literal 10990 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 literal 0 HcmV?d00001 diff --git a/clients/dashboard/public/favicon/site.webmanifest b/clients/dashboard/public/favicon/site.webmanifest new file mode 100644 index 0000000..8cf9748 --- /dev/null +++ b/clients/dashboard/public/favicon/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/favicon/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/favicon/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/clients/dashboard/public/fonts/inter-var-latin.woff2 b/clients/dashboard/public/fonts/inter-var-latin.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..2fbab974a9e1d56cafcd93c4a0a30b66dd1409ec GIT binary patch literal 36532 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 wqV5)unU(v0=O>H866^5xR+S zgGHFFV3=u|J|;BO>-7flc>K5BZu77d zRv;Y5z0BuxR?w;0Z1z*FR!`xqi4-ZNQfc36wZ12lNn5d4B=jheNE`)&!4H@|NJfTX z9?^@#;SiRgYL0L?{2v+2ol-=#TJ0+miEz~6PvFAxZ5LDuvKja=jh4&_|l00000NkvXXu0mjf DjPdej literal 0 HcmV?d00001 diff --git a/clients/dashboard/public/images/og.jpg b/clients/dashboard/public/images/og.jpg new file mode 100644 index 0000000000000000000000000000000000000000..88b03732b7453fc8226c17e686e5315b04d791de GIT binary patch literal 149123 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 RhFH5dzsSew-4#O5U#m{pDB}qHiuzfNh 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 literal 0 HcmV?d00001 diff --git a/clients/dashboard/public/robots.txt b/clients/dashboard/public/robots.txt new file mode 100644 index 0000000..8fbf606 --- /dev/null +++ b/clients/dashboard/public/robots.txt @@ -0,0 +1,9 @@ +# * +User-agent: * +Allow: / + +# Host +Host: https://tsnext-tw.thcl.dev + +# Sitemaps +Sitemap: https://tsnext-tw.thcl.dev/sitemap.xml diff --git a/clients/dashboard/public/sitemap-0.xml b/clients/dashboard/public/sitemap-0.xml new file mode 100644 index 0000000..7d36a7f --- /dev/null +++ b/clients/dashboard/public/sitemap-0.xml @@ -0,0 +1,4 @@ + + +https://tsnext-tw.thcl.devdaily0.72024-09-30T14:48:38.199Z + \ No newline at end of file diff --git a/clients/dashboard/public/sitemap.xml b/clients/dashboard/public/sitemap.xml new file mode 100644 index 0000000..f4d3450 --- /dev/null +++ b/clients/dashboard/public/sitemap.xml @@ -0,0 +1,4 @@ + + +https://tsnext-tw.thcl.dev/sitemap-0.xml + \ No newline at end of file diff --git a/clients/dashboard/public/svg/Logo.svg b/clients/dashboard/public/svg/Logo.svg new file mode 100644 index 0000000..9d9ae7d --- /dev/null +++ b/clients/dashboard/public/svg/Logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/clients/dashboard/public/svg/Vercel.svg b/clients/dashboard/public/svg/Vercel.svg new file mode 100644 index 0000000..6cd3196 --- /dev/null +++ b/clients/dashboard/public/svg/Vercel.svg @@ -0,0 +1 @@ +Vercel \ No newline at end of file diff --git a/clients/dashboard/renovate.json b/clients/dashboard/renovate.json new file mode 100644 index 0000000..ce15315 --- /dev/null +++ b/clients/dashboard/renovate.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["config:recommended", "group:all"], + "updatePinnedDependencies": false, + "stabilityDays": 2, + "separateMajorMinor": true, + "timezone": "Asia/Jakarta", + "schedule": ["before 11am on Monday"] +} diff --git a/clients/dashboard/src/app/error.tsx b/clients/dashboard/src/app/error.tsx new file mode 100644 index 0000000..a6d11c3 --- /dev/null +++ b/clients/dashboard/src/app/error.tsx @@ -0,0 +1,35 @@ +'use client'; // Error components must be Client Components + +import * as React from 'react'; +import { RiAlarmWarningFill } from 'react-icons/ri'; + + +export default function Error({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + React.useEffect(() => { + // eslint-disable-next-line no-console + console.error(error); + }, [error]); + + return ( +

+
+
+ +

+ Oops, something went wrong! +

+ +
+
+
+ ); +} diff --git a/clients/dashboard/src/app/layout.tsx b/clients/dashboard/src/app/layout.tsx new file mode 100644 index 0000000..224baf2 --- /dev/null +++ b/clients/dashboard/src/app/layout.tsx @@ -0,0 +1,66 @@ +import { Metadata } from 'next'; +import * as React from 'react'; +import { Toaster } from 'react-hot-toast'; + +import '@/styles/globals.css'; +// !STARTERCONF This is for demo purposes, remove @/styles/colors.css import immediately +import '@/styles/colors.css'; + +import { siteConfig } from '@/constant/config'; + +// !STARTERCONF Change these default meta +// !STARTERCONF Look at @/constant/config to change them +export const metadata: Metadata = { + metadataBase: new URL(siteConfig.url), + title: { + default: siteConfig.title, + template: `%s | ${siteConfig.title}`, + }, + description: siteConfig.description, + robots: { index: true, follow: true }, + // !STARTERCONF this is the default favicon, you can generate your own from https://realfavicongenerator.net/ + // ! copy to /favicon folder + icons: { + icon: '/favicon/favicon.ico', + shortcut: '/favicon/favicon-16x16.png', + apple: '/favicon/apple-touch-icon.png', + }, + manifest: `/favicon/site.webmanifest`, + openGraph: { + url: siteConfig.url, + title: siteConfig.title, + description: siteConfig.description, + siteName: siteConfig.title, + images: [`${siteConfig.url}/images/og.jpg`], + type: 'website', + locale: 'en_US', + }, + twitter: { + card: 'summary_large_image', + title: siteConfig.title, + description: siteConfig.description, + images: [`${siteConfig.url}/images/og.jpg`], + // creator: '@th_clarence', + }, + // authors: [ + // { + // name: 'Theodorus Clarence', + // url: 'https://theodorusclarence.com', + // }, + // ], +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + {children} + + + + ); +} diff --git a/clients/dashboard/src/app/not-found.tsx b/clients/dashboard/src/app/not-found.tsx new file mode 100644 index 0000000..9598fe5 --- /dev/null +++ b/clients/dashboard/src/app/not-found.tsx @@ -0,0 +1,24 @@ +import { Metadata } from 'next'; +import * as React from 'react'; +import { RiAlarmWarningFill } from 'react-icons/ri'; + +export const metadata: Metadata = { + title: 'Not Found', +}; + +export default function NotFound() { + return ( +
+
+
+ +

Page Not Found

+ Back to home +
+
+
+ ); +} diff --git a/clients/dashboard/src/app/page.tsx b/clients/dashboard/src/app/page.tsx new file mode 100644 index 0000000..763ecaa --- /dev/null +++ b/clients/dashboard/src/app/page.tsx @@ -0,0 +1,38 @@ +'use client'; + +import Head from 'next/head'; +import * as React from 'react'; +import '@/lib/env'; +import { Toaster, toast } from 'react-hot-toast'; + +/** + * SVGR Support + * Caveat: No React Props Type. + * + * You can override the next-env if the type is important to you + * @see https://stackoverflow.com/questions/68103844/how-to-override-next-js-svg-module-declaration + */ +import Logo from '~/svg/Logo.svg'; +import clsx from 'clsx'; +import { CreateTask } from '@/components/task/create'; +import { TaskList } from '@/components/task/list'; + +// !STARTERCONF -> Select !STARTERCONF and CMD + SHIFT + F +// Before you begin editing, follow all comments with `STARTERCONF`, +// to customize the default configuration. + +export default function HomePage() { + const showToast = () => { + toast.success('Hello, React Toast!'); + }; + + const [mode, setMode] = React.useState<'dark' | 'light'>('light'); + + return ( +
+
+ +
+
+ ); +} diff --git a/clients/dashboard/src/components/task/create.tsx b/clients/dashboard/src/components/task/create.tsx new file mode 100644 index 0000000..39d3db9 --- /dev/null +++ b/clients/dashboard/src/components/task/create.tsx @@ -0,0 +1,141 @@ +'use client'; + +import { useState } from 'react'; +import { + Sheet, + SheetClose, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "@/components/ui/sheet" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Editor } from "@monaco-editor/react" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" + +import { toast } from 'react-hot-toast'; // Assuming you're using react-hot-toast for notifications +import { + createConnectTransport, +} from '@connectrpc/connect-web' +import { + createPromiseClient, +} from '@connectrpc/connect' + + +import { TaskManagementService } from "@buf/evalsocket_cloud.connectrpc_es/cloud/v1/cloud_connect" +import { createTaskManagementClient } from '@/components/task/util'; + + +// Custom hook for form state management +function useTaskForm(initialTask: any) { + const [name, setName] = useState(initialTask?.name || ''); + const [description, setDescription] = useState(initialTask?.description || ''); + const [type, setType] = useState(initialTask?.type || 'run_query'); + const [jsonInput, setJsonInput] = useState(JSON.stringify(initialTask?.payload?.parameters || {}, null, 2)); + + return { name, setName, description, setDescription, type, setType, jsonInput, setJsonInput }; +} + +/** + * CreateTask component for creating a new task. + * This component renders a modal sheet with a form to create a new task. + */ +export function CreateTask({ isOpen, setOpen, initialTask, onCreateTask }: { isOpen: boolean, setOpen: (open: boolean) => void, initialTask: any, onCreateTask: (task: any) => void }) { + const { name, setName, description, setDescription, type, setType, jsonInput, setJsonInput } = useTaskForm(initialTask); + + const handleSubmit = async () => { + try { + const createdTask = await createTaskManagementClient().createTask({ + name: name, + type: type, + description: description, + payload: { + parameters: JSON.parse(jsonInput) + }, + }); + + console.log('Server response:', createdTask); + + if (createdTask && createdTask.id) { + onCreateTask(createdTask); + setOpen(false); + toast.success('Task created successfully'); + } else { + throw new Error('Task creation response is incomplete'); + } + } catch (error) { + console.error('Error creating task:', error); + let errorMessage = 'Failed to create task'; + if (error instanceof Error) { + errorMessage += `: ${error.message}`; + } + toast.error(errorMessage); + } + }; + + return ( + + + + Create New Task + + Enter task details and click save to create a new task. + + +
+
+ + setName(e.target.value)} + type="text" + placeholder="Task Name" + required + /> +
+
+ + setDescription(e.target.value)} + type="text" + placeholder="Task Description" + required + /> +
+
+ + +
+
+ + setJsonInput(value || '{}')} + options={{ minimap: { enabled: false } }} + /> +
+
+ + + +
+
+ ); +} \ No newline at end of file diff --git a/clients/dashboard/src/components/task/editor.tsx b/clients/dashboard/src/components/task/editor.tsx new file mode 100644 index 0000000..9e92a40 --- /dev/null +++ b/clients/dashboard/src/components/task/editor.tsx @@ -0,0 +1,67 @@ +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, + DialogClose, +} from "@/components/ui/dialog" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import Editor from '@monaco-editor/react'; + +import { Button } from "@/components/ui/button" + + +import { Eye, Info, RefreshCw, RotateCw, Plus, X, type Volume1 } from 'lucide-react'; // Add this import for icons + + + + +/** + * InputCode component to display task input in a dialog. + * @param {Object} props - Component props + * @param {any} props.input - Input data to display + */ +export function InputCode({ input }: { input: any }) { + return ( + + + + + + +
+ Task Input + + + +
+
+
+ +
+
+
+ ); +} diff --git a/clients/dashboard/src/components/task/history.tsx b/clients/dashboard/src/components/task/history.tsx new file mode 100644 index 0000000..ee7ddde --- /dev/null +++ b/clients/dashboard/src/components/task/history.tsx @@ -0,0 +1,117 @@ +'use client'; + + +import toast from "react-hot-toast" +import { + Sheet, + SheetClose, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "@/components/ui/sheet" + +import { formatDistanceToNow } from 'date-fns' +import { useEffect, useState } from "react"; // Import useState +import { createTaskManagementClient, getStatusColor, getStatusString, type TaskHistory, type TaskInterface } from "@/components/task/util"; + + + +/** + * TaskHistoryList component to display the details and history of a selected task. + * @param {Object} props - Component props + * @param {TaskInterface} props.task - The selected task + * @param {boolean} props.isOpen - Modal open state + * @param {Function} props.setOpen - Function to set modal open state + */ +export function TaskHistoryList({ task, isOpen, setOpen }: { task: TaskInterface; isOpen: boolean; setOpen: (open: boolean) => void; }) { + const [taskHistory, setTaskHistory] = useState([]); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + const fetchTaskHistory = async () => { + setIsLoading(true); + try { + const response = await createTaskManagementClient().getTaskHistory({ id: task.id }); + + const history = response.history.map((item: any) => ({ + id: item.id, + details: item.details, + status: getStatusString(item.status), + created_at: new Date(item.createdAt).toISOString(), + })); + + setTaskHistory(history); + } catch (error) { + console.error('Error fetching task history:', error); + toast.error("Failed to fetch task history. Please try again."); + } finally { + setIsLoading(false); + } + }; + + if (isOpen) { + fetchTaskHistory(); + } + }, [task.id, isOpen]); + + return ( + + + + Task Details and History + + View the task details and its history of status changes. + + + +
+ {/* Task Details */} +
+

Task Information

+
+
+

ID

+

{task.id}

+
+
+

Name

+

{task.name}

+
+
+

Status

+

+ {getStatusString(task.status)} +

+
+
+

Retries

+

{task.retries}

+
+
+
+ + {isLoading ? ( +

Loading task history...

+ ) : taskHistory.length > 0 ? ( + taskHistory.map((task: TaskHistory) => ( +
+
+

Status: {task.status}

+ + {formatDistanceToNow(new Date(task.created_at), { addSuffix: true })} + +
+

{task.details}

+
+ )) + ) : ( +

No history available for this task.

+ )} +
+
+
+ ); +} \ No newline at end of file diff --git a/clients/dashboard/src/components/task/list.tsx b/clients/dashboard/src/components/task/list.tsx new file mode 100644 index 0000000..75f13d8 --- /dev/null +++ b/clients/dashboard/src/components/task/list.tsx @@ -0,0 +1,344 @@ +'use client'; + +import { + Table, + TableBody, + TableCaption, + TableCell, + TableFooter, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table" +import { Button } from "@/components/ui/button" + + +import toast from "react-hot-toast" +import { + Sheet, + SheetClose, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "@/components/ui/sheet" +import { + createConnectTransport, +} from '@connectrpc/connect-web' +import { + createPromiseClient, +} from '@connectrpc/connect' + +import { formatDistanceToNow } from 'date-fns' +import { TaskManagementService } from "@buf/evalsocket_cloud.connectrpc_es/cloud/v1/cloud_connect" +import { Task, TaskType, CreateTaskRequest, Payload } from '@buf/evalsocket_cloud.bufbuild_es/cloud/v1/cloud_pb'; // Adjust this path if needed +import { useEffect, useState } from "react"; // Import useState +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { Eye, Info, RefreshCw, RotateCw, Plus, X, type Volume1 } from 'lucide-react'; // Add this import for icons +import { CreateTask } from './create'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" + +import { TaskHistory as TaskHistoryProto } from '@buf/evalsocket_cloud.bufbuild_es/cloud/v1/cloud_pb'; // Adjust this path if needed +import { TaskStatusEnum } from "@/cloud/v1/cloud_pb"; +import { InputCode } from "@/components/task/editor"; +import { createTaskManagementClient, getStatusColor, getStatusString, type TaskInterface } from "@/components/task/util"; +import { TaskHistoryList } from "@/components/task/history"; + + +/** + * TaskList component to display a list of tasks. + */ +export function TaskList() { + const [tasks, setTasks] = useState([]); // State for tasks + const [isOpen, setIsOpen] = useState(false); // Modal open state + const [selectedTaskId, setSelectedTaskId] = useState(0); // Selected task ID + const [statusCounts, setStatusCounts] = useState({ + QUEUED: 0, + RUNNING: 0, + FAILED: 0, + SUCCEEDED: 0, + UNKNOWN: 0, + }); + const [isCreateTaskOpen, setIsCreateTaskOpen] = useState(false); + const [isRefreshing, setIsRefreshing] = useState(false); + const [statusFilter, setStatusFilter] = useState("ALL"); + const [selectedTask, setSelectedTask] = useState(null); + const [typeFilter, setTypeFilter] = useState("ALL"); + const [currentPage, setCurrentPage] = useState(1); + const [tasksPerPage, setTasksPerPage] = useState(10); + const [hasMoreTasks, setHasMoreTasks] = useState(true); + + + // Add this useEffect to fetch status counts every 5 seconds + useEffect(() => { + const fetchStatusCounts = async () => { + try { + const response = await createTaskManagementClient().getStatus({}); + const newStatusCounts: any = {}; + + if ('statusCounts' in response) { + Object.entries(response.statusCounts).forEach(([status, count]) => { + newStatusCounts[getStatusString(parseInt(status))] = Number(count); + }); + } + setStatusCounts(newStatusCounts); + } catch (error) { + console.error('Error fetching status counts:', error); + toast.error('Failed to fetch status counts. Please try again later.'); + } + }; + + fetchStatusCounts(); // Initial fetch + const intervalId = setInterval(fetchStatusCounts, 5000); // Refresh every 5 seconds + + return () => clearInterval(intervalId); + }, []); + + const fetchTasks = async (page: number) => { + setIsRefreshing(true); + try { + const offset = (page - 1) * tasksPerPage; + const request: any = { + limit: tasksPerPage, + offset: offset, + }; + + // Add status filter if it's not "ALL" + if (statusFilter != "ALL") { + request.status = TaskStatusEnum[statusFilter as keyof typeof TaskStatusEnum]; + } else { + request.status = TaskStatusEnum.ALL + } + + // Add type filter if it's not "ALL" + if (typeFilter != "ALL") { + request.type = typeFilter; + } + + const response = await createTaskManagementClient().listTasks(request); + + const fetchedTasks = response.tasks.map((task: any) => ({ + id: task.id, + name: task.name, + type: task.type, + description: task.description, + payload: { + parameters: task?.payload?.parameters || {}, + }, + status: task.status, + retries: task.retries, + })); + + setTasks(fetchedTasks); + setHasMoreTasks(fetchedTasks.length === tasksPerPage); + } catch (error) { + console.error('Error fetching tasks:', error); + toast.error('Failed to refresh tasks. Please try again later.'); + } finally { + setIsRefreshing(false); + } + }; + + // Update this useEffect to refetch tasks when filters change + useEffect(() => { + fetchTasks(1); // Reset to first page when filters change + setCurrentPage(1); + }, [statusFilter, typeFilter, tasksPerPage]); + + // Separate useEffect for periodic refresh + useEffect(() => { + const intervalId = setInterval(() => { + fetchTasks(currentPage); + }, 10000); // Fetch tasks every 10 seconds + + return () => clearInterval(intervalId); + }, [currentPage, statusFilter, typeFilter, tasksPerPage]); + + const handleTaskClick = (taskId: number) => { + setIsOpen(true); // Open task details modal + setSelectedTaskId(taskId); // Set selected task ID + }; + + + const handleCreateTask = async (newTask: TaskInterface) => { + console.log(newTask, "===>"); + }; + + const filteredTasks = tasks.filter((task) => { + const statusMatch = statusFilter === "ALL" || getStatusString(task.status) === statusFilter; + const typeMatch = typeFilter === "ALL" || task.type === typeFilter; + return statusMatch && typeMatch; + }); + + + // Get unique task types + const taskTypes: any[] = ["ALL", "run_query", "send_email"]; + + const handleNextPage = () => { + if (hasMoreTasks) { + setCurrentPage(prevPage => prevPage + 1); + } + }; + + const handlePreviousPage = () => { + if (currentPage > 1) { + setCurrentPage(prevPage => prevPage - 1); + } + }; + + useEffect(() => { + fetchTasks(currentPage); + }, [currentPage, statusFilter, typeFilter, tasksPerPage]); + + return ( + <> +
+

Tasks Management

+
+ + + + +
+
+ +
+ {Object.entries(statusCounts).map(([status, count]) => ( + + + {status} + + +
{count}
+
+
+ ))} +
+ + + A list of your recent tasks. + + + ID + Name + Type + Description + Status + Action + + + + {filteredTasks.map((task: TaskInterface) => ( + + {task.id} + {task.name} + {task.type} + {task.description} + + + {getStatusString(task.status)} + + + +
+ + + +
+
+
+ ))} +
+
+ +
+
+ + Page {currentPage} + +
+
+ + +
+
+ + {isOpen && ( + t.id === selectedTaskId)!} + isOpen={isOpen} + setOpen={setIsOpen} + /> + )} + + + + ); +} + + diff --git a/clients/dashboard/src/components/task/util.ts b/clients/dashboard/src/components/task/util.ts new file mode 100644 index 0000000..17bd41d --- /dev/null +++ b/clients/dashboard/src/components/task/util.ts @@ -0,0 +1,70 @@ +import { TaskManagementService } from "@buf/evalsocket_cloud.connectrpc_es/cloud/v1/cloud_connect" +import { + createConnectTransport, +} from '@connectrpc/connect-web' +import { + createPromiseClient, +} from '@connectrpc/connect' + +// Update the TaskInterface to include a type field +export interface TaskInterface { + id: number; + name: string; + type: string; // Add this line + payload: { + parameters: any; + }; + retries: number; + status: number; + + description: string +} + + +// Define the type based on the proto structure +export interface TaskHistory { + id: number; + details: string; + status: string; + created_at: string; +} + + +// Change this to a function that creates and returns the client +export function createTaskManagementClient() { + return createPromiseClient( + TaskManagementService, + createConnectTransport({ + baseUrl: process.env.NEXT_PUBLIC_SERVER_ENDPOINT || "http://task:80" + }) + ); +} + +// Add this function to convert status number to string +export function getStatusString(status: number): string { + switch (status) { + case 0: + return "QUEUED"; + case 1: + return "RUNNING"; + case 2: + return "FAILED"; + case 3: + return "SUCCEEDED"; + default: + return "UNKNOWN"; + } +} + + + +// Add this function to get status color +export const getStatusColor = (status: string): string => { + switch (status) { + case "QUEUED": return "text-yellow-500"; + case "RUNNING": return "text-blue-500"; + case "FAILED": return "text-red-500"; + case "SUCCEEDED": return "text-green-500"; + default: return "text-gray-500"; + } +}; diff --git a/clients/dashboard/src/components/ui/button.tsx b/clients/dashboard/src/components/ui/button.tsx new file mode 100644 index 0000000..0270f64 --- /dev/null +++ b/clients/dashboard/src/components/ui/button.tsx @@ -0,0 +1,57 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/clients/dashboard/src/components/ui/card.tsx b/clients/dashboard/src/components/ui/card.tsx new file mode 100644 index 0000000..77e9fb7 --- /dev/null +++ b/clients/dashboard/src/components/ui/card.tsx @@ -0,0 +1,76 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/clients/dashboard/src/components/ui/dialog.tsx b/clients/dashboard/src/components/ui/dialog.tsx new file mode 100644 index 0000000..95b0d38 --- /dev/null +++ b/clients/dashboard/src/components/ui/dialog.tsx @@ -0,0 +1,122 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { Cross2Icon } from "@radix-ui/react-icons" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/clients/dashboard/src/components/ui/input.tsx b/clients/dashboard/src/components/ui/input.tsx new file mode 100644 index 0000000..5af26b2 --- /dev/null +++ b/clients/dashboard/src/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } diff --git a/clients/dashboard/src/components/ui/label.tsx b/clients/dashboard/src/components/ui/label.tsx new file mode 100644 index 0000000..5341821 --- /dev/null +++ b/clients/dashboard/src/components/ui/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" +) + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)) +Label.displayName = LabelPrimitive.Root.displayName + +export { Label } diff --git a/clients/dashboard/src/components/ui/select.tsx b/clients/dashboard/src/components/ui/select.tsx new file mode 100644 index 0000000..3c20a71 --- /dev/null +++ b/clients/dashboard/src/components/ui/select.tsx @@ -0,0 +1,160 @@ +"use client" + +import * as React from "react" +import * as SelectPrimitive from "@radix-ui/react-select" +import { Check, ChevronDown, ChevronUp } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Select = SelectPrimitive.Root + +const SelectGroup = SelectPrimitive.Group + +const SelectValue = SelectPrimitive.Value + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className + )} + {...props} + > + {children} + + + + +)) +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)) +SelectContent.displayName = SelectPrimitive.Content.displayName + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectLabel.displayName = SelectPrimitive.Label.displayName + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + + {children} + +)) +SelectItem.displayName = SelectPrimitive.Item.displayName + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectSeparator.displayName = SelectPrimitive.Separator.displayName + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +} diff --git a/clients/dashboard/src/components/ui/sheet.tsx b/clients/dashboard/src/components/ui/sheet.tsx new file mode 100644 index 0000000..417e7e1 --- /dev/null +++ b/clients/dashboard/src/components/ui/sheet.tsx @@ -0,0 +1,140 @@ +"use client" + +import * as React from "react" +import * as SheetPrimitive from "@radix-ui/react-dialog" +import { Cross2Icon } from "@radix-ui/react-icons" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const Sheet = SheetPrimitive.Root + +const SheetTrigger = SheetPrimitive.Trigger + +const SheetClose = SheetPrimitive.Close + +const SheetPortal = SheetPrimitive.Portal + +const SheetOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetOverlay.displayName = SheetPrimitive.Overlay.displayName + +const sheetVariants = cva( + "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out", + { + variants: { + side: { + top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", + bottom: + "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", + left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", + right: + "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", + }, + }, + defaultVariants: { + side: "right", + }, + } +) + +interface SheetContentProps + extends React.ComponentPropsWithoutRef, + VariantProps {} + +const SheetContent = React.forwardRef< + React.ElementRef, + SheetContentProps +>(({ side = "right", className, children, ...props }, ref) => ( + + + + + + Close + + {children} + + +)) +SheetContent.displayName = SheetPrimitive.Content.displayName + +const SheetHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +SheetHeader.displayName = "SheetHeader" + +const SheetFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +SheetFooter.displayName = "SheetFooter" + +const SheetTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetTitle.displayName = SheetPrimitive.Title.displayName + +const SheetDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetDescription.displayName = SheetPrimitive.Description.displayName + +export { + Sheet, + SheetPortal, + SheetOverlay, + SheetTrigger, + SheetClose, + SheetContent, + SheetHeader, + SheetFooter, + SheetTitle, + SheetDescription, +} diff --git a/clients/dashboard/src/components/ui/table.tsx b/clients/dashboard/src/components/ui/table.tsx new file mode 100644 index 0000000..c0df655 --- /dev/null +++ b/clients/dashboard/src/components/ui/table.tsx @@ -0,0 +1,120 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className + )} + {...props} + /> +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
[role=checkbox]]:translate-y-[2px]", + className + )} + {...props} + /> +)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + [role=checkbox]]:translate-y-[2px]", + className + )} + {...props} + /> +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +} diff --git a/clients/dashboard/src/constant/config.ts b/clients/dashboard/src/constant/config.ts new file mode 100644 index 0000000..a1cfa14 --- /dev/null +++ b/clients/dashboard/src/constant/config.ts @@ -0,0 +1,7 @@ +export const siteConfig = { + title: 'Next.js + Tailwind CSS + TypeScript Starter', + description: + 'A starter for Next.js, Tailwind CSS, and TypeScript with Absolute Import, Seo, Link component, pre-configured with Husky', + /** Without additional '/' on the end, e.g. https://theodorusclarence.com */ + url: 'https://tsnext-tw.thcl.dev', +}; diff --git a/clients/dashboard/src/constant/env.ts b/clients/dashboard/src/constant/env.ts new file mode 100644 index 0000000..8cd8ab5 --- /dev/null +++ b/clients/dashboard/src/constant/env.ts @@ -0,0 +1,6 @@ +export const isProd = process.env.NODE_ENV === 'production'; +export const isLocal = process.env.NODE_ENV === 'development'; + +export const showLogger = isLocal + ? true + : process.env.NEXT_PUBLIC_SHOW_LOGGER === 'true' ?? false; diff --git a/clients/dashboard/src/lib/env.ts b/clients/dashboard/src/lib/env.ts new file mode 100644 index 0000000..9f1a3e3 --- /dev/null +++ b/clients/dashboard/src/lib/env.ts @@ -0,0 +1,20 @@ +/* eslint-disable @typescript-eslint/no-namespace */ +/** + * Configuration for type-safe environment variables. + * Imported through src/app/page.tsx + * @see https://x.com/mattpocockuk/status/1760991147793449396 + */ +import { z } from 'zod'; + +const envVariables = z.object({ + NEXT_PUBLIC_SHOW_LOGGER: z.enum(['true', 'false']).optional(), +}); + +envVariables.parse(process.env); + +declare global { + namespace NodeJS { + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface ProcessEnv extends z.infer {} + } +} diff --git a/clients/dashboard/src/lib/helper.ts b/clients/dashboard/src/lib/helper.ts new file mode 100644 index 0000000..91ffd55 --- /dev/null +++ b/clients/dashboard/src/lib/helper.ts @@ -0,0 +1,13 @@ +export function getFromLocalStorage(key: string): string | null { + if (typeof window !== 'undefined') { + return window.localStorage.getItem(key); + } + return null; +} + +export function getFromSessionStorage(key: string): string | null { + if (typeof sessionStorage !== 'undefined') { + return sessionStorage.getItem(key); + } + return null; +} diff --git a/clients/dashboard/src/lib/logger.ts b/clients/dashboard/src/lib/logger.ts new file mode 100644 index 0000000..68ea99e --- /dev/null +++ b/clients/dashboard/src/lib/logger.ts @@ -0,0 +1,19 @@ +/* eslint-disable no-console */ +import { showLogger } from '@/constant/env'; + +/** + * A logger function that will only logs on development + * @param object - The object to log + * @param comment - Autogenerated with `lg` snippet + */ +export default function logger(object: unknown, comment?: string): void { + if (!showLogger) return; + + console.log( + '%c ============== INFO LOG \n', + 'color: #22D3EE', + `${typeof window !== 'undefined' && window?.location.pathname}\n`, + `=== ${comment ?? ''}\n`, + object + ); +} diff --git a/clients/dashboard/src/lib/og.ts b/clients/dashboard/src/lib/og.ts new file mode 100644 index 0000000..76cd32f --- /dev/null +++ b/clients/dashboard/src/lib/og.ts @@ -0,0 +1,27 @@ +type OpenGraphType = { + siteName: string; + description: string; + templateTitle?: string; + logo?: string; +}; +// !STARTERCONF This OG is generated from https://github.com/theodorusclarence/og +// Please clone them and self-host if your site is going to be visited by many people. +// Then change the url and the default logo. +export function openGraph({ + siteName, + templateTitle, + description, + // !STARTERCONF Or, you can use my server with your own logo. + logo = 'https://og./images/logo.jpg', +}: OpenGraphType): string { + const ogLogo = encodeURIComponent(logo); + const ogSiteName = encodeURIComponent(siteName.trim()); + const ogTemplateTitle = templateTitle + ? encodeURIComponent(templateTitle.trim()) + : undefined; + const ogDesc = encodeURIComponent(description.trim()); + + return `https://og./api/general?siteName=${ogSiteName}&description=${ogDesc}&logo=${ogLogo}${ + ogTemplateTitle ? `&templateTitle=${ogTemplateTitle}` : '' + }`; +} diff --git a/clients/dashboard/src/lib/utils.ts b/clients/dashboard/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/clients/dashboard/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/clients/dashboard/src/styles/colors.css b/clients/dashboard/src/styles/colors.css new file mode 100644 index 0000000..76a0760 --- /dev/null +++ b/clients/dashboard/src/styles/colors.css @@ -0,0 +1,550 @@ +/* //!STARTERCONF Remove this file after copying your desired color, this is a large file you should remove it. */ + +.slate { + --tw-color-primary-50: 248 250 252; + --tw-color-primary-100: 241 245 249; + --tw-color-primary-200: 226 232 240; + --tw-color-primary-300: 203 213 225; + --tw-color-primary-400: 148 163 184; + --tw-color-primary-500: 100 116 139; + --tw-color-primary-600: 71 85 105; + --tw-color-primary-700: 51 65 85; + --tw-color-primary-800: 30 41 59; + --tw-color-primary-900: 15 23 42; + --tw-color-primary-950: 2 6 23; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #f8fafc */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #f1f5f9 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #e2e8f0 */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #cbd5e1 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #94a3b8 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #64748b */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #475569 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #334155 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #1e293b */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #0f172a */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #020617 */ +} + +.gray { + --tw-color-primary-50: 249 250 251; + --tw-color-primary-100: 243 244 246; + --tw-color-primary-200: 229 231 235; + --tw-color-primary-300: 209 213 219; + --tw-color-primary-400: 156 163 175; + --tw-color-primary-500: 107 114 128; + --tw-color-primary-600: 75 85 99; + --tw-color-primary-700: 55 65 81; + --tw-color-primary-800: 31 41 55; + --tw-color-primary-900: 17 24 39; + --tw-color-primary-950: 3 7 18; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #f9fafb */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #f3f4f6 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #e5e7eb */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #d1d5db */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #9ca3af */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #6b7280 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #4b5563 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #374151 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #1f2937 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #111827 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #030712 */ +} + +.zinc { + --tw-color-primary-50: 250 250 250; + --tw-color-primary-100: 244 244 245; + --tw-color-primary-200: 228 228 231; + --tw-color-primary-300: 212 212 216; + --tw-color-primary-400: 161 161 170; + --tw-color-primary-500: 113 113 122; + --tw-color-primary-600: 82 82 91; + --tw-color-primary-700: 63 63 70; + --tw-color-primary-800: 39 39 42; + --tw-color-primary-900: 24 24 27; + --tw-color-primary-950: 9 9 11; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #fafafa */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #f4f4f5 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #e4e4e7 */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #d4d4d8 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #a1a1aa */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #71717a */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #52525b */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #3f3f46 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #27272a */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #18181b */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #09090b */ +} + +.neutral { + --tw-color-primary-50: 250 250 250; + --tw-color-primary-100: 245 245 245; + --tw-color-primary-200: 229 229 229; + --tw-color-primary-300: 212 212 212; + --tw-color-primary-400: 163 163 163; + --tw-color-primary-500: 115 115 115; + --tw-color-primary-600: 82 82 82; + --tw-color-primary-700: 64 64 64; + --tw-color-primary-800: 38 38 38; + --tw-color-primary-900: 23 23 23; + --tw-color-primary-950: 10 10 10; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #fafafa */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #f5f5f5 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #e5e5e5 */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #d4d4d4 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #a3a3a3 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #737373 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #525252 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #404040 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #262626 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #171717 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #0a0a0a */ +} + +.stone { + --tw-color-primary-50: 250 250 249; + --tw-color-primary-100: 245 245 244; + --tw-color-primary-200: 231 229 228; + --tw-color-primary-300: 214 211 209; + --tw-color-primary-400: 168 162 158; + --tw-color-primary-500: 120 113 108; + --tw-color-primary-600: 87 83 78; + --tw-color-primary-700: 68 64 60; + --tw-color-primary-800: 41 37 36; + --tw-color-primary-900: 28 25 23; + --tw-color-primary-950: 12 10 9; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #fafaf9 */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #f5f5f4 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #e7e5e4 */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #d6d3d1 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #a8a29e */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #78716c */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #57534e */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #44403c */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #292524 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #1c1917 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #0c0a09 */ +} + +.red { + --tw-color-primary-50: 254 242 242; + --tw-color-primary-100: 254 226 226; + --tw-color-primary-200: 254 202 202; + --tw-color-primary-300: 252 165 165; + --tw-color-primary-400: 248 113 113; + --tw-color-primary-500: 239 68 68; + --tw-color-primary-600: 220 38 38; + --tw-color-primary-700: 185 28 28; + --tw-color-primary-800: 153 27 27; + --tw-color-primary-900: 127 29 29; + --tw-color-primary-950: 69 10 10; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #fef2f2 */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #fee2e2 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #fecaca */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #fca5a5 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #f87171 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #ef4444 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #dc2626 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #b91c1c */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #991b1b */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #7f1d1d */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #450a0a */ +} + +.orange { + --tw-color-primary-50: 255 247 237; + --tw-color-primary-100: 255 237 213; + --tw-color-primary-200: 254 215 170; + --tw-color-primary-300: 253 186 116; + --tw-color-primary-400: 251 146 60; + --tw-color-primary-500: 249 115 22; + --tw-color-primary-600: 234 88 12; + --tw-color-primary-700: 194 65 12; + --tw-color-primary-800: 154 52 18; + --tw-color-primary-900: 124 45 18; + --tw-color-primary-950: 67 20 7; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #fff7ed */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #ffedd5 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #fed7aa */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #fdba74 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #fb923c */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #f97316 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #ea580c */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #c2410c */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #9a3412 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #7c2d12 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #431407 */ +} + +.amber { + --tw-color-primary-50: 255 251 235; + --tw-color-primary-100: 254 243 199; + --tw-color-primary-200: 253 230 138; + --tw-color-primary-300: 252 211 77; + --tw-color-primary-400: 251 191 36; + --tw-color-primary-500: 245 158 11; + --tw-color-primary-600: 217 119 6; + --tw-color-primary-700: 180 83 9; + --tw-color-primary-800: 146 64 14; + --tw-color-primary-900: 120 53 15; + --tw-color-primary-950: 69 26 3; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #fffbeb */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #fef3c7 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #fde68a */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #fcd34d */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #fbbf24 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #f59e0b */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #d97706 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #b45309 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #92400e */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #78350f */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #451a03 */ +} + +.yellow { + --tw-color-primary-50: 254 252 232; + --tw-color-primary-100: 254 249 195; + --tw-color-primary-200: 254 240 138; + --tw-color-primary-300: 253 224 71; + --tw-color-primary-400: 250 204 21; + --tw-color-primary-500: 234 179 8; + --tw-color-primary-600: 202 138 4; + --tw-color-primary-700: 161 98 7; + --tw-color-primary-800: 133 77 14; + --tw-color-primary-900: 113 63 18; + --tw-color-primary-950: 66 32 6; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #fefce8 */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #fef9c3 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #fef08a */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #fde047 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #facc15 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #eab308 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #ca8a04 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #a16207 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #854d0e */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #713f12 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #422006 */ +} +.lime { + --tw-color-primary-50: 247 254 231; + --tw-color-primary-100: 236 252 203; + --tw-color-primary-200: 217 249 157; + --tw-color-primary-300: 190 242 100; + --tw-color-primary-400: 163 230 53; + --tw-color-primary-500: 132 204 22; + --tw-color-primary-600: 101 163 13; + --tw-color-primary-700: 77 124 15; + --tw-color-primary-800: 63 98 18; + --tw-color-primary-900: 54 83 20; + --tw-color-primary-950: 26 46 5; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #f7fee7 */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #ecfccb */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #d9f99d */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #bef264 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #a3e635 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #84cc16 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #65a30d */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #4d7c0f */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #3f6212 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #365314 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #1a2e05 */ +} + +.green { + --tw-color-primary-50: 240 253 244; + --tw-color-primary-100: 220 252 231; + --tw-color-primary-200: 187 247 208; + --tw-color-primary-300: 134 239 172; + --tw-color-primary-400: 74 222 128; + --tw-color-primary-500: 34 197 94; + --tw-color-primary-600: 22 163 74; + --tw-color-primary-700: 21 128 61; + --tw-color-primary-800: 22 101 52; + --tw-color-primary-900: 20 83 45; + --tw-color-primary-950: 5 46 22; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #f0fdf4 */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #dcfce7 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #bbf7d0 */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #86efac */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #4ade80 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #22c55e */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #16a34a */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #15803d */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #166534 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #14532d */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #052e16 */ +} + +.emerald { + --tw-color-primary-50: 236 253 245; + --tw-color-primary-100: 209 250 229; + --tw-color-primary-200: 167 243 208; + --tw-color-primary-300: 110 231 183; + --tw-color-primary-400: 52 211 153; + --tw-color-primary-500: 16 185 129; + --tw-color-primary-600: 5 150 105; + --tw-color-primary-700: 4 120 87; + --tw-color-primary-800: 6 95 70; + --tw-color-primary-900: 6 78 59; + --tw-color-primary-950: 2 44 34; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #ecfdf5 */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #d1fae5 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #a7f3d0 */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #6ee7b7 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #34d399 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #10b981 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #059669 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #047857 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #065f46 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #064e3b */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #022c22 */ +} + +.teal { + --tw-color-primary-50: 240 253 250; + --tw-color-primary-100: 204 251 241; + --tw-color-primary-200: 153 246 228; + --tw-color-primary-300: 94 234 212; + --tw-color-primary-400: 45 212 191; + --tw-color-primary-500: 20 184 166; + --tw-color-primary-600: 13 148 136; + --tw-color-primary-700: 15 118 110; + --tw-color-primary-800: 17 94 89; + --tw-color-primary-900: 19 78 74; + --tw-color-primary-950: 4 47 46; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #f0fdfa */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #ccfbf1 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #99f6e4 */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #5eead4 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #2dd4bf */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #14b8a6 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #0d9488 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #0f766e */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #115e59 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #134e4a */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #042f2e */ +} + +.cyan { + --tw-color-primary-50: 236 254 255; + --tw-color-primary-100: 207 250 254; + --tw-color-primary-200: 165 243 252; + --tw-color-primary-300: 103 232 249; + --tw-color-primary-400: 34 211 238; + --tw-color-primary-500: 6 182 212; + --tw-color-primary-600: 8 145 178; + --tw-color-primary-700: 14 116 144; + --tw-color-primary-800: 21 94 117; + --tw-color-primary-900: 22 78 99; + --tw-color-primary-950: 8 51 68; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #ecfeff */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #cffafe */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #a5f3fc */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #67e8f9 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #22d3ee */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #06b6d4 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #0891b2 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #0e7490 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #155e75 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #164e63 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #083344 */ +} + +.sky { + --tw-color-primary-50: 240 249 255; + --tw-color-primary-100: 224 242 254; + --tw-color-primary-200: 186 230 253; + --tw-color-primary-300: 125 211 252; + --tw-color-primary-400: 56 189 248; + --tw-color-primary-500: 14 165 233; + --tw-color-primary-600: 2 132 199; + --tw-color-primary-700: 3 105 161; + --tw-color-primary-800: 7 89 133; + --tw-color-primary-900: 12 74 110; + --tw-color-primary-950: 8 47 73; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #f0f9ff */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #e0f2fe */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #bae6fd */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #7dd3fc */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #38bdf8 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #0ea5e9 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #0284c7 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #0369a1 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #075985 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #0c4a6e */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #082f49 */ +} + +.blue { + --tw-color-primary-50: 239 246 255; + --tw-color-primary-100: 219 234 254; + --tw-color-primary-200: 191 219 254; + --tw-color-primary-300: 147 197 253; + --tw-color-primary-400: 96 165 250; + --tw-color-primary-500: 59 130 246; + --tw-color-primary-600: 37 99 235; + --tw-color-primary-700: 29 78 216; + --tw-color-primary-800: 30 64 175; + --tw-color-primary-900: 30 58 138; + --tw-color-primary-950: 23 37 84; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #eff6ff */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #dbeafe */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #bfdbfe */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #93c5fd */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #60a5fa */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #3b82f6 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #2563eb */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #1d4ed8 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #1e40af */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #1e3a8a */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #172554 */ +} + +.indigo { + --tw-color-primary-50: 238 242 255; + --tw-color-primary-100: 224 231 255; + --tw-color-primary-200: 199 210 254; + --tw-color-primary-300: 165 180 252; + --tw-color-primary-400: 129 140 248; + --tw-color-primary-500: 99 102 241; + --tw-color-primary-600: 79 70 229; + --tw-color-primary-700: 67 56 202; + --tw-color-primary-800: 55 48 163; + --tw-color-primary-900: 49 46 129; + --tw-color-primary-950: 30 27 75; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #eef2ff */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #e0e7ff */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #c7d2fe */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #a5b4fc */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #818cf8 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #6366f1 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #4f46e5 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #4338ca */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #3730a3 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #312e81 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #1e1b4b */ +} + +.violet { + --tw-color-primary-50: 245 243 255; + --tw-color-primary-100: 237 233 254; + --tw-color-primary-200: 221 214 254; + --tw-color-primary-300: 196 181 253; + --tw-color-primary-400: 167 139 250; + --tw-color-primary-500: 139 92 246; + --tw-color-primary-600: 124 58 237; + --tw-color-primary-700: 109 40 217; + --tw-color-primary-800: 91 33 182; + --tw-color-primary-900: 76 29 149; + --tw-color-primary-950: 46 16 101; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #f5f3ff */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #ede9fe */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #ddd6fe */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #c4b5fd */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #a78bfa */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #8b5cf6 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #7c3aed */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #6d28d9 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #5b21b6 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #4c1d95 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #2e1065 */ +} + +.purple { + --tw-color-primary-50: 250 245 255; + --tw-color-primary-100: 243 232 255; + --tw-color-primary-200: 233 213 255; + --tw-color-primary-300: 216 180 254; + --tw-color-primary-400: 192 132 252; + --tw-color-primary-500: 168 85 247; + --tw-color-primary-600: 147 51 234; + --tw-color-primary-700: 126 34 206; + --tw-color-primary-800: 107 33 168; + --tw-color-primary-900: 88 28 135; + --tw-color-primary-950: 59 7 100; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #faf5ff */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #f3e8ff */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #e9d5ff */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #d8b4fe */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #c084fc */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #a855f7 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #9333ea */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #7e22ce */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #6b21a8 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #581c87 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #3b0764 */ +} + +.fuchsia { + --tw-color-primary-50: 253 244 255; + --tw-color-primary-100: 250 232 255; + --tw-color-primary-200: 245 208 254; + --tw-color-primary-300: 240 171 252; + --tw-color-primary-400: 232 121 249; + --tw-color-primary-500: 217 70 239; + --tw-color-primary-600: 192 38 211; + --tw-color-primary-700: 162 28 175; + --tw-color-primary-800: 134 25 143; + --tw-color-primary-900: 112 26 117; + --tw-color-primary-950: 74 4 78; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #fdf4ff */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #fae8ff */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #f5d0fe */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #f0abfc */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #e879f9 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #d946ef */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #c026d3 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #a21caf */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #86198f */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #701a75 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #4a044e */ +} + +.pink { + --tw-color-primary-50: 253 242 248; + --tw-color-primary-100: 252 231 243; + --tw-color-primary-200: 251 207 232; + --tw-color-primary-300: 249 168 212; + --tw-color-primary-400: 244 114 182; + --tw-color-primary-500: 236 72 153; + --tw-color-primary-600: 219 39 119; + --tw-color-primary-700: 190 24 93; + --tw-color-primary-800: 157 23 77; + --tw-color-primary-900: 131 24 67; + --tw-color-primary-950: 80 4 36; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #fdf2f8 */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #fce7f3 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #fbcfe8 */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #f9a8d4 */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #f472b6 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #ec4899 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #db2777 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #be185d */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #9d174d */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #831843 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #500724 */ +} + +.rose { + --tw-color-primary-50: 255 241 242; + --tw-color-primary-100: 255 228 230; + --tw-color-primary-200: 254 205 211; + --tw-color-primary-300: 253 164 175; + --tw-color-primary-400: 251 113 133; + --tw-color-primary-500: 244 63 94; + --tw-color-primary-600: 225 29 72; + --tw-color-primary-700: 190 18 60; + --tw-color-primary-800: 159 18 57; + --tw-color-primary-900: 136 19 55; + --tw-color-primary-950: 76 5 25; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #fff1f2 */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #ffe4e6 */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #fecdd3 */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #fda4af */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #fb7185 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #f43f5e */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #e11d48 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #be123c */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #9f1239 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #881337 */ + --color-primary-950: rgb(var(--tw-color-primary-950)); /* #4c0519 */ +} diff --git a/clients/dashboard/src/styles/globals.css b/clients/dashboard/src/styles/globals.css new file mode 100644 index 0000000..d689db9 --- /dev/null +++ b/clients/dashboard/src/styles/globals.css @@ -0,0 +1,180 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + /* #region /**=========== Primary Color =========== */ + /* !STARTERCONF Customize these variable, copy and paste from /styles/colors.css for list of colors */ + --tw-color-primary-50: 240 249 255; + --tw-color-primary-100: 224 242 254; + --tw-color-primary-200: 186 230 253; + --tw-color-primary-300: 125 211 252; + --tw-color-primary-400: 56 189 248; + --tw-color-primary-500: 14 165 233; + --tw-color-primary-600: 2 132 199; + --tw-color-primary-700: 3 105 161; + --tw-color-primary-800: 7 89 133; + --tw-color-primary-900: 12 74 110; + --color-primary-50: rgb(var(--tw-color-primary-50)); /* #f0f9ff */ + --color-primary-100: rgb(var(--tw-color-primary-100)); /* #e0f2fe */ + --color-primary-200: rgb(var(--tw-color-primary-200)); /* #bae6fd */ + --color-primary-300: rgb(var(--tw-color-primary-300)); /* #7dd3fc */ + --color-primary-400: rgb(var(--tw-color-primary-400)); /* #38bdf8 */ + --color-primary-500: rgb(var(--tw-color-primary-500)); /* #0ea5e9 */ + --color-primary-600: rgb(var(--tw-color-primary-600)); /* #0284c7 */ + --color-primary-700: rgb(var(--tw-color-primary-700)); /* #0369a1 */ + --color-primary-800: rgb(var(--tw-color-primary-800)); /* #075985 */ + --color-primary-900: rgb(var(--tw-color-primary-900)); /* #0c4a6e */ + /* #endregion /**======== Primary Color =========== */ +} + +@layer base { + /* inter var - latin */ + @font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 100 900; + font-display: block; + src: url('/fonts/inter-var-latin.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; + } + + .cursor-newtab { + cursor: url('/images/new-tab.png') 10 10, pointer; + } + + /* #region /**=========== Typography =========== */ + .h0 { + @apply font-primary text-3xl font-bold md:text-5xl; + } + + h1, + .h1 { + @apply font-primary text-2xl font-bold md:text-4xl; + } + + h2, + .h2 { + @apply font-primary text-xl font-bold md:text-3xl; + } + + h3, + .h3 { + @apply font-primary text-lg font-bold md:text-2xl; + } + + h4, + .h4 { + @apply font-primary text-base font-bold md:text-lg; + } + + body, + .p { + @apply font-primary text-sm md:text-base; + } + /* #endregion /**======== Typography =========== */ + + .layout { + /* 1100px */ + max-width: 68.75rem; + @apply mx-auto w-11/12; + } + + .bg-dark a.custom-link { + @apply border-gray-200 hover:border-gray-200/0; + } + + /* Class to adjust with sticky footer */ + .min-h-main { + @apply min-h-[calc(100vh-56px)]; + } + :root { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + --primary: 0 0% 9%; + --primary-foreground: 0 0% 98%; + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + --ring: 0 0% 3.9%; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + --radius: 0.5rem; + } + .dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + --ring: 0 0% 83.1%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } +} + +@layer utilities { + .animated-underline { + background-image: linear-gradient(#33333300, #33333300), + linear-gradient( + to right, + var(--color-primary-400), + var(--color-primary-500) + ); + background-size: 100% 2px, 0 2px; + background-position: 100% 100%, 0 100%; + background-repeat: no-repeat; + } + @media (prefers-reduced-motion: no-preference) { + .animated-underline { + transition: 0.3s ease; + transition-property: background-size, color, background-color, + border-color; + } + } + .animated-underline:hover, + .animated-underline:focus-visible { + background-size: 0 2px, 100% 2px; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/clients/dashboard/src/validate/validate_pb.ts b/clients/dashboard/src/validate/validate_pb.ts new file mode 100644 index 0000000..321d73f --- /dev/null +++ b/clients/dashboard/src/validate/validate_pb.ts @@ -0,0 +1,2621 @@ +// @generated by protoc-gen-es v1.10.0 with parameter "target=ts,import_extension=none" +// @generated from file validate/validate.proto (package validate, syntax proto2) +/* eslint-disable */ +// @ts-nocheck + +import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; +import { Duration, FieldOptions, Message, MessageOptions, OneofOptions, proto2, Timestamp } from "@bufbuild/protobuf"; + +/** + * WellKnownRegex contain some well-known patterns. + * + * @generated from enum validate.KnownRegex + */ +export enum KnownRegex { + /** + * @generated from enum value: UNKNOWN = 0; + */ + UNKNOWN = 0, + + /** + * HTTP header name as defined by RFC 7230. + * + * @generated from enum value: HTTP_HEADER_NAME = 1; + */ + HTTP_HEADER_NAME = 1, + + /** + * HTTP header value as defined by RFC 7230. + * + * @generated from enum value: HTTP_HEADER_VALUE = 2; + */ + HTTP_HEADER_VALUE = 2, +} +// Retrieve enum metadata with: proto2.getEnumType(KnownRegex) +proto2.util.setEnumType(KnownRegex, "validate.KnownRegex", [ + { no: 0, name: "UNKNOWN" }, + { no: 1, name: "HTTP_HEADER_NAME" }, + { no: 2, name: "HTTP_HEADER_VALUE" }, +]); + +/** + * FieldRules encapsulates the rules for each type of field. Depending on the + * field, the correct set should be used to ensure proper validations. + * + * @generated from message validate.FieldRules + */ +export class FieldRules extends Message { + /** + * @generated from field: optional validate.MessageRules message = 17; + */ + message?: MessageRules; + + /** + * @generated from oneof validate.FieldRules.type + */ + type: { + /** + * Scalar Field Types + * + * @generated from field: validate.FloatRules float = 1; + */ + value: FloatRules; + case: "float"; + } | { + /** + * @generated from field: validate.DoubleRules double = 2; + */ + value: DoubleRules; + case: "double"; + } | { + /** + * @generated from field: validate.Int32Rules int32 = 3; + */ + value: Int32Rules; + case: "int32"; + } | { + /** + * @generated from field: validate.Int64Rules int64 = 4; + */ + value: Int64Rules; + case: "int64"; + } | { + /** + * @generated from field: validate.UInt32Rules uint32 = 5; + */ + value: UInt32Rules; + case: "uint32"; + } | { + /** + * @generated from field: validate.UInt64Rules uint64 = 6; + */ + value: UInt64Rules; + case: "uint64"; + } | { + /** + * @generated from field: validate.SInt32Rules sint32 = 7; + */ + value: SInt32Rules; + case: "sint32"; + } | { + /** + * @generated from field: validate.SInt64Rules sint64 = 8; + */ + value: SInt64Rules; + case: "sint64"; + } | { + /** + * @generated from field: validate.Fixed32Rules fixed32 = 9; + */ + value: Fixed32Rules; + case: "fixed32"; + } | { + /** + * @generated from field: validate.Fixed64Rules fixed64 = 10; + */ + value: Fixed64Rules; + case: "fixed64"; + } | { + /** + * @generated from field: validate.SFixed32Rules sfixed32 = 11; + */ + value: SFixed32Rules; + case: "sfixed32"; + } | { + /** + * @generated from field: validate.SFixed64Rules sfixed64 = 12; + */ + value: SFixed64Rules; + case: "sfixed64"; + } | { + /** + * @generated from field: validate.BoolRules bool = 13; + */ + value: BoolRules; + case: "bool"; + } | { + /** + * @generated from field: validate.StringRules string = 14; + */ + value: StringRules; + case: "string"; + } | { + /** + * @generated from field: validate.BytesRules bytes = 15; + */ + value: BytesRules; + case: "bytes"; + } | { + /** + * Complex Field Types + * + * @generated from field: validate.EnumRules enum = 16; + */ + value: EnumRules; + case: "enum"; + } | { + /** + * @generated from field: validate.RepeatedRules repeated = 18; + */ + value: RepeatedRules; + case: "repeated"; + } | { + /** + * @generated from field: validate.MapRules map = 19; + */ + value: MapRules; + case: "map"; + } | { + /** + * Well-Known Field Types + * + * @generated from field: validate.AnyRules any = 20; + */ + value: AnyRules; + case: "any"; + } | { + /** + * @generated from field: validate.DurationRules duration = 21; + */ + value: DurationRules; + case: "duration"; + } | { + /** + * @generated from field: validate.TimestampRules timestamp = 22; + */ + value: TimestampRules; + case: "timestamp"; + } | { case: undefined; value?: undefined } = { case: undefined }; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.FieldRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 17, name: "message", kind: "message", T: MessageRules, opt: true }, + { no: 1, name: "float", kind: "message", T: FloatRules, oneof: "type" }, + { no: 2, name: "double", kind: "message", T: DoubleRules, oneof: "type" }, + { no: 3, name: "int32", kind: "message", T: Int32Rules, oneof: "type" }, + { no: 4, name: "int64", kind: "message", T: Int64Rules, oneof: "type" }, + { no: 5, name: "uint32", kind: "message", T: UInt32Rules, oneof: "type" }, + { no: 6, name: "uint64", kind: "message", T: UInt64Rules, oneof: "type" }, + { no: 7, name: "sint32", kind: "message", T: SInt32Rules, oneof: "type" }, + { no: 8, name: "sint64", kind: "message", T: SInt64Rules, oneof: "type" }, + { no: 9, name: "fixed32", kind: "message", T: Fixed32Rules, oneof: "type" }, + { no: 10, name: "fixed64", kind: "message", T: Fixed64Rules, oneof: "type" }, + { no: 11, name: "sfixed32", kind: "message", T: SFixed32Rules, oneof: "type" }, + { no: 12, name: "sfixed64", kind: "message", T: SFixed64Rules, oneof: "type" }, + { no: 13, name: "bool", kind: "message", T: BoolRules, oneof: "type" }, + { no: 14, name: "string", kind: "message", T: StringRules, oneof: "type" }, + { no: 15, name: "bytes", kind: "message", T: BytesRules, oneof: "type" }, + { no: 16, name: "enum", kind: "message", T: EnumRules, oneof: "type" }, + { no: 18, name: "repeated", kind: "message", T: RepeatedRules, oneof: "type" }, + { no: 19, name: "map", kind: "message", T: MapRules, oneof: "type" }, + { no: 20, name: "any", kind: "message", T: AnyRules, oneof: "type" }, + { no: 21, name: "duration", kind: "message", T: DurationRules, oneof: "type" }, + { no: 22, name: "timestamp", kind: "message", T: TimestampRules, oneof: "type" }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): FieldRules { + return new FieldRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): FieldRules { + return new FieldRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): FieldRules { + return new FieldRules().fromJsonString(jsonString, options); + } + + static equals(a: FieldRules | PlainMessage | undefined, b: FieldRules | PlainMessage | undefined): boolean { + return proto2.util.equals(FieldRules, a, b); + } +} + +/** + * FloatRules describes the constraints applied to `float` values + * + * @generated from message validate.FloatRules + */ +export class FloatRules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional float const = 1; + */ + const?: number; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional float lt = 2; + */ + lt?: number; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional float lte = 3; + */ + lte?: number; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional float gt = 4; + */ + gt?: number; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional float gte = 5; + */ + gte?: number; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated float in = 6; + */ + in: number[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated float not_in = 7; + */ + notIn: number[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.FloatRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 2 /* ScalarType.FLOAT */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 2 /* ScalarType.FLOAT */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): FloatRules { + return new FloatRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): FloatRules { + return new FloatRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): FloatRules { + return new FloatRules().fromJsonString(jsonString, options); + } + + static equals(a: FloatRules | PlainMessage | undefined, b: FloatRules | PlainMessage | undefined): boolean { + return proto2.util.equals(FloatRules, a, b); + } +} + +/** + * DoubleRules describes the constraints applied to `double` values + * + * @generated from message validate.DoubleRules + */ +export class DoubleRules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional double const = 1; + */ + const?: number; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional double lt = 2; + */ + lt?: number; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional double lte = 3; + */ + lte?: number; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional double gt = 4; + */ + gt?: number; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional double gte = 5; + */ + gte?: number; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated double in = 6; + */ + in: number[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated double not_in = 7; + */ + notIn: number[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.DoubleRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): DoubleRules { + return new DoubleRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): DoubleRules { + return new DoubleRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): DoubleRules { + return new DoubleRules().fromJsonString(jsonString, options); + } + + static equals(a: DoubleRules | PlainMessage | undefined, b: DoubleRules | PlainMessage | undefined): boolean { + return proto2.util.equals(DoubleRules, a, b); + } +} + +/** + * Int32Rules describes the constraints applied to `int32` values + * + * @generated from message validate.Int32Rules + */ +export class Int32Rules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional int32 const = 1; + */ + const?: number; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional int32 lt = 2; + */ + lt?: number; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional int32 lte = 3; + */ + lte?: number; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional int32 gt = 4; + */ + gt?: number; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional int32 gte = 5; + */ + gte?: number; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated int32 in = 6; + */ + in: number[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated int32 not_in = 7; + */ + notIn: number[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.Int32Rules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Int32Rules { + return new Int32Rules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Int32Rules { + return new Int32Rules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Int32Rules { + return new Int32Rules().fromJsonString(jsonString, options); + } + + static equals(a: Int32Rules | PlainMessage | undefined, b: Int32Rules | PlainMessage | undefined): boolean { + return proto2.util.equals(Int32Rules, a, b); + } +} + +/** + * Int64Rules describes the constraints applied to `int64` values + * + * @generated from message validate.Int64Rules + */ +export class Int64Rules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional int64 const = 1; + */ + const?: bigint; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional int64 lt = 2; + */ + lt?: bigint; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional int64 lte = 3; + */ + lte?: bigint; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional int64 gt = 4; + */ + gt?: bigint; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional int64 gte = 5; + */ + gte?: bigint; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated int64 in = 6; + */ + in: bigint[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated int64 not_in = 7; + */ + notIn: bigint[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.Int64Rules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 3 /* ScalarType.INT64 */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 3 /* ScalarType.INT64 */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 3 /* ScalarType.INT64 */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 3 /* ScalarType.INT64 */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 3 /* ScalarType.INT64 */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 3 /* ScalarType.INT64 */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 3 /* ScalarType.INT64 */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Int64Rules { + return new Int64Rules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Int64Rules { + return new Int64Rules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Int64Rules { + return new Int64Rules().fromJsonString(jsonString, options); + } + + static equals(a: Int64Rules | PlainMessage | undefined, b: Int64Rules | PlainMessage | undefined): boolean { + return proto2.util.equals(Int64Rules, a, b); + } +} + +/** + * UInt32Rules describes the constraints applied to `uint32` values + * + * @generated from message validate.UInt32Rules + */ +export class UInt32Rules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional uint32 const = 1; + */ + const?: number; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional uint32 lt = 2; + */ + lt?: number; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional uint32 lte = 3; + */ + lte?: number; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional uint32 gt = 4; + */ + gt?: number; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional uint32 gte = 5; + */ + gte?: number; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated uint32 in = 6; + */ + in: number[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated uint32 not_in = 7; + */ + notIn: number[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.UInt32Rules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 13 /* ScalarType.UINT32 */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 13 /* ScalarType.UINT32 */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 13 /* ScalarType.UINT32 */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 13 /* ScalarType.UINT32 */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 13 /* ScalarType.UINT32 */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 13 /* ScalarType.UINT32 */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 13 /* ScalarType.UINT32 */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): UInt32Rules { + return new UInt32Rules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): UInt32Rules { + return new UInt32Rules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): UInt32Rules { + return new UInt32Rules().fromJsonString(jsonString, options); + } + + static equals(a: UInt32Rules | PlainMessage | undefined, b: UInt32Rules | PlainMessage | undefined): boolean { + return proto2.util.equals(UInt32Rules, a, b); + } +} + +/** + * UInt64Rules describes the constraints applied to `uint64` values + * + * @generated from message validate.UInt64Rules + */ +export class UInt64Rules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional uint64 const = 1; + */ + const?: bigint; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional uint64 lt = 2; + */ + lt?: bigint; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional uint64 lte = 3; + */ + lte?: bigint; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional uint64 gt = 4; + */ + gt?: bigint; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional uint64 gte = 5; + */ + gte?: bigint; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated uint64 in = 6; + */ + in: bigint[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated uint64 not_in = 7; + */ + notIn: bigint[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.UInt64Rules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 4 /* ScalarType.UINT64 */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 4 /* ScalarType.UINT64 */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): UInt64Rules { + return new UInt64Rules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): UInt64Rules { + return new UInt64Rules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): UInt64Rules { + return new UInt64Rules().fromJsonString(jsonString, options); + } + + static equals(a: UInt64Rules | PlainMessage | undefined, b: UInt64Rules | PlainMessage | undefined): boolean { + return proto2.util.equals(UInt64Rules, a, b); + } +} + +/** + * SInt32Rules describes the constraints applied to `sint32` values + * + * @generated from message validate.SInt32Rules + */ +export class SInt32Rules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional sint32 const = 1; + */ + const?: number; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional sint32 lt = 2; + */ + lt?: number; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional sint32 lte = 3; + */ + lte?: number; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional sint32 gt = 4; + */ + gt?: number; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional sint32 gte = 5; + */ + gte?: number; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated sint32 in = 6; + */ + in: number[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated sint32 not_in = 7; + */ + notIn: number[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.SInt32Rules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 17 /* ScalarType.SINT32 */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 17 /* ScalarType.SINT32 */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 17 /* ScalarType.SINT32 */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 17 /* ScalarType.SINT32 */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 17 /* ScalarType.SINT32 */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 17 /* ScalarType.SINT32 */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 17 /* ScalarType.SINT32 */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): SInt32Rules { + return new SInt32Rules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): SInt32Rules { + return new SInt32Rules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): SInt32Rules { + return new SInt32Rules().fromJsonString(jsonString, options); + } + + static equals(a: SInt32Rules | PlainMessage | undefined, b: SInt32Rules | PlainMessage | undefined): boolean { + return proto2.util.equals(SInt32Rules, a, b); + } +} + +/** + * SInt64Rules describes the constraints applied to `sint64` values + * + * @generated from message validate.SInt64Rules + */ +export class SInt64Rules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional sint64 const = 1; + */ + const?: bigint; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional sint64 lt = 2; + */ + lt?: bigint; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional sint64 lte = 3; + */ + lte?: bigint; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional sint64 gt = 4; + */ + gt?: bigint; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional sint64 gte = 5; + */ + gte?: bigint; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated sint64 in = 6; + */ + in: bigint[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated sint64 not_in = 7; + */ + notIn: bigint[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.SInt64Rules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 18 /* ScalarType.SINT64 */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 18 /* ScalarType.SINT64 */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 18 /* ScalarType.SINT64 */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 18 /* ScalarType.SINT64 */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 18 /* ScalarType.SINT64 */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 18 /* ScalarType.SINT64 */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 18 /* ScalarType.SINT64 */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): SInt64Rules { + return new SInt64Rules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): SInt64Rules { + return new SInt64Rules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): SInt64Rules { + return new SInt64Rules().fromJsonString(jsonString, options); + } + + static equals(a: SInt64Rules | PlainMessage | undefined, b: SInt64Rules | PlainMessage | undefined): boolean { + return proto2.util.equals(SInt64Rules, a, b); + } +} + +/** + * Fixed32Rules describes the constraints applied to `fixed32` values + * + * @generated from message validate.Fixed32Rules + */ +export class Fixed32Rules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional fixed32 const = 1; + */ + const?: number; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional fixed32 lt = 2; + */ + lt?: number; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional fixed32 lte = 3; + */ + lte?: number; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional fixed32 gt = 4; + */ + gt?: number; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional fixed32 gte = 5; + */ + gte?: number; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated fixed32 in = 6; + */ + in: number[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated fixed32 not_in = 7; + */ + notIn: number[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.Fixed32Rules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 7 /* ScalarType.FIXED32 */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 7 /* ScalarType.FIXED32 */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 7 /* ScalarType.FIXED32 */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 7 /* ScalarType.FIXED32 */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 7 /* ScalarType.FIXED32 */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 7 /* ScalarType.FIXED32 */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 7 /* ScalarType.FIXED32 */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Fixed32Rules { + return new Fixed32Rules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Fixed32Rules { + return new Fixed32Rules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Fixed32Rules { + return new Fixed32Rules().fromJsonString(jsonString, options); + } + + static equals(a: Fixed32Rules | PlainMessage | undefined, b: Fixed32Rules | PlainMessage | undefined): boolean { + return proto2.util.equals(Fixed32Rules, a, b); + } +} + +/** + * Fixed64Rules describes the constraints applied to `fixed64` values + * + * @generated from message validate.Fixed64Rules + */ +export class Fixed64Rules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional fixed64 const = 1; + */ + const?: bigint; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional fixed64 lt = 2; + */ + lt?: bigint; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional fixed64 lte = 3; + */ + lte?: bigint; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional fixed64 gt = 4; + */ + gt?: bigint; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional fixed64 gte = 5; + */ + gte?: bigint; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated fixed64 in = 6; + */ + in: bigint[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated fixed64 not_in = 7; + */ + notIn: bigint[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.Fixed64Rules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 6 /* ScalarType.FIXED64 */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 6 /* ScalarType.FIXED64 */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 6 /* ScalarType.FIXED64 */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 6 /* ScalarType.FIXED64 */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 6 /* ScalarType.FIXED64 */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 6 /* ScalarType.FIXED64 */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 6 /* ScalarType.FIXED64 */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Fixed64Rules { + return new Fixed64Rules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Fixed64Rules { + return new Fixed64Rules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Fixed64Rules { + return new Fixed64Rules().fromJsonString(jsonString, options); + } + + static equals(a: Fixed64Rules | PlainMessage | undefined, b: Fixed64Rules | PlainMessage | undefined): boolean { + return proto2.util.equals(Fixed64Rules, a, b); + } +} + +/** + * SFixed32Rules describes the constraints applied to `sfixed32` values + * + * @generated from message validate.SFixed32Rules + */ +export class SFixed32Rules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional sfixed32 const = 1; + */ + const?: number; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional sfixed32 lt = 2; + */ + lt?: number; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional sfixed32 lte = 3; + */ + lte?: number; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional sfixed32 gt = 4; + */ + gt?: number; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional sfixed32 gte = 5; + */ + gte?: number; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated sfixed32 in = 6; + */ + in: number[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated sfixed32 not_in = 7; + */ + notIn: number[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.SFixed32Rules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 15 /* ScalarType.SFIXED32 */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 15 /* ScalarType.SFIXED32 */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 15 /* ScalarType.SFIXED32 */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 15 /* ScalarType.SFIXED32 */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 15 /* ScalarType.SFIXED32 */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 15 /* ScalarType.SFIXED32 */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 15 /* ScalarType.SFIXED32 */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): SFixed32Rules { + return new SFixed32Rules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): SFixed32Rules { + return new SFixed32Rules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): SFixed32Rules { + return new SFixed32Rules().fromJsonString(jsonString, options); + } + + static equals(a: SFixed32Rules | PlainMessage | undefined, b: SFixed32Rules | PlainMessage | undefined): boolean { + return proto2.util.equals(SFixed32Rules, a, b); + } +} + +/** + * SFixed64Rules describes the constraints applied to `sfixed64` values + * + * @generated from message validate.SFixed64Rules + */ +export class SFixed64Rules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional sfixed64 const = 1; + */ + const?: bigint; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional sfixed64 lt = 2; + */ + lt?: bigint; + + /** + * Lte specifies that this field must be less than or equal to the + * specified value, inclusive + * + * @generated from field: optional sfixed64 lte = 3; + */ + lte?: bigint; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive. If the value of Gt is larger than a specified Lt or Lte, the + * range is reversed. + * + * @generated from field: optional sfixed64 gt = 4; + */ + gt?: bigint; + + /** + * Gte specifies that this field must be greater than or equal to the + * specified value, inclusive. If the value of Gte is larger than a + * specified Lt or Lte, the range is reversed. + * + * @generated from field: optional sfixed64 gte = 5; + */ + gte?: bigint; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated sfixed64 in = 6; + */ + in: bigint[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated sfixed64 not_in = 7; + */ + notIn: bigint[] = []; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 8; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.SFixed64Rules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 16 /* ScalarType.SFIXED64 */, opt: true }, + { no: 2, name: "lt", kind: "scalar", T: 16 /* ScalarType.SFIXED64 */, opt: true }, + { no: 3, name: "lte", kind: "scalar", T: 16 /* ScalarType.SFIXED64 */, opt: true }, + { no: 4, name: "gt", kind: "scalar", T: 16 /* ScalarType.SFIXED64 */, opt: true }, + { no: 5, name: "gte", kind: "scalar", T: 16 /* ScalarType.SFIXED64 */, opt: true }, + { no: 6, name: "in", kind: "scalar", T: 16 /* ScalarType.SFIXED64 */, repeated: true }, + { no: 7, name: "not_in", kind: "scalar", T: 16 /* ScalarType.SFIXED64 */, repeated: true }, + { no: 8, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): SFixed64Rules { + return new SFixed64Rules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): SFixed64Rules { + return new SFixed64Rules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): SFixed64Rules { + return new SFixed64Rules().fromJsonString(jsonString, options); + } + + static equals(a: SFixed64Rules | PlainMessage | undefined, b: SFixed64Rules | PlainMessage | undefined): boolean { + return proto2.util.equals(SFixed64Rules, a, b); + } +} + +/** + * BoolRules describes the constraints applied to `bool` values + * + * @generated from message validate.BoolRules + */ +export class BoolRules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional bool const = 1; + */ + const?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.BoolRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): BoolRules { + return new BoolRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): BoolRules { + return new BoolRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): BoolRules { + return new BoolRules().fromJsonString(jsonString, options); + } + + static equals(a: BoolRules | PlainMessage | undefined, b: BoolRules | PlainMessage | undefined): boolean { + return proto2.util.equals(BoolRules, a, b); + } +} + +/** + * StringRules describe the constraints applied to `string` values + * + * @generated from message validate.StringRules + */ +export class StringRules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional string const = 1; + */ + const?: string; + + /** + * Len specifies that this field must be the specified number of + * characters (Unicode code points). Note that the number of + * characters may differ from the number of bytes in the string. + * + * @generated from field: optional uint64 len = 19; + */ + len?: bigint; + + /** + * MinLen specifies that this field must be the specified number of + * characters (Unicode code points) at a minimum. Note that the number of + * characters may differ from the number of bytes in the string. + * + * @generated from field: optional uint64 min_len = 2; + */ + minLen?: bigint; + + /** + * MaxLen specifies that this field must be the specified number of + * characters (Unicode code points) at a maximum. Note that the number of + * characters may differ from the number of bytes in the string. + * + * @generated from field: optional uint64 max_len = 3; + */ + maxLen?: bigint; + + /** + * LenBytes specifies that this field must be the specified number of bytes + * + * @generated from field: optional uint64 len_bytes = 20; + */ + lenBytes?: bigint; + + /** + * MinBytes specifies that this field must be the specified number of bytes + * at a minimum + * + * @generated from field: optional uint64 min_bytes = 4; + */ + minBytes?: bigint; + + /** + * MaxBytes specifies that this field must be the specified number of bytes + * at a maximum + * + * @generated from field: optional uint64 max_bytes = 5; + */ + maxBytes?: bigint; + + /** + * Pattern specifies that this field must match against the specified + * regular expression (RE2 syntax). The included expression should elide + * any delimiters. + * + * @generated from field: optional string pattern = 6; + */ + pattern?: string; + + /** + * Prefix specifies that this field must have the specified substring at + * the beginning of the string. + * + * @generated from field: optional string prefix = 7; + */ + prefix?: string; + + /** + * Suffix specifies that this field must have the specified substring at + * the end of the string. + * + * @generated from field: optional string suffix = 8; + */ + suffix?: string; + + /** + * Contains specifies that this field must have the specified substring + * anywhere in the string. + * + * @generated from field: optional string contains = 9; + */ + contains?: string; + + /** + * NotContains specifies that this field cannot have the specified substring + * anywhere in the string. + * + * @generated from field: optional string not_contains = 23; + */ + notContains?: string; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated string in = 10; + */ + in: string[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated string not_in = 11; + */ + notIn: string[] = []; + + /** + * WellKnown rules provide advanced constraints against common string + * patterns + * + * @generated from oneof validate.StringRules.well_known + */ + wellKnown: { + /** + * Email specifies that the field must be a valid email address as + * defined by RFC 5322 + * + * @generated from field: bool email = 12; + */ + value: boolean; + case: "email"; + } | { + /** + * Hostname specifies that the field must be a valid hostname as + * defined by RFC 1034. This constraint does not support + * internationalized domain names (IDNs). + * + * @generated from field: bool hostname = 13; + */ + value: boolean; + case: "hostname"; + } | { + /** + * Ip specifies that the field must be a valid IP (v4 or v6) address. + * Valid IPv6 addresses should not include surrounding square brackets. + * + * @generated from field: bool ip = 14; + */ + value: boolean; + case: "ip"; + } | { + /** + * Ipv4 specifies that the field must be a valid IPv4 address. + * + * @generated from field: bool ipv4 = 15; + */ + value: boolean; + case: "ipv4"; + } | { + /** + * Ipv6 specifies that the field must be a valid IPv6 address. Valid + * IPv6 addresses should not include surrounding square brackets. + * + * @generated from field: bool ipv6 = 16; + */ + value: boolean; + case: "ipv6"; + } | { + /** + * Uri specifies that the field must be a valid, absolute URI as defined + * by RFC 3986 + * + * @generated from field: bool uri = 17; + */ + value: boolean; + case: "uri"; + } | { + /** + * UriRef specifies that the field must be a valid URI as defined by RFC + * 3986 and may be relative or absolute. + * + * @generated from field: bool uri_ref = 18; + */ + value: boolean; + case: "uriRef"; + } | { + /** + * Address specifies that the field must be either a valid hostname as + * defined by RFC 1034 (which does not support internationalized domain + * names or IDNs), or it can be a valid IP (v4 or v6). + * + * @generated from field: bool address = 21; + */ + value: boolean; + case: "address"; + } | { + /** + * Uuid specifies that the field must be a valid UUID as defined by + * RFC 4122 + * + * @generated from field: bool uuid = 22; + */ + value: boolean; + case: "uuid"; + } | { + /** + * WellKnownRegex specifies a common well known pattern defined as a regex. + * + * @generated from field: validate.KnownRegex well_known_regex = 24; + */ + value: KnownRegex; + case: "wellKnownRegex"; + } | { case: undefined; value?: undefined } = { case: undefined }; + + /** + * This applies to regexes HTTP_HEADER_NAME and HTTP_HEADER_VALUE to enable + * strict header validation. + * By default, this is true, and HTTP header validations are RFC-compliant. + * Setting to false will enable a looser validations that only disallows + * \r\n\0 characters, which can be used to bypass header matching rules. + * + * @generated from field: optional bool strict = 25 [default = true]; + */ + strict?: boolean; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 26; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.StringRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 19, name: "len", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 2, name: "min_len", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 3, name: "max_len", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 20, name: "len_bytes", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 4, name: "min_bytes", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 5, name: "max_bytes", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 6, name: "pattern", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 7, name: "prefix", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 8, name: "suffix", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 9, name: "contains", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 23, name: "not_contains", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 10, name: "in", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 11, name: "not_in", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 12, name: "email", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 13, name: "hostname", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 14, name: "ip", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 15, name: "ipv4", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 16, name: "ipv6", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 17, name: "uri", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 18, name: "uri_ref", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 21, name: "address", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 22, name: "uuid", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 24, name: "well_known_regex", kind: "enum", T: proto2.getEnumType(KnownRegex), oneof: "well_known" }, + { no: 25, name: "strict", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: true }, + { no: 26, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): StringRules { + return new StringRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): StringRules { + return new StringRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): StringRules { + return new StringRules().fromJsonString(jsonString, options); + } + + static equals(a: StringRules | PlainMessage | undefined, b: StringRules | PlainMessage | undefined): boolean { + return proto2.util.equals(StringRules, a, b); + } +} + +/** + * BytesRules describe the constraints applied to `bytes` values + * + * @generated from message validate.BytesRules + */ +export class BytesRules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional bytes const = 1; + */ + const?: Uint8Array; + + /** + * Len specifies that this field must be the specified number of bytes + * + * @generated from field: optional uint64 len = 13; + */ + len?: bigint; + + /** + * MinLen specifies that this field must be the specified number of bytes + * at a minimum + * + * @generated from field: optional uint64 min_len = 2; + */ + minLen?: bigint; + + /** + * MaxLen specifies that this field must be the specified number of bytes + * at a maximum + * + * @generated from field: optional uint64 max_len = 3; + */ + maxLen?: bigint; + + /** + * Pattern specifies that this field must match against the specified + * regular expression (RE2 syntax). The included expression should elide + * any delimiters. + * + * @generated from field: optional string pattern = 4; + */ + pattern?: string; + + /** + * Prefix specifies that this field must have the specified bytes at the + * beginning of the string. + * + * @generated from field: optional bytes prefix = 5; + */ + prefix?: Uint8Array; + + /** + * Suffix specifies that this field must have the specified bytes at the + * end of the string. + * + * @generated from field: optional bytes suffix = 6; + */ + suffix?: Uint8Array; + + /** + * Contains specifies that this field must have the specified bytes + * anywhere in the string. + * + * @generated from field: optional bytes contains = 7; + */ + contains?: Uint8Array; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated bytes in = 8; + */ + in: Uint8Array[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated bytes not_in = 9; + */ + notIn: Uint8Array[] = []; + + /** + * WellKnown rules provide advanced constraints against common byte + * patterns + * + * @generated from oneof validate.BytesRules.well_known + */ + wellKnown: { + /** + * Ip specifies that the field must be a valid IP (v4 or v6) address in + * byte format + * + * @generated from field: bool ip = 10; + */ + value: boolean; + case: "ip"; + } | { + /** + * Ipv4 specifies that the field must be a valid IPv4 address in byte + * format + * + * @generated from field: bool ipv4 = 11; + */ + value: boolean; + case: "ipv4"; + } | { + /** + * Ipv6 specifies that the field must be a valid IPv6 address in byte + * format + * + * @generated from field: bool ipv6 = 12; + */ + value: boolean; + case: "ipv6"; + } | { case: undefined; value?: undefined } = { case: undefined }; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 14; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.BytesRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true }, + { no: 13, name: "len", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 2, name: "min_len", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 3, name: "max_len", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 4, name: "pattern", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 5, name: "prefix", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true }, + { no: 6, name: "suffix", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true }, + { no: 7, name: "contains", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true }, + { no: 8, name: "in", kind: "scalar", T: 12 /* ScalarType.BYTES */, repeated: true }, + { no: 9, name: "not_in", kind: "scalar", T: 12 /* ScalarType.BYTES */, repeated: true }, + { no: 10, name: "ip", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 11, name: "ipv4", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 12, name: "ipv6", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "well_known" }, + { no: 14, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): BytesRules { + return new BytesRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): BytesRules { + return new BytesRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): BytesRules { + return new BytesRules().fromJsonString(jsonString, options); + } + + static equals(a: BytesRules | PlainMessage | undefined, b: BytesRules | PlainMessage | undefined): boolean { + return proto2.util.equals(BytesRules, a, b); + } +} + +/** + * EnumRules describe the constraints applied to enum values + * + * @generated from message validate.EnumRules + */ +export class EnumRules extends Message { + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional int32 const = 1; + */ + const?: number; + + /** + * DefinedOnly specifies that this field must be only one of the defined + * values for this enum, failing on any undefined value. + * + * @generated from field: optional bool defined_only = 2; + */ + definedOnly?: boolean; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated int32 in = 3; + */ + in: number[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated int32 not_in = 4; + */ + notIn: number[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.EnumRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "const", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 2, name: "defined_only", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 3, name: "in", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true }, + { no: 4, name: "not_in", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumRules { + return new EnumRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumRules { + return new EnumRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): EnumRules { + return new EnumRules().fromJsonString(jsonString, options); + } + + static equals(a: EnumRules | PlainMessage | undefined, b: EnumRules | PlainMessage | undefined): boolean { + return proto2.util.equals(EnumRules, a, b); + } +} + +/** + * MessageRules describe the constraints applied to embedded message values. + * For message-type fields, validation is performed recursively. + * + * @generated from message validate.MessageRules + */ +export class MessageRules extends Message { + /** + * Skip specifies that the validation rules of this field should not be + * evaluated + * + * @generated from field: optional bool skip = 1; + */ + skip?: boolean; + + /** + * Required specifies that this field must be set + * + * @generated from field: optional bool required = 2; + */ + required?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.MessageRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "skip", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 2, name: "required", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): MessageRules { + return new MessageRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): MessageRules { + return new MessageRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): MessageRules { + return new MessageRules().fromJsonString(jsonString, options); + } + + static equals(a: MessageRules | PlainMessage | undefined, b: MessageRules | PlainMessage | undefined): boolean { + return proto2.util.equals(MessageRules, a, b); + } +} + +/** + * RepeatedRules describe the constraints applied to `repeated` values + * + * @generated from message validate.RepeatedRules + */ +export class RepeatedRules extends Message { + /** + * MinItems specifies that this field must have the specified number of + * items at a minimum + * + * @generated from field: optional uint64 min_items = 1; + */ + minItems?: bigint; + + /** + * MaxItems specifies that this field must have the specified number of + * items at a maximum + * + * @generated from field: optional uint64 max_items = 2; + */ + maxItems?: bigint; + + /** + * Unique specifies that all elements in this field must be unique. This + * constraint is only applicable to scalar and enum types (messages are not + * supported). + * + * @generated from field: optional bool unique = 3; + */ + unique?: boolean; + + /** + * Items specifies the constraints to be applied to each item in the field. + * Repeated message fields will still execute validation against each item + * unless skip is specified here. + * + * @generated from field: optional validate.FieldRules items = 4; + */ + items?: FieldRules; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 5; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.RepeatedRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "min_items", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 2, name: "max_items", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 3, name: "unique", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 4, name: "items", kind: "message", T: FieldRules, opt: true }, + { no: 5, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): RepeatedRules { + return new RepeatedRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): RepeatedRules { + return new RepeatedRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): RepeatedRules { + return new RepeatedRules().fromJsonString(jsonString, options); + } + + static equals(a: RepeatedRules | PlainMessage | undefined, b: RepeatedRules | PlainMessage | undefined): boolean { + return proto2.util.equals(RepeatedRules, a, b); + } +} + +/** + * MapRules describe the constraints applied to `map` values + * + * @generated from message validate.MapRules + */ +export class MapRules extends Message { + /** + * MinPairs specifies that this field must have the specified number of + * KVs at a minimum + * + * @generated from field: optional uint64 min_pairs = 1; + */ + minPairs?: bigint; + + /** + * MaxPairs specifies that this field must have the specified number of + * KVs at a maximum + * + * @generated from field: optional uint64 max_pairs = 2; + */ + maxPairs?: bigint; + + /** + * NoSparse specifies values in this field cannot be unset. This only + * applies to map's with message value types. + * + * @generated from field: optional bool no_sparse = 3; + */ + noSparse?: boolean; + + /** + * Keys specifies the constraints to be applied to each key in the field. + * + * @generated from field: optional validate.FieldRules keys = 4; + */ + keys?: FieldRules; + + /** + * Values specifies the constraints to be applied to the value of each key + * in the field. Message values will still have their validations evaluated + * unless skip is specified here. + * + * @generated from field: optional validate.FieldRules values = 5; + */ + values?: FieldRules; + + /** + * IgnoreEmpty specifies that the validation rules of this field should be + * evaluated only if the field is not empty + * + * @generated from field: optional bool ignore_empty = 6; + */ + ignoreEmpty?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.MapRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "min_pairs", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 2, name: "max_pairs", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 3, name: "no_sparse", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 4, name: "keys", kind: "message", T: FieldRules, opt: true }, + { no: 5, name: "values", kind: "message", T: FieldRules, opt: true }, + { no: 6, name: "ignore_empty", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): MapRules { + return new MapRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): MapRules { + return new MapRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): MapRules { + return new MapRules().fromJsonString(jsonString, options); + } + + static equals(a: MapRules | PlainMessage | undefined, b: MapRules | PlainMessage | undefined): boolean { + return proto2.util.equals(MapRules, a, b); + } +} + +/** + * AnyRules describe constraints applied exclusively to the + * `google.protobuf.Any` well-known type + * + * @generated from message validate.AnyRules + */ +export class AnyRules extends Message { + /** + * Required specifies that this field must be set + * + * @generated from field: optional bool required = 1; + */ + required?: boolean; + + /** + * In specifies that this field's `type_url` must be equal to one of the + * specified values. + * + * @generated from field: repeated string in = 2; + */ + in: string[] = []; + + /** + * NotIn specifies that this field's `type_url` must not be equal to any of + * the specified values. + * + * @generated from field: repeated string not_in = 3; + */ + notIn: string[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.AnyRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "required", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 2, name: "in", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 3, name: "not_in", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): AnyRules { + return new AnyRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): AnyRules { + return new AnyRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): AnyRules { + return new AnyRules().fromJsonString(jsonString, options); + } + + static equals(a: AnyRules | PlainMessage | undefined, b: AnyRules | PlainMessage | undefined): boolean { + return proto2.util.equals(AnyRules, a, b); + } +} + +/** + * DurationRules describe the constraints applied exclusively to the + * `google.protobuf.Duration` well-known type + * + * @generated from message validate.DurationRules + */ +export class DurationRules extends Message { + /** + * Required specifies that this field must be set + * + * @generated from field: optional bool required = 1; + */ + required?: boolean; + + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional google.protobuf.Duration const = 2; + */ + const?: Duration; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional google.protobuf.Duration lt = 3; + */ + lt?: Duration; + + /** + * Lt specifies that this field must be less than the specified value, + * inclusive + * + * @generated from field: optional google.protobuf.Duration lte = 4; + */ + lte?: Duration; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive + * + * @generated from field: optional google.protobuf.Duration gt = 5; + */ + gt?: Duration; + + /** + * Gte specifies that this field must be greater than the specified value, + * inclusive + * + * @generated from field: optional google.protobuf.Duration gte = 6; + */ + gte?: Duration; + + /** + * In specifies that this field must be equal to one of the specified + * values + * + * @generated from field: repeated google.protobuf.Duration in = 7; + */ + in: Duration[] = []; + + /** + * NotIn specifies that this field cannot be equal to one of the specified + * values + * + * @generated from field: repeated google.protobuf.Duration not_in = 8; + */ + notIn: Duration[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.DurationRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "required", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 2, name: "const", kind: "message", T: Duration, opt: true }, + { no: 3, name: "lt", kind: "message", T: Duration, opt: true }, + { no: 4, name: "lte", kind: "message", T: Duration, opt: true }, + { no: 5, name: "gt", kind: "message", T: Duration, opt: true }, + { no: 6, name: "gte", kind: "message", T: Duration, opt: true }, + { no: 7, name: "in", kind: "message", T: Duration, repeated: true }, + { no: 8, name: "not_in", kind: "message", T: Duration, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): DurationRules { + return new DurationRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): DurationRules { + return new DurationRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): DurationRules { + return new DurationRules().fromJsonString(jsonString, options); + } + + static equals(a: DurationRules | PlainMessage | undefined, b: DurationRules | PlainMessage | undefined): boolean { + return proto2.util.equals(DurationRules, a, b); + } +} + +/** + * TimestampRules describe the constraints applied exclusively to the + * `google.protobuf.Timestamp` well-known type + * + * @generated from message validate.TimestampRules + */ +export class TimestampRules extends Message { + /** + * Required specifies that this field must be set + * + * @generated from field: optional bool required = 1; + */ + required?: boolean; + + /** + * Const specifies that this field must be exactly the specified value + * + * @generated from field: optional google.protobuf.Timestamp const = 2; + */ + const?: Timestamp; + + /** + * Lt specifies that this field must be less than the specified value, + * exclusive + * + * @generated from field: optional google.protobuf.Timestamp lt = 3; + */ + lt?: Timestamp; + + /** + * Lte specifies that this field must be less than the specified value, + * inclusive + * + * @generated from field: optional google.protobuf.Timestamp lte = 4; + */ + lte?: Timestamp; + + /** + * Gt specifies that this field must be greater than the specified value, + * exclusive + * + * @generated from field: optional google.protobuf.Timestamp gt = 5; + */ + gt?: Timestamp; + + /** + * Gte specifies that this field must be greater than the specified value, + * inclusive + * + * @generated from field: optional google.protobuf.Timestamp gte = 6; + */ + gte?: Timestamp; + + /** + * LtNow specifies that this must be less than the current time. LtNow + * can only be used with the Within rule. + * + * @generated from field: optional bool lt_now = 7; + */ + ltNow?: boolean; + + /** + * GtNow specifies that this must be greater than the current time. GtNow + * can only be used with the Within rule. + * + * @generated from field: optional bool gt_now = 8; + */ + gtNow?: boolean; + + /** + * Within specifies that this field must be within this duration of the + * current time. This constraint can be used alone or with the LtNow and + * GtNow rules. + * + * @generated from field: optional google.protobuf.Duration within = 9; + */ + within?: Duration; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "validate.TimestampRules"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "required", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 2, name: "const", kind: "message", T: Timestamp, opt: true }, + { no: 3, name: "lt", kind: "message", T: Timestamp, opt: true }, + { no: 4, name: "lte", kind: "message", T: Timestamp, opt: true }, + { no: 5, name: "gt", kind: "message", T: Timestamp, opt: true }, + { no: 6, name: "gte", kind: "message", T: Timestamp, opt: true }, + { no: 7, name: "lt_now", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 8, name: "gt_now", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 9, name: "within", kind: "message", T: Duration, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): TimestampRules { + return new TimestampRules().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): TimestampRules { + return new TimestampRules().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): TimestampRules { + return new TimestampRules().fromJsonString(jsonString, options); + } + + static equals(a: TimestampRules | PlainMessage | undefined, b: TimestampRules | PlainMessage | undefined): boolean { + return proto2.util.equals(TimestampRules, a, b); + } +} + +/** + * Disabled nullifies any validation rules for this message, including any + * message fields associated with it that do support validation. + * + * @generated from extension: optional bool disabled = 1071; + */ +export const disabled = proto2.makeExtension( + "validate.disabled", + MessageOptions, + { no: 1071, kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, +); + +/** + * Ignore skips generation of validation methods for this message. + * + * @generated from extension: optional bool ignored = 1072; + */ +export const ignored = proto2.makeExtension( + "validate.ignored", + MessageOptions, + { no: 1072, kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, +); + +/** + * Required ensures that exactly one the field options in a oneof is set; + * validation fails if no fields in the oneof are set. + * + * @generated from extension: optional bool required = 1071; + */ +export const required = proto2.makeExtension( + "validate.required", + OneofOptions, + { no: 1071, kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, +); + +/** + * Rules specify the validations to be performed on this field. By default, + * no validation is performed against a field. + * + * @generated from extension: optional validate.FieldRules rules = 1071; + */ +export const rules = proto2.makeExtension( + "validate.rules", + FieldOptions, + () => ({ no: 1071, kind: "message", T: FieldRules, opt: true }), +); + diff --git a/clients/dashboard/tailwind.config.ts b/clients/dashboard/tailwind.config.ts new file mode 100644 index 0000000..36e7a5c --- /dev/null +++ b/clients/dashboard/tailwind.config.ts @@ -0,0 +1,98 @@ +import type { Config } from 'tailwindcss'; +import defaultTheme from 'tailwindcss/defaultTheme'; + +export default { + darkMode: ['class'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], + theme: { + extend: { + fontFamily: { + primary: ['Inter', ...defaultTheme.fontFamily.sans] + }, + colors: { + primary: { + '50': 'rgb(var(--tw-color-primary-50) / )', + '100': 'rgb(var(--tw-color-primary-100) / )', + '200': 'rgb(var(--tw-color-primary-200) / )', + '300': 'rgb(var(--tw-color-primary-300) / )', + '400': 'rgb(var(--tw-color-primary-400) / )', + '500': 'rgb(var(--tw-color-primary-500) / )', + '600': 'rgb(var(--tw-color-primary-600) / )', + '700': 'rgb(var(--tw-color-primary-700) / )', + '800': 'rgb(var(--tw-color-primary-800) / )', + '900': 'rgb(var(--tw-color-primary-900) / )', + '950': 'rgb(var(--tw-color-primary-950) / )', + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + dark: '#222222', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + chart: { + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + } + }, + keyframes: { + flicker: { + '0%, 19.999%, 22%, 62.999%, 64%, 64.999%, 70%, 100%': { + opacity: '0.99', + filter: 'drop-shadow(0 0 1px rgba(252, 211, 77)) drop-shadow(0 0 15px rgba(245, 158, 11)) drop-shadow(0 0 1px rgba(252, 211, 77))' + }, + '20%, 21.999%, 63%, 63.999%, 65%, 69.999%': { + opacity: '0.4', + filter: 'none' + } + }, + shimmer: { + '0%': { + backgroundPosition: '-700px 0' + }, + '100%': { + backgroundPosition: '700px 0' + } + } + }, + animation: { + flicker: 'flicker 3s linear infinite', + shimmer: 'shimmer 1.3s linear infinite' + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' + } + } + }, + plugins: [require('@tailwindcss/forms'), require("tailwindcss-animate")], +} satisfies Config; diff --git a/clients/dashboard/tsconfig.json b/clients/dashboard/tsconfig.json new file mode 100644 index 0000000..10c575f --- /dev/null +++ b/clients/dashboard/tsconfig.json @@ -0,0 +1,51 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "baseUrl": ".", + "paths": { + "@/*": [ + "./src/*" + ], + "~/*": [ + "./public/*" + ] + }, + "incremental": true, + "plugins": [ + { + "name": "next" + } + ] + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + "dist/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ], + "moduleResolution": [ + "node_modules", + ".next", + "node" + ] +} diff --git a/clients/dashboard/vercel.json b/clients/dashboard/vercel.json new file mode 100644 index 0000000..603bfca --- /dev/null +++ b/clients/dashboard/vercel.json @@ -0,0 +1,13 @@ +{ + "headers": [ + { + "source": "/fonts/inter-var-latin.woff2", + "headers": [ + { + "key": "Cache-Control", + "value": "public, max-age=31536000, immutable" + } + ] + } + ] +} diff --git a/docker-compose.demo.yaml b/docker-compose.demo.yaml new file mode 100644 index 0000000..0fc7787 --- /dev/null +++ b/docker-compose.demo.yaml @@ -0,0 +1,74 @@ +version: '3.1' + +services: + db: + image: postgres:16.1 + restart: always + environment: + - POSTGRES_USER=admin + - POSTGRES_DB=tasks + - POSTGRES_PASSWORD=admin + ports: + - "5432:5432" + networks: + - task-network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U admin"] + interval: 10s + timeout: 5s + retries: 5 + + + river: + image: evalsocket/river:latest + command: ["migrate-up", "--database-url", "postgres://admin:admin@db:5432/tasks"] + depends_on: + db: + condition: service_healthy + links: + - db + env_file: + - .env.docker + networks: + - task-network + + dashboard: + build: + context: . + dockerfile: Dockerfile.client + ports: + - "3000:3000" + depends_on: + db: + condition: service_healthy + links: + - db + - task + - river + env_file: + - .env.docker + networks: + - task-network + + task: + build: + context: . + dockerfile: Dockerfile + target: server-final + ports: + - "8080:8080" + depends_on: + db: + condition: service_healthy + links: + - db + - river + env_file: + - .env.docker + networks: + - task-network + + +networks: + task-network: + driver: bridge \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..c3160ad --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,12 @@ +version: '3.1' + +services: + db: + image: postgres:16.1 + restart: always + environment: + - POSTGRES_USER=admin + - POSTGRES_DB=tasks + - POSTGRES_PASSWORD=admin + ports: + - "5432:5432" diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e5752c8 --- /dev/null +++ b/go.mod @@ -0,0 +1,87 @@ +module task + +go 1.22.3 + +require ( + connectrpc.com/connect v1.16.2 + connectrpc.com/grpchealth v1.3.0 + connectrpc.com/grpcreflect v1.2.0 + connectrpc.com/otelconnect v0.7.1 + github.com/avast/retry-go/v4 v4.6.0 + github.com/bufbuild/protovalidate-go v0.7.0 + github.com/envoyproxy/protoc-gen-validate v1.1.0 + github.com/google/go-cmp v0.6.0 + github.com/jackc/pgx/v5 v5.7.1 + github.com/joho/godotenv v1.5.1 + github.com/kelseyhightower/envconfig v1.4.0 + github.com/olekukonko/tablewriter v0.0.5 + github.com/prometheus/client_golang v1.20.4 + github.com/riverqueue/river v0.12.1 + github.com/riverqueue/river/riverdriver/riverdatabasesql v0.12.1 + github.com/riverqueue/river/riverdriver/riverpgxv5 v0.12.1 + github.com/riverqueue/river/rivertype v0.12.1 + github.com/rs/cors v1.11.1 + github.com/spf13/cobra v1.8.1 + github.com/stretchr/testify v1.9.0 + go.akshayshah.org/connectauth v0.6.0 + golang.org/x/net v0.29.0 + google.golang.org/protobuf v1.34.2 + gopkg.in/yaml.v2 v2.4.0 + gorm.io/driver/postgres v1.5.9 + gorm.io/gorm v1.25.12 +) + +require ( + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240920164238-5a7b106cbb87.2 // indirect + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect + github.com/avast/retry-go v3.0.0+incompatible // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.22.0 // indirect + github.com/google/cel-go v0.21.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/riverqueue/river/riverdriver v0.12.1 // indirect + github.com/riverqueue/river/rivershared v0.12.1 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/stoewer/go-strcase v1.3.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/tidwall/gjson v1.17.3 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + go.opentelemetry.io/otel v1.19.0 // indirect + go.opentelemetry.io/otel/metric v1.19.0 // indirect + go.opentelemetry.io/otel/trace v1.19.0 // indirect + go.uber.org/goleak v1.3.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + riverqueue.com/riverui v0.5.3 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a1d2a95 --- /dev/null +++ b/go.sum @@ -0,0 +1,191 @@ +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240920164238-5a7b106cbb87.2 h1:hl0FrmGlNpQZIGvU1/jDz0lsPDd0BhCE0QDRwPfLZcA= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240920164238-5a7b106cbb87.2/go.mod h1:ylS4c28ACSI59oJrOdW4pHS4n0Hw4TgSPHn8rpHl4Yw= +connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= +connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= +connectrpc.com/grpchealth v1.3.0 h1:FA3OIwAvuMokQIXQrY5LbIy8IenftksTP/lG4PbYN+E= +connectrpc.com/grpchealth v1.3.0/go.mod h1:3vpqmX25/ir0gVgW6RdnCPPZRcR6HvqtXX5RNPmDXHM= +connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= +connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY= +connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= +github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= +github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= +github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bufbuild/protovalidate-go v0.7.0 h1:MYU9GSZM7TSsWNywvyXoEc8y3kc1MNqD3k5mddIBEL4= +github.com/bufbuild/protovalidate-go v0.7.0/go.mod h1:PHV5pFuWlRzdDW02/cmVyNzdiQ+RNNwo7idGxdzS7o4= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM= +github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= +github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/google/cel-go v0.21.0 h1:cl6uW/gxN+Hy50tNYvI691+sXxioCnstFzLp2WO4GCI= +github.com/google/cel-go v0.21.0/go.mod h1:rHUlWCcBKgyEk+eV03RPdZUekPp6YcJwV0FxuUksYxc= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa h1:s+4MhCQ6YrzisK6hFJUX53drDT4UsSW3DEhKn0ifuHw= +github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= +github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0= +github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= +github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/riverqueue/river v0.12.1 h1:TS3FVioPStlvb7yj1dYgtgX+zn/3JkLdPn+S6qNBcZ0= +github.com/riverqueue/river v0.12.1/go.mod h1:j7O42JlHo76YgXkAFX66E63Ke890/oSUUlui/ImyLuU= +github.com/riverqueue/river/riverdriver v0.12.1 h1:MqAh6mw9h/m/nNXImJTXXtCefTDPdmZSlgsUdSYUHe0= +github.com/riverqueue/river/riverdriver v0.12.1/go.mod h1:E4hf4wPidG0xYrwsez4R9u4LvLdjlDu9m4iJFpb1DfQ= +github.com/riverqueue/river/riverdriver/riverdatabasesql v0.12.1 h1:E2pYemeaaiqOqr1x1Cq872IdulGu5z/iIHChqxPJwfA= +github.com/riverqueue/river/riverdriver/riverdatabasesql v0.12.1/go.mod h1:+5DVUCfdPS3ZtsRm4V0GzQfXJI9MsFvq3BNqW/Nei3E= +github.com/riverqueue/river/riverdriver/riverpgxv5 v0.12.1 h1:stodaBk+GKMU4Uwoj2tShG5L/EK/E5gWOQwZhsJ65QY= +github.com/riverqueue/river/riverdriver/riverpgxv5 v0.12.1/go.mod h1:kwV0SdmvBYOj3hsI4sn3tQQQ5NqXrq68yDvKb1Jms1E= +github.com/riverqueue/river/rivershared v0.12.1 h1:7y03CM6iYrSoT1k6ylneTIoK74qQ27yi1aoT3dozU6Y= +github.com/riverqueue/river/rivershared v0.12.1/go.mod h1:IpJ63Jz/Rx61nKhJ45K9IdJR0VEHf3qnFlEPI9l11HM= +github.com/riverqueue/river/rivertype v0.12.1 h1:iTciVhZ/yQQQBMAouivPrSlrQH8MEK5uCVtzu3eITu8= +github.com/riverqueue/river/rivertype v0.12.1/go.mod h1:3WRQEDlLKZky/vGwFcZC3uKjC+/8izE6ucHwCsuir98= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94= +github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +go.akshayshah.org/attest v1.0.2 h1:qOv9PXCG2mwnph3g0I3yZj0rLAwLyUITs8nhxP+wS44= +go.akshayshah.org/attest v1.0.2/go.mod h1:PnWzcW5j9dkyGwTlBmUsYpPnHG0AUPrs1RQ+HrldWO0= +go.akshayshah.org/connectauth v0.6.0 h1:lyzJ3z33L2KKgfSZW95tilktE7bCgc/OTQm0V8C2//g= +go.akshayshah.org/connectauth v0.6.0/go.mod h1:4dHteR5Gt7mh0weczJVRESBBWf+tmphmTIDg7R99JYQ= +go.akshayshah.org/memhttp v0.1.0 h1:Enf7JeZnm+A8iRur0FYvs4ZjWa1VVMc2gG4EirG+aNE= +go.akshayshah.org/memhttp v0.1.0/go.mod h1:Q1A5oqQfj2tZFRzpw0HRmmZAMzw8f3AxqOe55Afn1d8= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda h1:b6F6WIV4xHHD0FA4oIyzU6mHWg2WI2X1RBehwa5QN38= +google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda/go.mod h1:AHcE/gZH76Bk/ROZhQphlRoWo5xKDEtz3eVEO1LfA8c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8= +gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= +gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= +gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= +riverqueue.com/riverui v0.5.3 h1:SoKWTreMJqTgFYScvoqBva5YZ45bBzgXWEEAv/oQrKE= +riverqueue.com/riverui v0.5.3/go.mod h1:846dydyj0GILXGmiOnsnZ4HYJSfgtQ93jib+joX4no4= diff --git a/idl/buf.lock b/idl/buf.lock new file mode 100644 index 0000000..744d0f2 --- /dev/null +++ b/idl/buf.lock @@ -0,0 +1,13 @@ +# Generated by buf. DO NOT EDIT. +version: v1 +deps: + - remote: buf.build + owner: bufbuild + repository: protovalidate + commit: 5a7b106cbb87462d9a8c9ffecdbd2e38 + digest: shake256:2f7efa5a904668219f039d4f6eeb51e871f8f7f5966055a10663cba335bd65f76cac84da3fa758ab7b5dcb489ec599521390ce3951d119fb56df1fc2def16bb0 + - remote: buf.build + owner: envoyproxy + repository: protoc-gen-validate + commit: daf171c6cdb54629b5f51e345a79e4dd + digest: shake256:4ae167d7eed10da5f83a3f5df8c670d249170f11b1f2fd19afda06be2cff4d47dcc95e9e4a15151ecc8ce2d3d3614caf9a04d3ad82fb768a3870dedfa9455f36 diff --git a/idl/buf.md b/idl/buf.md new file mode 100644 index 0000000..a577d8b --- /dev/null +++ b/idl/buf.md @@ -0,0 +1,15 @@ +# Task Service + +## Overview + +Task Service is a distributed system designed for efficient task management and execution. It provides a scalable architecture with separate control and data planes, allowing for flexible task creation, scheduling, and processing. + +## Key Features + +- Distributed architecture with control plane (server) and data plane (workers) +- Asynchronous task execution using RiverQueue with PostgreSQL as the queue backend +- RESTful API for task management +- CLI tool for easy interaction with the service +- Web-based dashboard for task monitoring and management +- Plugin-based architecture for extensible task types +- Kubernetes-ready with Helm charts for deployment diff --git a/idl/buf.yaml b/idl/buf.yaml new file mode 100644 index 0000000..da1aad3 --- /dev/null +++ b/idl/buf.yaml @@ -0,0 +1,11 @@ +version: v1 +name: buf.build/evalsocket/cloud +lint: + use: + - DEFAULT +breaking: + use: + - FILE +deps: + - buf.build/bufbuild/protovalidate + - buf.build/envoyproxy/protoc-gen-validate diff --git a/idl/cloud/v1/cloud.proto b/idl/cloud/v1/cloud.proto new file mode 100644 index 0000000..b7652c5 --- /dev/null +++ b/idl/cloud/v1/cloud.proto @@ -0,0 +1,219 @@ +syntax = "proto3"; + +package cloud.v1; + +import "validate/validate.proto"; +import "google/protobuf/empty.proto"; + +// Enum for Task statuses +enum TaskStatusEnum { + QUEUED = 0; // Task is in the queue, waiting to be processed + RUNNING = 1; // Task is currently being executed + FAILED = 2; // Task encountered an error and failed to complete + SUCCEEDED = 3; // Task completed successfully + UNKNOWN = 4; // Task status cannot be determined + ALL = 5; // Task status cannot be determined +} + +// Message for Task Payload +message Payload { + // Dynamic key-value pairs for task parameters. + // Keys must contain only alphanumeric characters, underscores, or dashes. + // Values are limited to 1024 characters to prevent excessive data storage. + map parameters = 1 [(validate.rules).map = { + keys: {string: {pattern: "^[a-zA-Z0-9_-]+$"}}, + values: {string: {max_len: 1024}} + }]; +} + +// Message for Task creation request +message CreateTaskRequest { + // Name of the task. Must contain only alphanumeric characters, underscores, or dashes, + // with a maximum length of 255 characters for readability and database compatibility. + string name = 1 [(validate.rules).string = { + pattern: "^[a-zA-Z0-9_-]+$", + max_len: 255 + }]; + + // Type of the task. Must be either SEND_EMAIL or RUN_QUERY. + // This field is an enum to ensure only predefined task types are used. + string type = 2 [(validate.rules).enum = {defined_only: true}]; + + // Payload containing task parameters. This field is required to ensure + // all necessary information for task execution is provided. + Payload payload = 3 [(validate.rules).message.required = true]; + + // Description of the task. Allows for a detailed explanation of the task's purpose. + // Limited to 5000 characters to balance between providing sufficient detail and + // preventing excessively long descriptions. + string description = 4 [(validate.rules).string = { + max_len: 5000 + }]; +} + +// Message for Task creation response +message CreateTaskResponse { + // Unique identifier for the created task. Must be >= 0. + int32 id = 1 [(validate.rules).int32 = {gte: 0}]; +} + +// Message for Task status +message Task { + // Unique identifier for the task. Must be >= 0. + int32 id = 1 [(validate.rules).int32 = {gte: 0}]; + + // Name of the task. Must be alphanumeric, underscores, or dashes, + // with a maximum length of 255 characters. + string name = 2 [(validate.rules).string = { + pattern: "^[a-zA-Z0-9_-]+$", + max_len: 255 + }]; + + // Type of the task, must be either SEND_EMAIL or RUN_QUERY. + string type = 3 [(validate.rules).enum = {defined_only: true}]; + + // Current status of the task, must be one of the defined statuses. + TaskStatusEnum status = 4 [(validate.rules).enum = {defined_only: true}]; + + // Number of retries attempted for this task. Limited to 10 to prevent + // infinite retry loops while allowing for reasonable error recovery. + int32 retries = 5 [(validate.rules).int32 = { + gte: 0, + lte: 10 + }]; + + // Priority level of the task. Higher values indicate higher priority. + // Must be non-negative to ensure valid prioritization. + int32 priority = 6 [(validate.rules).int32 = {gte: 0}]; + + // Timestamp of when the task was created, in ISO 8601 format (UTC). + // This format ensures consistent time representation across different systems. + string created_at = 7 [(validate.rules).string = { + pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$" + }]; + + // Payload containing task parameters. This field is required. + Payload payload = 8 [(validate.rules).message.required = true]; + + // Description of the task. A large text string with a maximum length of 5000 characters. + string description = 9 [(validate.rules).string = { + max_len: 5000 + }]; +} + +// Message for Task history +message TaskHistory { + // Unique identifier for the history entry. Must be >= 0. + int32 id = 1 [(validate.rules).int32 = {gte: 0}]; + + // Status of the task at the time of this history entry. + TaskStatusEnum status = 2 [(validate.rules).enum = {defined_only: true}]; + + // Timestamp of when this history entry was created, in ISO 8601 format. + string created_at = 3 [(validate.rules).string = { + pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$" + }]; + + // Additional details about the task's execution or status. + // Maximum length of 2000 characters. + string details = 4 [(validate.rules).string = {max_len: 2000}]; +} + +// Message for Task status request +message GetTaskRequest { + // Unique identifier for the task. Must be >= 0. + int32 id = 1 [(validate.rules).int32 = {gte: 0}]; +} + +// Message for Task history request +message GetTaskHistoryRequest { + // Unique identifier for the task. Must be >= 0. + int32 id = 1 [(validate.rules).int32 = {gte: 0}]; +} + +// Message for Task history response +message GetTaskHistoryResponse { + // List of task history entries. Minimum of 1 entry ensures that some history is always returned. + // Maximum of 1000 entries prevents excessive data transfer and processing for very long-running tasks. + repeated TaskHistory history = 1 [(validate.rules).repeated = { + min_items: 1, + max_items: 1000 + }]; +} + +// Message for Task status update request +message UpdateTaskStatusRequest { + // Unique identifier for the task. Must be >= 0. + int32 id = 1 [(validate.rules).int32 = {gte: 0}]; + + // New status for the task, must be one of the defined statuses. + TaskStatusEnum status = 2 [(validate.rules).enum = {defined_only: true}]; + + // Additional message about the status update. Maximum length of 2000 characters. + string message = 3 [(validate.rules).string = {max_len: 2000}]; +} + + +// Task Management service definition +service TaskManagementService { + // Creates a new task based on the provided request. + // Returns a CreateTaskResponse containing the unique identifier of the created task. + rpc CreateTask(CreateTaskRequest) returns (CreateTaskResponse) {} + + // Retrieves the current status and details of the specified task. + // Returns a Task message containing all information about the requested task. + rpc GetTask(GetTaskRequest) returns (Task) {} + + // Lists tasks currently available in the system, with pagination support. + // Returns a TaskList containing the requested subset of tasks. + rpc ListTasks(TaskListRequest) returns (TaskList) {} + + // Retrieves the execution history of the specified task. + // Returns a GetTaskHistoryResponse containing a list of historical status updates. + rpc GetTaskHistory(GetTaskHistoryRequest) returns (GetTaskHistoryResponse) {} + + // Updates the status of the specified task. + // Returns an empty response to confirm the update was processed. + rpc UpdateTaskStatus(UpdateTaskStatusRequest) returns (google.protobuf.Empty) {} + + // Retrieves the count of tasks for each status. + // Returns a GetStatusResponse containing a map of status counts. + rpc GetStatus(GetStatusRequest) returns (GetStatusResponse) {} +} + +// Message for GetStatus request (empty) +message GetStatusRequest {} + +// Message for GetStatus response +message GetStatusResponse { + // Map of task statuses and their counts + map status_counts = 1; +} + +// Message for Task List +message TaskList { + repeated Task tasks = 1; // List of tasks in the system. +} + +// Message for Task List request +message TaskListRequest { + // Maximum number of tasks to return in a single request. + // Limited between 1 and 100 to balance between minimizing requests and preventing excessive data transfer. + int32 limit = 1 [(validate.rules).int32 = { + gte: 1, + lte: 100 + }]; + + // Number of tasks to skip before starting to return results. + // Allows for pagination of results. Must be non-negative. + int32 offset = 2 [(validate.rules).int32.gte = 0]; + + // Optional filter for tasks by status. If not specified, tasks of all statuses will be returned. + optional TaskStatusEnum status = 3; + + // Optional filter for tasks by type. Must be either SEND_EMAIL or RUN_QUERY if specified. + // If not specified, tasks of all types will be returned. + optional string type = 4 [(validate.rules).string = { + in: ["send_email", "run_query"] + }]; +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0907e02 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,18062 @@ +{ + "name": "task", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "task", + "version": "0.0.1", + "workspaces": [ + "clients/*" + ], + "devDependencies": { + "@commitlint/cli": "18.6.0", + "@commitlint/config-conventional": "18.6.0", + "@connectrpc/protoc-gen-connect-es": "^1.5.0", + "@svgr/webpack": "^8.1.0", + "@tailwindcss/forms": "^0.5.9", + "@testing-library/dom": "9.3.4", + "@testing-library/jest-dom": "^6.3.0", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "14.5.2", + "@types/node": "20.11.10", + "@types/react": "18.2.48", + "@types/react-dom": "18.2.18", + "@types/testing-library__jest-dom": "^5.14.9", + "@typescript-eslint/eslint-plugin": "^5.62.0", + "@typescript-eslint/parser": "^5.62.0", + "autoprefixer": "10.4.17", + "commitizen": "4.3.0", + "eslint": "^8.57.1", + "eslint-config-next": "^14.2.13", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-simple-import-sort": "^7.0.0", + "eslint-plugin-unused-imports": "^2.0.0", + "jest": "^29.7.0", + "lint-staged": "^15.2.10", + "next-router-mock": "^0.9.0", + "next-sitemap": "^2.5.28", + "postcss": "8.4.33", + "prettier": "3.2.4", + "prettier-plugin-tailwindcss": "0.5.11", + "tailwindcss": "3.4.1", + "ts-node": "10.9.2", + "tsup": "8.0.1", + "turbo": "1.11.3", + "typescript": "5.3.3" + } + }, + "clients/dashboard": { + "version": "0.1.0", + "dependencies": { + "@buf/evalsocket_cloud.bufbuild_es": "^1.10.0-20240930090015-e8421d60e43d.1", + "@buf/evalsocket_cloud.connectrpc_es": "^1.5.0-20240930133422-6e6299195d4e.1", + "@bufbuild/protobuf": "^1.10.0", + "@connectrpc/connect": "^1.5.0", + "@connectrpc/connect-next": "^1.5.0", + "@connectrpc/connect-node": "^1.5.0", + "@connectrpc/connect-web": "^1.5.0", + "@monaco-editor/react": "^4.6.0", + "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-select": "^2.1.1", + "@radix-ui/react-slot": "^1.1.0", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "date-fns": "^4.1.0", + "install": "^0.13.0", + "lucide-react": "^0.438.0", + "monaco-editor": "^0.52.0", + "next": "^14.2.13", + "npm": "^10.8.3", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-hot-toast": "^2.4.1", + "react-icons": "^5.3.0", + "recharts": "^2.12.7", + "tailwind-merge": "^2.5.2", + "tailwindcss-animate": "^1.0.7", + "zod": "^3.22.4" + }, + "devDependencies": { + "@bufbuild/buf": "^1.39.0", + "@commitlint/cli": "^19.5.0", + "@commitlint/config-conventional": "^16.2.4", + "@connectrpc/protoc-gen-connect-es": "^1.5.0", + "@svgr/webpack": "^8.1.0", + "@tailwindcss/forms": "^0.5.9", + "@testing-library/jest-dom": "^6.3.0", + "@testing-library/react": "^13.4.0", + "@types/react": "^18.3.4", + "@types/testing-library__jest-dom": "^5.14.9", + "@typescript-eslint/eslint-plugin": "^5.62.0", + "@typescript-eslint/parser": "^5.62.0", + "autoprefixer": "^10.4.20", + "eslint": "^8.57.1", + "eslint-config-next": "^14.2.13", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-simple-import-sort": "^7.0.0", + "eslint-plugin-unused-imports": "^2.0.0", + "jest": "^29.7.0", + "lint-staged": "15.2.10", + "next-router-mock": "^0.9.0", + "next-sitemap": "^2.5.28", + "postcss": "^8.4.45", + "prettier": "^2.8.8", + "prettier-plugin-tailwindcss": "^0.5.0", + "tailwindcss": "^3.4.12", + "typescript": "5.4.5" + } + }, + "clients/dashboard/node_modules/@commitlint/cli": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.5.0.tgz", + "integrity": "sha512-gaGqSliGwB86MDmAAKAtV9SV1SHdmN8pnGq4EJU4+hLisQ7IFfx4jvU4s+pk6tl0+9bv6yT+CaZkufOinkSJIQ==", + "dev": true, + "dependencies": { + "@commitlint/format": "^19.5.0", + "@commitlint/lint": "^19.5.0", + "@commitlint/load": "^19.5.0", + "@commitlint/read": "^19.5.0", + "@commitlint/types": "^19.5.0", + "tinyexec": "^0.3.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/config-conventional": { + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-16.2.4.tgz", + "integrity": "sha512-av2UQJa3CuE5P0dzxj/o/B9XVALqYzEViHrMXtDrW9iuflrqCStWBAioijppj9URyz6ONpohJKAtSdgAOE0gkA==", + "dev": true, + "dependencies": { + "conventional-changelog-conventionalcommits": "^4.3.1" + }, + "engines": { + "node": ">=v12" + } + }, + "clients/dashboard/node_modules/@commitlint/config-validator": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.5.0.tgz", + "integrity": "sha512-CHtj92H5rdhKt17RmgALhfQt95VayrUo2tSqY9g2w+laAXyk7K/Ef6uPm9tn5qSIwSmrLjKaXK9eiNuxmQrDBw==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.5.0", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/ensure": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.5.0.tgz", + "integrity": "sha512-Kv0pYZeMrdg48bHFEU5KKcccRfKmISSm9MvgIgkpI6m+ohFTB55qZlBW6eYqh/XDfRuIO0x4zSmvBjmOwWTwkg==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.5.0", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/execute-rule": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.5.0.tgz", + "integrity": "sha512-aqyGgytXhl2ejlk+/rfgtwpPexYyri4t8/n4ku6rRJoRhGZpLFMqrZ+YaubeGysCP6oz4mMA34YSTaSOKEeNrg==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/format": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.5.0.tgz", + "integrity": "sha512-yNy088miE52stCI3dhG/vvxFo9e4jFkU1Mj3xECfzp/bIS/JUay4491huAlVcffOoMK1cd296q0W92NlER6r3A==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.5.0", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/is-ignored": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.5.0.tgz", + "integrity": "sha512-0XQ7Llsf9iL/ANtwyZ6G0NGp5Y3EQ8eDQSxv/SRcfJ0awlBY4tHFAvwWbw66FVUaWICH7iE5en+FD9TQsokZ5w==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.5.0", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/lint": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.5.0.tgz", + "integrity": "sha512-cAAQwJcRtiBxQWO0eprrAbOurtJz8U6MgYqLz+p9kLElirzSCc0vGMcyCaA1O7AqBuxo11l1XsY3FhOFowLAAg==", + "dev": true, + "dependencies": { + "@commitlint/is-ignored": "^19.5.0", + "@commitlint/parse": "^19.5.0", + "@commitlint/rules": "^19.5.0", + "@commitlint/types": "^19.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/load": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.5.0.tgz", + "integrity": "sha512-INOUhkL/qaKqwcTUvCE8iIUf5XHsEPCLY9looJ/ipzi7jtGhgmtH7OOFiNvwYgH7mA8osUWOUDV8t4E2HAi4xA==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^19.5.0", + "@commitlint/execute-rule": "^19.5.0", + "@commitlint/resolve-extends": "^19.5.0", + "@commitlint/types": "^19.5.0", + "chalk": "^5.3.0", + "cosmiconfig": "^9.0.0", + "cosmiconfig-typescript-loader": "^5.0.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/message": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.5.0.tgz", + "integrity": "sha512-R7AM4YnbxN1Joj1tMfCyBryOC5aNJBdxadTZkuqtWi3Xj0kMdutq16XQwuoGbIzL2Pk62TALV1fZDCv36+JhTQ==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/parse": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.5.0.tgz", + "integrity": "sha512-cZ/IxfAlfWYhAQV0TwcbdR1Oc0/r0Ik1GEessDJ3Lbuma/MRO8FRQX76eurcXtmhJC//rj52ZSZuXUg0oIX0Fw==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.5.0", + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-parser": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/read": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.5.0.tgz", + "integrity": "sha512-TjS3HLPsLsxFPQj6jou8/CZFAmOP2y+6V4PGYt3ihbQKTY1Jnv0QG28WRKl/d1ha6zLODPZqsxLEov52dhR9BQ==", + "dev": true, + "dependencies": { + "@commitlint/top-level": "^19.5.0", + "@commitlint/types": "^19.5.0", + "git-raw-commits": "^4.0.0", + "minimist": "^1.2.8", + "tinyexec": "^0.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/resolve-extends": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.5.0.tgz", + "integrity": "sha512-CU/GscZhCUsJwcKTJS9Ndh3AKGZTNFIOoQB2n8CmFnizE0VnEuJoum+COW+C1lNABEeqk6ssfc1Kkalm4bDklA==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^19.5.0", + "@commitlint/types": "^19.5.0", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/rules": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.5.0.tgz", + "integrity": "sha512-hDW5TPyf/h1/EufSHEKSp6Hs+YVsDMHazfJ2azIk9tHPXS6UqSz1dIRs1gpqS3eMXgtkT7JH6TW4IShdqOwhAw==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^19.5.0", + "@commitlint/message": "^19.5.0", + "@commitlint/to-lines": "^19.5.0", + "@commitlint/types": "^19.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/to-lines": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.5.0.tgz", + "integrity": "sha512-R772oj3NHPkodOSRZ9bBVNq224DOxQtNef5Pl8l2M8ZnkkzQfeSTr4uxawV2Sd3ui05dUVzvLNnzenDBO1KBeQ==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/top-level": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.5.0.tgz", + "integrity": "sha512-IP1YLmGAk0yWrImPRRc578I3dDUI5A2UBJx9FbSOjxe9sTlzFiwVJ+zeMLgAtHMtGZsC8LUnzmW1qRemkFU4ng==", + "dev": true, + "dependencies": { + "find-up": "^7.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@commitlint/types": { + "version": "19.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.5.0.tgz", + "integrity": "sha512-DSHae2obMSMkAtTBSOulg5X7/z+rGLxcXQIkg3OmWvY6wifojge5uVMydfhUvs7yQj+V7jNmRZ2Xzl8GJyqRgg==", + "dev": true, + "dependencies": { + "@types/conventional-commits-parser": "^5.0.0", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "clients/dashboard/node_modules/@types/react": { + "version": "18.3.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.10.tgz", + "integrity": "sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "clients/dashboard/node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "clients/dashboard/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "clients/dashboard/node_modules/conventional-changelog-conventionalcommits": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz", + "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "clients/dashboard/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "clients/dashboard/node_modules/dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "clients/dashboard/node_modules/find-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", + "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", + "dev": true, + "dependencies": { + "locate-path": "^7.2.0", + "path-exists": "^5.0.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "clients/dashboard/node_modules/git-raw-commits": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", + "dev": true, + "dependencies": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "clients/dashboard/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "clients/dashboard/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "clients/dashboard/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "clients/dashboard/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "clients/dashboard/node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "clients/dashboard/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "clients/dashboard/node_modules/tailwindcss": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz", + "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "clients/dashboard/node_modules/tailwindcss/node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "clients/dashboard/node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "clients/dashboard/node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", + "dev": true + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "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/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/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/@babel/helper-create-class-features-plugin": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", + "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.4", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "dev": true, + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", + "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", + "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", + "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", + "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.4", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", + "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.1.tgz", + "integrity": "sha512-SLV/giH/V4SmloZ6Dt40HjTGTAIkxn33TVIHxNGNvo8ezMhrxBkzisj4op1KZYPIOHFLqhv60OHvX+YRu4xbmQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", + "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dev": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", + "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", + "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz", + "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.25.4", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.25.4", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.4", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/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/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@buf/envoyproxy_protoc-gen-validate.bufbuild_es": { + "version": "1.10.0-20240617172848-daf171c6cdb5.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/envoyproxy_protoc-gen-validate.bufbuild_es/-/envoyproxy_protoc-gen-validate.bufbuild_es-1.10.0-20240617172848-daf171c6cdb5.1.tgz", + "peerDependencies": { + "@bufbuild/protobuf": "^1.10.0" + } + }, + "node_modules/@buf/envoyproxy_protoc-gen-validate.connectrpc_es": { + "version": "1.5.0-20240617172848-daf171c6cdb5.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/envoyproxy_protoc-gen-validate.connectrpc_es/-/envoyproxy_protoc-gen-validate.connectrpc_es-1.5.0-20240617172848-daf171c6cdb5.1.tgz", + "dependencies": { + "@buf/envoyproxy_protoc-gen-validate.bufbuild_es": "1.10.0-20240617172848-daf171c6cdb5.1" + }, + "peerDependencies": { + "@connectrpc/connect": "^1.5.0" + } + }, + "node_modules/@buf/evalsocket_cloud.bufbuild_es": { + "version": "1.10.0-20240930133422-6e6299195d4e.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/evalsocket_cloud.bufbuild_es/-/evalsocket_cloud.bufbuild_es-1.10.0-20240930133422-6e6299195d4e.1.tgz", + "dependencies": { + "@buf/envoyproxy_protoc-gen-validate.bufbuild_es": "1.10.0-20240617172848-daf171c6cdb5.1" + }, + "peerDependencies": { + "@bufbuild/protobuf": "^1.10.0" + } + }, + "node_modules/@buf/evalsocket_cloud.connectrpc_es": { + "version": "1.5.0-20240930133422-6e6299195d4e.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/evalsocket_cloud.connectrpc_es/-/evalsocket_cloud.connectrpc_es-1.5.0-20240930133422-6e6299195d4e.1.tgz", + "dependencies": { + "@buf/envoyproxy_protoc-gen-validate.connectrpc_es": "1.5.0-20240617172848-daf171c6cdb5.1", + "@buf/evalsocket_cloud.bufbuild_es": "1.10.0-20240930133422-6e6299195d4e.1" + }, + "peerDependencies": { + "@connectrpc/connect": "^1.5.0" + } + }, + "node_modules/@bufbuild/buf": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/@bufbuild/buf/-/buf-1.42.0.tgz", + "integrity": "sha512-k+Y4Sy9z2O9cOIA7q56WzAGC2xnIvxPfGb3X1+XsbeC0P/c7IW2/aWL324ppER538zCqqMtOwhp0vgljT4mthA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "buf": "bin/buf", + "protoc-gen-buf-breaking": "bin/protoc-gen-buf-breaking", + "protoc-gen-buf-lint": "bin/protoc-gen-buf-lint" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@bufbuild/buf-darwin-arm64": "1.42.0", + "@bufbuild/buf-darwin-x64": "1.42.0", + "@bufbuild/buf-linux-aarch64": "1.42.0", + "@bufbuild/buf-linux-x64": "1.42.0", + "@bufbuild/buf-win32-arm64": "1.42.0", + "@bufbuild/buf-win32-x64": "1.42.0" + } + }, + "node_modules/@bufbuild/buf-darwin-x64": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-x64/-/buf-darwin-x64-1.42.0.tgz", + "integrity": "sha512-qnWjWEWLoC/5meyTvNX7l/px1bJOF8DtnO+HHzlY/bYE1sUl326OXWQbpHyr+R/ftB/A5RYpxkuH9ypi3t+Dag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.10.0.tgz", + "integrity": "sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==" + }, + "node_modules/@bufbuild/protoc-gen-es": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protoc-gen-es/-/protoc-gen-es-1.10.0.tgz", + "integrity": "sha512-zBYBsVT/ul4uZb6F+kD7/k4sWNHVVbEPfJwKi0FDr+9VJo8MKIofI6pkr5ksBLr4fi/74r+e/75Xi/0clL5dXg==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@bufbuild/protobuf": "^1.10.0", + "@bufbuild/protoplugin": "1.10.0" + }, + "bin": { + "protoc-gen-es": "bin/protoc-gen-es" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@bufbuild/protobuf": "1.10.0" + }, + "peerDependenciesMeta": { + "@bufbuild/protobuf": { + "optional": true + } + } + }, + "node_modules/@bufbuild/protoplugin": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protoplugin/-/protoplugin-1.10.0.tgz", + "integrity": "sha512-u6NE4vL0lw1+EK4/PiE/SQB7fKO4LRJNTEScIXVOi2x88K/c8WKc/k0KyEaA0asVBMpwekJQZGnRyj04ZtN5Gg==", + "dev": true, + "dependencies": { + "@bufbuild/protobuf": "1.10.0", + "@typescript/vfs": "^1.4.0", + "typescript": "4.5.2" + } + }, + "node_modules/@bufbuild/protoplugin/node_modules/typescript": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", + "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@commitlint/cli": { + "version": "18.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-18.6.0.tgz", + "integrity": "sha512-FiH23cr9QG8VdfbmvJJZmdfHGVMCouOOAzoXZ3Cd7czGC52RbycwNt8YCI7SA69pAl+t30vh8LMaO/N+kcel6w==", + "dev": true, + "dependencies": { + "@commitlint/format": "^18.6.0", + "@commitlint/lint": "^18.6.0", + "@commitlint/load": "^18.6.0", + "@commitlint/read": "^18.6.0", + "@commitlint/types": "^18.6.0", + "execa": "^5.0.0", + "lodash.isfunction": "^3.0.9", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "18.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-18.6.0.tgz", + "integrity": "sha512-CDCOf2eJz9D/TL44IBks0stM9TmdLCNE2B48owIU3YCadwzts/bobXPScagIgPQF6hhKYMEdj5zpUDlmbwuqwQ==", + "dev": true, + "dependencies": { + "conventional-changelog-conventionalcommits": "^7.0.2" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-18.6.1.tgz", + "integrity": "sha512-05uiToBVfPhepcQWE1ZQBR/Io3+tb3gEotZjnI4tTzzPk16NffN6YABgwFQCLmzZefbDcmwWqJWc2XT47q7Znw==", + "dev": true, + "dependencies": { + "@commitlint/types": "^18.6.1", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/ensure": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-18.6.1.tgz", + "integrity": "sha512-BPm6+SspyxQ7ZTsZwXc7TRQL5kh5YWt3euKmEIBZnocMFkJevqs3fbLRb8+8I/cfbVcAo4mxRlpTPfz8zX7SnQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^18.6.1", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-18.6.1.tgz", + "integrity": "sha512-7s37a+iWyJiGUeMFF6qBlyZciUkF8odSAnHijbD36YDctLhGKoYltdvuJ/AFfRm6cBLRtRk9cCVPdsEFtt/2rg==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-18.6.1.tgz", + "integrity": "sha512-K8mNcfU/JEFCharj2xVjxGSF+My+FbUHoqR+4GqPGrHNqXOGNio47ziiR4HQUPKtiNs05o8/WyLBoIpMVOP7wg==", + "dev": true, + "dependencies": { + "@commitlint/types": "^18.6.1", + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-18.6.1.tgz", + "integrity": "sha512-MOfJjkEJj/wOaPBw5jFjTtfnx72RGwqYIROABudOtJKW7isVjFe9j0t8xhceA02QebtYf4P/zea4HIwnXg8rvA==", + "dev": true, + "dependencies": { + "@commitlint/types": "^18.6.1", + "semver": "7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/lint": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-18.6.1.tgz", + "integrity": "sha512-8WwIFo3jAuU+h1PkYe5SfnIOzp+TtBHpFr4S8oJWhu44IWKuVx6GOPux3+9H1iHOan/rGBaiacicZkMZuluhfQ==", + "dev": true, + "dependencies": { + "@commitlint/is-ignored": "^18.6.1", + "@commitlint/parse": "^18.6.1", + "@commitlint/rules": "^18.6.1", + "@commitlint/types": "^18.6.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-18.6.1.tgz", + "integrity": "sha512-p26x8734tSXUHoAw0ERIiHyW4RaI4Bj99D8YgUlVV9SedLf8hlWAfyIFhHRIhfPngLlCe0QYOdRKYFt8gy56TA==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^18.6.1", + "@commitlint/execute-rule": "^18.6.1", + "@commitlint/resolve-extends": "^18.6.1", + "@commitlint/types": "^18.6.1", + "chalk": "^4.1.0", + "cosmiconfig": "^8.3.6", + "cosmiconfig-typescript-loader": "^5.0.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/message": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-18.6.1.tgz", + "integrity": "sha512-VKC10UTMLcpVjMIaHHsY1KwhuTQtdIKPkIdVEwWV+YuzKkzhlI3aNy6oo1eAN6b/D2LTtZkJe2enHmX0corYRw==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-18.6.1.tgz", + "integrity": "sha512-eS/3GREtvVJqGZrwAGRwR9Gdno3YcZ6Xvuaa+vUF8j++wsmxrA2En3n0ccfVO2qVOLJC41ni7jSZhQiJpMPGOQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^18.6.1", + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-parser": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/read": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-18.6.1.tgz", + "integrity": "sha512-ia6ODaQFzXrVul07ffSgbZGFajpe8xhnDeLIprLeyfz3ivQU1dIoHp7yz0QIorZ6yuf4nlzg4ZUkluDrGN/J/w==", + "dev": true, + "dependencies": { + "@commitlint/top-level": "^18.6.1", + "@commitlint/types": "^18.6.1", + "git-raw-commits": "^2.0.11", + "minimist": "^1.2.6" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-18.6.1.tgz", + "integrity": "sha512-ifRAQtHwK+Gj3Bxj/5chhc4L2LIc3s30lpsyW67yyjsETR6ctHAHRu1FSpt0KqahK5xESqoJ92v6XxoDRtjwEQ==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^18.6.1", + "@commitlint/types": "^18.6.1", + "import-fresh": "^3.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/rules": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-18.6.1.tgz", + "integrity": "sha512-kguM6HxZDtz60v/zQYOe0voAtTdGybWXefA1iidjWYmyUUspO1zBPQEmJZ05/plIAqCVyNUTAiRPWIBKLCrGew==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^18.6.1", + "@commitlint/message": "^18.6.1", + "@commitlint/to-lines": "^18.6.1", + "@commitlint/types": "^18.6.1", + "execa": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-18.6.1.tgz", + "integrity": "sha512-Gl+orGBxYSNphx1+83GYeNy5N0dQsHBQ9PJMriaLQDB51UQHCVLBT/HBdOx5VaYksivSf5Os55TLePbRLlW50Q==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-18.6.1.tgz", + "integrity": "sha512-HyiHQZUTf0+r0goTCDs/bbVv/LiiQ7AVtz6KIar+8ZrseB9+YJAIo8HQ2IC2QT1y3N1lbW6OqVEsTHjbT6hGSw==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/types": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-18.6.1.tgz", + "integrity": "sha512-gwRLBLra/Dozj2OywopeuHj2ac26gjGkz2cZ+86cTJOdtWfiRRr4+e77ZDAGc6MDWxaWheI+mAV5TLWWRwqrFg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@connectrpc/connect": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect/-/connect-1.5.0.tgz", + "integrity": "sha512-1gGg0M6c2Y3lnr5itis9dNj9r8hbOIuBMqoGSbUy7L7Vjw4MAttjJzJfj9HCDgytGCJkGanYEYI6MQVDijdVQw==", + "peerDependencies": { + "@bufbuild/protobuf": "^1.10.0" + } + }, + "node_modules/@connectrpc/connect-next": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect-next/-/connect-next-1.5.0.tgz", + "integrity": "sha512-WTFacM5k2IyQy89JaPsfkKEOgNwhttGR+NZxCYqew/y4BmwolRUWMp5rtzzPKJXh8bgGsNXcml7XuiwOohC0qQ==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@bufbuild/protobuf": "^1.10.0", + "@connectrpc/connect": "1.5.0", + "@connectrpc/connect-node": "1.5.0", + "next": "^13.2.4 || ^14.2.5" + } + }, + "node_modules/@connectrpc/connect-node": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect-node/-/connect-node-1.5.0.tgz", + "integrity": "sha512-go27+V6c6/YOGMXUs7d1NbXnGpMJl5fKYfMtbBKDs9azZTg/tW9q5S0iw9upZs43bOPV8YnJAWmTW9n1Te9NAw==", + "dependencies": { + "undici": "^5.28.4" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@bufbuild/protobuf": "^1.10.0", + "@connectrpc/connect": "1.5.0" + } + }, + "node_modules/@connectrpc/connect-web": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect-web/-/connect-web-1.5.0.tgz", + "integrity": "sha512-xjiiQ932Kibddaka18fGZ6yQL7xjXuLcYFYh/cU+q1WWEIrFPkZfViG/Ee6yrZbrlZkjcBuDibng+q7baTndfg==", + "peerDependencies": { + "@bufbuild/protobuf": "^1.10.0", + "@connectrpc/connect": "1.5.0" + } + }, + "node_modules/@connectrpc/protoc-gen-connect-es": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@connectrpc/protoc-gen-connect-es/-/protoc-gen-connect-es-1.5.0.tgz", + "integrity": "sha512-W3FX/mFPEY3rOIiIbxxUnIpQOPeFrwyhNL5m/JGBJ1lh5PAF0FH4WImJsnN9UAJR1HMkwf6RMfKVLuxFqu3KTA==", + "dev": true, + "dependencies": { + "@bufbuild/protobuf": "^1.10.0", + "@bufbuild/protoplugin": "^1.10.0" + }, + "bin": { + "protoc-gen-connect-es": "bin/protoc-gen-connect-es" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@bufbuild/protoc-gen-es": "^1.10.0", + "@connectrpc/connect": "1.5.0" + }, + "peerDependenciesMeta": { + "@bufbuild/protoc-gen-es": { + "optional": true + }, + "@connectrpc/connect": { + "optional": true + } + } + }, + "node_modules/@corex/deepmerge": { + "version": "2.6.148", + "resolved": "https://registry.npmjs.org/@corex/deepmerge/-/deepmerge-2.6.148.tgz", + "integrity": "sha512-6QMz0/2h5C3ua51iAnXMPWFbb1QOU1UvSM4bKBw5mzdT+WtLgjbETBBIQZ+Sh9WvEcGwlAt/DEdRpIC3XlDBMA==", + "dev": true + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "devOptional": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "devOptional": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", + "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", + "dependencies": { + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz", + "integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "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/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@monaco-editor/loader": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", + "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", + "dependencies": { + "state-local": "^1.0.6" + }, + "peerDependencies": { + "monaco-editor": ">= 0.21.0 < 1" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", + "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", + "dependencies": { + "@monaco-editor/loader": "^1.4.0" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@next/env": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.13.tgz", + "integrity": "sha512-s3lh6K8cbW1h5Nga7NNeXrbe0+2jIIYK9YaA9T7IufDWnZpozdFUp6Hf0d5rNWUKu4fEuSX2rCKlGjCrtylfDw==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.13.tgz", + "integrity": "sha512-z8Mk0VljxhIzsSiZUSdt3wp+t2lKd+jk5a9Jsvh3zDGkItgDMfjv/ZbET6HsxEl/fSihVoHGsXV6VLyDH0lfTQ==", + "dev": true, + "dependencies": { + "glob": "10.3.10" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.13.tgz", + "integrity": "sha512-IkAmQEa2Htq+wHACBxOsslt+jMoV3msvxCn0WFSfJSkv/scy+i/EukBKNad36grRxywaXUYJc9mxEGkeIs8Bzg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.13.tgz", + "integrity": "sha512-Dv1RBGs2TTjkwEnFMVL5XIfJEavnLqqwYSD6LXgTPdEy/u6FlSrLBSSfe1pcfqhFEXRAgVL3Wpjibe5wXJzWog==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.13.tgz", + "integrity": "sha512-yB1tYEFFqo4ZNWkwrJultbsw7NPAAxlPXURXioRl9SdW6aIefOLS+0TEsKrWBtbJ9moTDgU3HRILL6QBQnMevg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.13.tgz", + "integrity": "sha512-v5jZ/FV/eHGoWhMKYrsAweQ7CWb8xsWGM/8m1mwwZQ/sutJjoFaXchwK4pX8NqwImILEvQmZWyb8pPTcP7htWg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.13.tgz", + "integrity": "sha512-aVc7m4YL7ViiRv7SOXK3RplXzOEe/qQzRA5R2vpXboHABs3w8vtFslGTz+5tKiQzWUmTmBNVW0UQdhkKRORmGA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.13.tgz", + "integrity": "sha512-4wWY7/OsSaJOOKvMsu1Teylku7vKyTuocvDLTZQq0TYv9OjiYYWt63PiE1nTuZnqQ4RPvME7Xai+9enoiN0Wrg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.13.tgz", + "integrity": "sha512-uP1XkqCqV2NVH9+g2sC7qIw+w2tRbcMiXFEbMihkQ8B1+V6m28sshBwAB0SDmOe0u44ne1vFU66+gx/28RsBVQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.13.tgz", + "integrity": "sha512-V26ezyjPqQpDBV4lcWIh8B/QICQ4v+M5Bo9ykLN+sqeKKBxJVDpEc6biDVyluTXTC40f5IqCU0ttth7Es2ZuMw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.13.tgz", + "integrity": "sha512-WwzOEAFBGhlDHE5Z73mNU8CO8mqMNLqaG+AO9ETmzdCQlJhVtWZnOl2+rqgVQS+YHunjOWptdFmNfbpwcUuEsw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "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/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", + "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", + "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", + "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "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.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz", + "integrity": "sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.0", + "@radix-ui/react-focus-guards": "1.1.0", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-portal": "1.1.1", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.7" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz", + "integrity": "sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz", + "integrity": "sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==", + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", + "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "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-icons": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz", + "integrity": "sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==", + "peerDependencies": { + "react": "^16.x || ^17.x || ^18.x" + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz", + "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", + "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" + }, + "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.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.1.tgz", + "integrity": "sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", + "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "dependencies": { + "@radix-ui/react-slot": "1.1.0" + }, + "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-select": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.1.tgz", + "integrity": "sha512-8iRDfyLtzxlprOo9IicnzvpsO1wNCkuwzzCM+Z5Rb5tNOpCdMvcc2AkzX0Fz+Tz9v6NJ5B/7EEgyZveo4FBRfQ==", + "dependencies": { + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.0", + "@radix-ui/react-focus-guards": "1.1.0", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-visually-hidden": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.7" + }, + "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.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "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-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "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.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", + "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "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-previous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", + "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", + "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", + "dependencies": { + "@radix-ui/rect": "1.1.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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-visually-hidden": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz", + "integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "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/rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", + "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.5.tgz", + "integrity": "sha512-D8brJEFg5D+QxFcW6jYANu+Rr9SlKtTenmsX5hOSzNYVrK5oLAEMTUgKWYJP+wdKyCdeSwnapLsn+OVRFycuQg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", + "dev": true + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dev": true, + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz", + "integrity": "sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==", + "dev": true, + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20" + } + }, + "node_modules/@testing-library/dom": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", + "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.3.0.tgz", + "integrity": "sha512-hJVIrkFizEQxoWsGBlycTcQhrpoCH4DhXfrnHFFXgkx3Xdm15zycsq5Ep+vpw4W8S0NJa8cxDHcuJib+1tEbhg==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@jest/globals": ">= 28", + "@types/bun": "latest", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/bun": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@testing-library/react": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", + "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.5.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/@testing-library/dom": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", + "integrity": "sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "devOptional": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "devOptional": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "devOptional": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "devOptional": true + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "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.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "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.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.13", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", + "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jest/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@types/jest/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", + "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", + "devOptional": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "devOptional": true + }, + "node_modules/@types/react": { + "version": "18.2.48", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", + "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "devOptional": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.18", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", + "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "devOptional": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==", + "devOptional": true + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.9", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", + "integrity": "sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==", + "dev": true, + "dependencies": { + "@types/jest": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript/vfs": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.0.tgz", + "integrity": "sha512-hvJUjNVeBMp77qPINuUvYXj4FyWeeMMKZkxEATEU3hqBAQ7qdTBCUFT7Sp0Zu0faeEtFf+ldXxMEDr/bk73ISg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "devOptional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "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/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.17", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", + "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.22.2", + "caniuse-lite": "^1.0.30001578", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", + "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/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/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/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/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/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/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/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.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "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.30001663", + "electron-to-chromium": "^1.5.28", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bundle-require": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.2.1.tgz", + "integrity": "sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA==", + "dev": true, + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.17" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001664", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", + "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", + "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/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "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/chokidar/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/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "dev": true + }, + "node_modules/class-variance-authority": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", + "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==", + "dependencies": { + "clsx": "2.0.0" + }, + "funding": { + "url": "https://joebell.co.uk" + } + }, + "node_modules/class-variance-authority/node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "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/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/commitizen": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.3.0.tgz", + "integrity": "sha512-H0iNtClNEhT0fotHvGV3E9tDejDeS04sN1veIebsKYGMuGscFaswRoYJKmT3eW85eIJAs0F28bG2+a/9wCOfPw==", + "dev": true, + "dependencies": { + "cachedir": "2.3.0", + "cz-conventional-changelog": "3.3.0", + "dedent": "0.7.0", + "detect-indent": "6.1.0", + "find-node-modules": "^2.1.2", + "find-root": "1.1.0", + "fs-extra": "9.1.0", + "glob": "7.2.3", + "inquirer": "8.2.5", + "is-utf8": "^0.2.1", + "lodash": "4.17.21", + "minimist": "1.2.7", + "strip-bom": "4.0.0", + "strip-json-comments": "3.1.1" + }, + "bin": { + "commitizen": "bin/commitizen", + "cz": "bin/git-cz", + "git-cz": "bin/git-cz" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/commitizen/node_modules/minimist": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commit-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz", + "integrity": "sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==", + "dev": true + }, + "node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "dev": true, + "dependencies": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "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/core-js-compat": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz", + "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==", + "dev": true, + "dependencies": { + "jiti": "^1.19.1" + }, + "engines": { + "node": ">=v16" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=8.2", + "typescript": ">=4" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "devOptional": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/cz-conventional-changelog": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz", + "integrity": "sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==", + "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@commitlint/load": ">6.1.1" + } + }, + "node_modules/cz-conventional-changelog/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cz-conventional-changelog/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cz-conventional-changelog/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/cz-conventional-changelog/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/cz-conventional-changelog/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/cz-conventional-changelog/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cz-conventional-changelog/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dashboard": { + "resolved": "clients/dashboard", + "link": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "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/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "devOptional": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", + "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "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/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-next": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.13.tgz", + "integrity": "sha512-aro1EKAoyYchnO/3Tlo91hnNBO7QO7qnv/79MAFC+4Jq8TdUVKQlht5d2F+YjrePjdpOvfL+mV9JPfyYNwkk1g==", + "dev": true, + "dependencies": { + "@next/eslint-plugin-next": "14.2.13", + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", + "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", + "dev": true, + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.5", + "enhanced-resolve": "^5.15.0", + "eslint-module-utils": "^2.8.1", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", + "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", + "dev": true, + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.9.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/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/eslint-plugin-jsx-a11y": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.0.tgz", + "integrity": "sha512-ySOHvXX8eSN6zz8Bywacm7CvGNhUtdjvqfQDVe6020TUK34Cywkw7m0KsCCk1Qtm9G1FayfTN1/7mMYnYO2Bhg==", + "dev": true, + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.0.tgz", + "integrity": "sha512-IHBePmfWH5lKhJnJ7WB1V+v/GolbB0rjS8XYVCSQCZKaQCAUhMoVoOEn1Ef8Z8Wf0a7l8KTJvuZg5/e4qrZ6nA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/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/eslint-plugin-simple-import-sort": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-7.0.0.tgz", + "integrity": "sha512-U3vEDB5zhYPNfxT5TYR7u01dboFZp+HNpnGhkDB2g/2E4wZ/g1Q9Ton8UwCLfRV9yAKyYqDh62oHOamvkFxsvw==", + "dev": true, + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, + "node_modules/eslint-plugin-unused-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", + "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", + "dev": true, + "dependencies": { + "eslint-rule-composer": "^0.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "eslint": "^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, + "node_modules/eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-equals": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", + "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "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.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/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/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", + "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "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/find-node-modules": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz", + "integrity": "sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==", + "dev": true, + "dependencies": { + "findup-sync": "^4.0.0", + "merge": "^2.1.1" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "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/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/git-raw-commits": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", + "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "dev": true, + "dependencies": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-raw-commits/node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits/node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/git-raw-commits/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-directory/node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", + "dev": true, + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/goober": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz", + "integrity": "sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inquirer": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", + "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/install": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/install/-/install-0.13.0.tgz", + "integrity": "sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", + "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "dev": true, + "dependencies": { + "semver": "^7.6.3" + } + }, + "node_modules/is-bun-module/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "dev": true, + "dependencies": { + "text-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/jest-circus/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-config/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-leak-detector/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/lint-staged": { + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", + "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", + "dev": true, + "dependencies": { + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.6", + "execa": "~8.0.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.5.0" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", + "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true + }, + "node_modules/lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/longest": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz", + "integrity": "sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "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.438.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.438.0.tgz", + "integrity": "sha512-uq6yCB+IzVfgIPMK8ibkecXSWTTSOMs9UjUgZigfrDCVqgdwkpIgYg1fSYnf0XXF2AoSyCJZhoZXQwzoai7VGw==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "devOptional": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true, + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "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/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "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/monaco-editor": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.0.tgz", + "integrity": "sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==" + }, + "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/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "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/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/next": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.13.tgz", + "integrity": "sha512-BseY9YNw8QJSwLYD7hlZzl6QVDoSFHL/URN5K64kVEVpCsSOWeyjbIGK+dZUaRViHTaMQX8aqmnn0PHBbGZezg==", + "dependencies": { + "@next/env": "14.2.13", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.13", + "@next/swc-darwin-x64": "14.2.13", + "@next/swc-linux-arm64-gnu": "14.2.13", + "@next/swc-linux-arm64-musl": "14.2.13", + "@next/swc-linux-x64-gnu": "14.2.13", + "@next/swc-linux-x64-musl": "14.2.13", + "@next/swc-win32-arm64-msvc": "14.2.13", + "@next/swc-win32-ia32-msvc": "14.2.13", + "@next/swc-win32-x64-msvc": "14.2.13" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-router-mock": { + "version": "0.9.13", + "resolved": "https://registry.npmjs.org/next-router-mock/-/next-router-mock-0.9.13.tgz", + "integrity": "sha512-906n2RRaE6Y28PfYJbaz5XZeJ6Tw8Xz1S6E31GGwZ0sXB6/XjldD1/2azn1ZmBmRk5PQRkzjg+n+RHZe5xQzWA==", + "dev": true, + "peerDependencies": { + "next": ">=10.0.0", + "react": ">=17.0.0" + } + }, + "node_modules/next-sitemap": { + "version": "2.5.28", + "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-2.5.28.tgz", + "integrity": "sha512-rDMTa7nLE0ikYnu8JDCrwQufIRm4b4Sg8BK11DGdDAmYpXmcmw4Qvm+oVBR8gUL97E6i2ihTM+cRx8mgENDACA==", + "dev": true, + "dependencies": { + "@corex/deepmerge": "^2.6.148", + "minimist": "^1.2.6" + }, + "bin": { + "next-sitemap": "bin/next-sitemap" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "next": "*" + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "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.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "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/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm": { + "version": "10.8.3", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.3.tgz", + "integrity": "sha512-0IQlyAYvVtQ7uOhDFYZCGK8kkut2nh8cpAdA9E6FvRSJaTgtZRZgNjlC5ZCct//L73ygrpY93CxXpRJDtNqPVg==", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/promise-spawn", + "@npmcli/redact", + "@npmcli/run-script", + "@sigstore/tuf", + "abbrev", + "archy", + "cacache", + "chalk", + "ci-info", + "cli-columns", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "ms", + "node-gyp", + "nopt", + "normalize-package-data", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "semver", + "spdx-expression-parse", + "ssri", + "supports-color", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^7.5.4", + "@npmcli/config": "^8.3.4", + "@npmcli/fs": "^3.1.1", + "@npmcli/map-workspaces": "^3.0.6", + "@npmcli/package-json": "^5.2.0", + "@npmcli/promise-spawn": "^7.0.2", + "@npmcli/redact": "^2.0.1", + "@npmcli/run-script": "^8.1.0", + "@sigstore/tuf": "^2.3.4", + "abbrev": "^2.0.0", + "archy": "~1.0.0", + "cacache": "^18.0.4", + "chalk": "^5.3.0", + "ci-info": "^4.0.0", + "cli-columns": "^4.0.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.3", + "glob": "^10.4.5", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^7.0.2", + "ini": "^4.1.3", + "init-package-json": "^6.0.3", + "is-cidr": "^5.1.0", + "json-parse-even-better-errors": "^3.0.2", + "libnpmaccess": "^8.0.6", + "libnpmdiff": "^6.1.4", + "libnpmexec": "^8.1.4", + "libnpmfund": "^5.0.12", + "libnpmhook": "^10.0.5", + "libnpmorg": "^6.0.6", + "libnpmpack": "^7.0.4", + "libnpmpublish": "^9.0.9", + "libnpmsearch": "^7.0.6", + "libnpmteam": "^6.0.5", + "libnpmversion": "^6.0.3", + "make-fetch-happen": "^13.0.1", + "minimatch": "^9.0.5", + "minipass": "^7.1.1", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^10.2.0", + "nopt": "^7.2.1", + "normalize-package-data": "^6.0.2", + "npm-audit-report": "^5.0.0", + "npm-install-checks": "^6.3.0", + "npm-package-arg": "^11.0.3", + "npm-pick-manifest": "^9.1.0", + "npm-profile": "^10.0.0", + "npm-registry-fetch": "^17.1.0", + "npm-user-validate": "^2.0.1", + "p-map": "^4.0.0", + "pacote": "^18.0.6", + "parse-conflict-json": "^3.0.1", + "proc-log": "^4.2.0", + "qrcode-terminal": "^0.12.0", + "read": "^3.0.1", + "semver": "^7.6.3", + "spdx-expression-parse": "^4.0.0", + "ssri": "^10.0.6", + "supports-color": "^9.4.0", + "tar": "^6.2.1", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^5.0.1", + "which": "^4.0.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/@npmcli/agent": { + "version": "2.2.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/arborist": { + "version": "7.5.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^3.1.1", + "@npmcli/installed-package-contents": "^2.1.0", + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/metavuln-calculator": "^7.1.1", + "@npmcli/name-from-folder": "^2.0.0", + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.1.0", + "@npmcli/query": "^3.1.0", + "@npmcli/redact": "^2.0.0", + "@npmcli/run-script": "^8.1.0", + "bin-links": "^4.0.4", + "cacache": "^18.0.3", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^7.0.2", + "json-parse-even-better-errors": "^3.0.2", + "json-stringify-nice": "^1.1.4", + "lru-cache": "^10.2.2", + "minimatch": "^9.0.4", + "nopt": "^7.2.1", + "npm-install-checks": "^6.2.0", + "npm-package-arg": "^11.0.2", + "npm-pick-manifest": "^9.0.1", + "npm-registry-fetch": "^17.0.1", + "pacote": "^18.0.6", + "parse-conflict-json": "^3.0.0", + "proc-log": "^4.2.0", + "proggy": "^2.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^10.0.6", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/config": { + "version": "8.3.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/package-json": "^5.1.1", + "ci-info": "^4.0.0", + "ini": "^4.1.2", + "nopt": "^7.2.1", + "proc-log": "^4.2.0", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/fs": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/git": { + "version": "5.0.8", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^7.0.0", + "ini": "^4.1.3", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^4.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/installed-package-contents": { + "version": "2.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/map-workspaces": { + "version": "3.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { + "version": "7.1.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cacache": "^18.0.0", + "json-parse-even-better-errors": "^3.0.0", + "pacote": "^18.0.0", + "proc-log": "^4.1.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/package-json": { + "version": "5.2.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^4.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/promise-spawn": { + "version": "7.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/query": { + "version": "3.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/redact": { + "version": "2.0.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/run-script": { + "version": "8.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", + "proc-log": "^4.0.0", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/@sigstore/bundle": { + "version": "2.3.2", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/core": { + "version": "1.1.0", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/protobuf-specs": { + "version": "0.3.2", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/sign": { + "version": "2.3.2", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.2", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "make-fetch-happen": "^13.0.1", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/tuf": { + "version": "2.3.4", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2", + "tuf-js": "^2.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/verify": { + "version": "1.2.1", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.2", + "@sigstore/core": "^1.1.0", + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/models": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/abbrev": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/agent-base": { + "version": "7.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/aggregate-error": { + "version": "3.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-styles": { + "version": "6.2.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/aproba": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/archy": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/balanced-match": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/bin-links": { + "version": "4.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/binary-extensions": { + "version": "2.3.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/brace-expansion": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm/node_modules/cacache": { + "version": "18.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/chalk": { + "version": "5.3.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm/node_modules/chownr": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ci-info": { + "version": "4.0.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/cidr-regex": { + "version": "4.1.1", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "ip-regex": "^5.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/clean-stack": { + "version": "2.2.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/cli-columns": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/cmd-shim": { + "version": "6.0.3", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/color-convert": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/npm/node_modules/color-name": { + "version": "1.1.4", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/common-ancestor-path": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/cross-spawn": { + "version": "7.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cssesc": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/debug": { + "version": "4.3.6", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/npm/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/diff": { + "version": "5.2.0", + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/npm/node_modules/eastasianwidth": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/emoji-regex": { + "version": "8.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/encoding": { + "version": "0.1.13", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/npm/node_modules/env-paths": { + "version": "2.2.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/err-code": { + "version": "2.0.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/exponential-backoff": { + "version": "3.1.1", + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/npm/node_modules/fastest-levenshtein": { + "version": "1.0.16", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/npm/node_modules/foreground-child": { + "version": "3.3.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/fs-minipass": { + "version": "3.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/glob": { + "version": "10.4.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/graceful-fs": { + "version": "4.2.11", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/hosted-git-info": { + "version": "7.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/http-cache-semantics": { + "version": "4.1.1", + "inBundle": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/http-proxy-agent": { + "version": "7.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/https-proxy-agent": { + "version": "7.0.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/iconv-lite": { + "version": "0.6.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/ignore-walk": { + "version": "6.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/imurmurhash": { + "version": "0.1.4", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/npm/node_modules/indent-string": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ini": { + "version": "4.1.3", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/init-package-json": { + "version": "6.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/package-json": "^5.0.0", + "npm-package-arg": "^11.0.0", + "promzard": "^1.0.0", + "read": "^3.0.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/ip-address": { + "version": "9.0.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/npm/node_modules/ip-regex": { + "version": "5.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/is-cidr": { + "version": "5.1.0", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "cidr-regex": "^4.1.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/is-lambda": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/isexe": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/jackspeak": { + "version": "3.4.3", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/npm/node_modules/jsbn": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/json-stringify-nice": { + "version": "1.1.4", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/jsonparse": { + "version": "1.3.1", + "engines": [ + "node >= 0.2.0" + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff": { + "version": "6.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff-apply": { + "version": "5.5.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/libnpmaccess": { + "version": "8.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^11.0.2", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff": { + "version": "6.1.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.4", + "@npmcli/installed-package-contents": "^2.1.0", + "binary-extensions": "^2.3.0", + "diff": "^5.1.0", + "minimatch": "^9.0.4", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.6", + "tar": "^6.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmexec": { + "version": "8.1.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.4", + "@npmcli/run-script": "^8.1.0", + "ci-info": "^4.0.0", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.6", + "proc-log": "^4.2.0", + "read": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmfund": { + "version": "5.0.12", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmhook": { + "version": "10.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmorg": { + "version": "6.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpack": { + "version": "7.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.4", + "@npmcli/run-script": "^8.1.0", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.6" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpublish": { + "version": "9.0.9", + "inBundle": true, + "license": "ISC", + "dependencies": { + "ci-info": "^4.0.0", + "normalize-package-data": "^6.0.1", + "npm-package-arg": "^11.0.2", + "npm-registry-fetch": "^17.0.1", + "proc-log": "^4.2.0", + "semver": "^7.3.7", + "sigstore": "^2.2.0", + "ssri": "^10.0.6" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmsearch": { + "version": "7.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmteam": { + "version": "6.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmversion": { + "version": "6.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.7", + "@npmcli/run-script": "^8.1.0", + "json-parse-even-better-errors": "^3.0.2", + "proc-log": "^4.2.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/lru-cache": { + "version": "10.4.3", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/make-fetch-happen": { + "version": "13.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/minimatch": { + "version": "9.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/minipass": { + "version": "7.1.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-collect": { + "version": "2.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-fetch": { + "version": "3.0.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm/node_modules/minipass-flush": { + "version": "1.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline": { + "version": "1.2.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized": { + "version": "1.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minizlib": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/mkdirp": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ms": { + "version": "2.1.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/mute-stream": { + "version": "1.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/negotiator": { + "version": "0.6.3", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/node-gyp": { + "version": "10.2.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^4.1.0", + "semver": "^7.3.5", + "tar": "^6.2.1", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/nopt": { + "version": "7.2.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/normalize-package-data": { + "version": "6.0.2", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-audit-report": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-bundled": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-install-checks": { + "version": "6.3.0", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-package-arg": { + "version": "11.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-packlist": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "ignore-walk": "^6.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-pick-manifest": { + "version": "9.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-profile": { + "version": "10.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^17.0.1", + "proc-log": "^4.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-registry-fetch": { + "version": "17.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/redact": "^2.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-user-validate": { + "version": "2.0.1", + "inBundle": true, + "license": "BSD-2-Clause", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/p-map": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/package-json-from-dist": { + "version": "1.0.0", + "inBundle": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/npm/node_modules/pacote": { + "version": "18.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/package-json": "^5.1.0", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^8.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^17.0.0", + "proc-log": "^4.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^2.2.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/parse-conflict-json": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/path-key": { + "version": "3.1.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/path-scurry": { + "version": "1.11.1", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/proc-log": { + "version": "4.2.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/proggy": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/promise-all-reject-late": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-call-limit": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-inflight": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/promise-retry": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/promzard": { + "version": "1.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "read": "^3.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/qrcode-terminal": { + "version": "0.12.0", + "inBundle": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/npm/node_modules/read": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-cmd-shim": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json-fast": { + "version": "3.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/retry": { + "version": "0.12.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm/node_modules/safer-buffer": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/npm/node_modules/semver": { + "version": "7.6.3", + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/shebang-command": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/shebang-regex": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/signal-exit": { + "version": "4.1.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/sigstore": { + "version": "2.3.1", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.2", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "@sigstore/sign": "^2.3.2", + "@sigstore/tuf": "^2.3.4", + "@sigstore/verify": "^1.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/smart-buffer": { + "version": "4.2.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks": { + "version": "2.8.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks-proxy-agent": { + "version": "8.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/spdx-correct": { + "version": "3.2.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-exceptions": { + "version": "2.5.0", + "inBundle": true, + "license": "CC-BY-3.0" + }, + "node_modules/npm/node_modules/spdx-expression-parse": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-license-ids": { + "version": "3.0.18", + "inBundle": true, + "license": "CC0-1.0" + }, + "node_modules/npm/node_modules/sprintf-js": { + "version": "1.1.3", + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/npm/node_modules/ssri": { + "version": "10.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/string-width": { + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/supports-color": { + "version": "9.4.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/npm/node_modules/tar": { + "version": "6.2.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/text-table": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/tiny-relative-date": { + "version": "1.3.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/treeverse": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/tuf-js": { + "version": "2.2.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/models": "2.0.1", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-filename": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-slug": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/util-deprecate": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-name": { + "version": "5.0.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/walk-up-path": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/which": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/which/node_modules/isexe": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/npm/node_modules/wrap-ansi": { + "version": "8.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/write-file-atomic": { + "version": "5.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/yallist": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + }, + "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/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-tailwindcss": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.11.tgz", + "integrity": "sha512-AvI/DNyMctyyxGOjyePgi/gqj5hJYClZ1avtQvLlqMT3uDZkRbi4HhGUpok3DRzv9z7Lti85Kdj3s3/1CeNI0w==", + "dev": true, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "prettier": "^3.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-import-sort": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-marko": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-style-order": "*", + "prettier-plugin-svelte": "*" + }, + "peerDependenciesMeta": { + "@ianvs/prettier-plugin-sort-imports": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-import-sort": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-marko": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-style-order": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + }, + "prettier-plugin-twig-melody": { + "optional": true + } + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "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/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-hot-toast": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz", + "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==", + "dependencies": { + "goober": "^2.1.10" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/react-icons": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz", + "integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/react-remove-scroll": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz", + "integrity": "sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.4", + "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/react-remove-scroll-bar": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", + "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", + "dependencies": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + }, + "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/react-smooth": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz", + "integrity": "sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dependencies": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + }, + "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/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/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/recharts": { + "version": "2.12.7", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.12.7.tgz", + "integrity": "sha512-hlLJMhPQfv4/3NBSAyq3gzGg4h2v69RJh6KU7b3pXYNNAELs9kEoXOjbkxdXpALqKBoVmVptGfLpxdaVYqjmXQ==", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^16.10.2", + "react-smooth": "^4.0.0", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/recharts/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/recharts/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "dev": true, + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.5.tgz", + "integrity": "sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.22.5", + "@rollup/rollup-android-arm64": "4.22.5", + "@rollup/rollup-darwin-arm64": "4.22.5", + "@rollup/rollup-darwin-x64": "4.22.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.22.5", + "@rollup/rollup-linux-arm-musleabihf": "4.22.5", + "@rollup/rollup-linux-arm64-gnu": "4.22.5", + "@rollup/rollup-linux-arm64-musl": "4.22.5", + "@rollup/rollup-linux-powerpc64le-gnu": "4.22.5", + "@rollup/rollup-linux-riscv64-gnu": "4.22.5", + "@rollup/rollup-linux-s390x-gnu": "4.22.5", + "@rollup/rollup-linux-x64-gnu": "4.22.5", + "@rollup/rollup-linux-x64-musl": "4.22.5", + "@rollup/rollup-win32-arm64-msvc": "4.22.5", + "@rollup/rollup-win32-ia32-msvc": "4.22.5", + "@rollup/rollup-win32-x64-msvc": "4.22.5", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "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/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tailwind-merge": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.2.tgz", + "integrity": "sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", + "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.19.1", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "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/tailwindcss/node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, + "node_modules/tinyexec": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", + "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "dev": true + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "devOptional": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "devOptional": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "devOptional": true + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/tsup": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.0.1.tgz", + "integrity": "sha512-hvW7gUSG96j53ZTSlT4j/KL0q1Q2l6TqGBFc6/mu/L46IoNWqLLUzLRLP1R8Q7xrJTmkDxxDoojV5uCVs1sVOg==", + "dev": true, + "dependencies": { + "bundle-require": "^4.0.0", + "cac": "^6.7.12", + "chokidar": "^3.5.1", + "debug": "^4.3.1", + "esbuild": "^0.19.2", + "execa": "^5.0.0", + "globby": "^11.0.3", + "joycon": "^3.0.1", + "postcss-load-config": "^4.0.1", + "resolve-from": "^5.0.0", + "rollup": "^4.0.2", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.20.3", + "tree-kill": "^1.2.2" + }, + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@microsoft/api-extractor": "^7.36.0", + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/tsup/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tsup/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tsup/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/tsup/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/turbo": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.11.3.tgz", + "integrity": "sha512-RCJOUFcFMQNIGKSjC9YmA5yVP1qtDiBA0Lv9VIgrXraI5Da1liVvl3VJPsoDNIR9eFMyA/aagx1iyj6UWem5hA==", + "dev": true, + "bin": { + "turbo": "bin/turbo" + }, + "optionalDependencies": { + "turbo-darwin-64": "1.11.3", + "turbo-darwin-arm64": "1.11.3", + "turbo-linux-64": "1.11.3", + "turbo-linux-arm64": "1.11.3", + "turbo-windows-64": "1.11.3", + "turbo-windows-arm64": "1.11.3" + } + }, + "node_modules/turbo-darwin-64": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.11.3.tgz", + "integrity": "sha512-IsOOg2bVbIt3o/X8Ew9fbQp5t1hTHN3fGNQYrPQwMR2W1kIAC6RfbVD4A9OeibPGyEPUpwOH79hZ9ydFH5kifw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "devOptional": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "dev": true, + "funding": [ + { + "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.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", + "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "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/use-sidecar": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "devOptional": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ac1bda8 --- /dev/null +++ b/package.json @@ -0,0 +1,59 @@ +{ + "name": "task", + "version": "0.0.1", + "private": true, + "workspaces": [ + "clients/*" + ], + "packageManager": "npm@10.1.0", + "scripts": { + "build": "turbo build ", + "dev": "turbo dev", + "lint": "turbo lint", + "tsc": "turbo tsc", + "test": "turbo test", + "format-lint": "prettier --config .prettierrc --check --ignore-unknown .", + "format-fix": "prettier --config .prettierrc --write --ignore-unknown -l .", + "clean": "npm exec --workspaces -- shx rm -rf node_modules .next .turbo coverage dist compiled build-next-static && shx rm -rf node_modules", + "remove-turbo-cache": "shx rm -rf ./node_modules/.cache/turbo", + "update-dependencies": "turbo update-dependencies && npx npm-check-updates -u" + }, + "devDependencies": { + "@commitlint/cli": "18.6.0", + "@commitlint/config-conventional": "18.6.0", + "@connectrpc/protoc-gen-connect-es": "^1.5.0", + "@svgr/webpack": "^8.1.0", + "@tailwindcss/forms": "^0.5.9", + "@testing-library/dom": "9.3.4", + "@testing-library/jest-dom": "^6.3.0", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "14.5.2", + "@types/node": "20.11.10", + "@types/react": "18.2.48", + "@types/react-dom": "18.2.18", + "@types/testing-library__jest-dom": "^5.14.9", + "@typescript-eslint/eslint-plugin": "^5.62.0", + "@typescript-eslint/parser": "^5.62.0", + "autoprefixer": "10.4.17", + "commitizen": "4.3.0", + "eslint": "^8.57.1", + "eslint-config-next": "^14.2.13", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-simple-import-sort": "^7.0.0", + "eslint-plugin-unused-imports": "^2.0.0", + "jest": "^29.7.0", + "lint-staged": "^15.2.10", + "next-router-mock": "^0.9.0", + "next-sitemap": "^2.5.28", + "postcss": "8.4.33", + "prettier": "3.2.4", + "prettier-plugin-tailwindcss": "0.5.11", + "tailwindcss": "3.4.1", + "ts-node": "10.9.2", + "tsup": "8.0.1", + "turbo": "1.11.3", + "typescript": "5.3.3" + }, + "dependencies": { + } +} diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 0000000..13af399 --- /dev/null +++ b/pixi.lock @@ -0,0 +1,2122 @@ +version: 5 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/_go_select-2.3.0-cgo.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.31-hb28a666_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.7.4-h8128ea2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.28-h00291cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.2.19-h8128ea2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.4.3-hcd1ed9e_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.8.10-h2f86973_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.14.18-hf9a0f1c_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.10.6-h9d7d61c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.6.6-hd01826e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.1.19-h8128ea2_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.20-h8128ea2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.28.3-h21c617a_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.407-h2e282c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-hfdf4475_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.33.1-h44e7173_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.8.30-h8857fd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.17.1-py310hfce808e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.3.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/curl-8.10.1-h58e7537_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.16.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gettext-0.22.5-hdfe23c8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gettext-tools-0.22.5-hdfe23c8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/git-2.42.0-pl5321hba7a703_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/go-1.21.7-he277650_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20240116.2-cxx17_hf036a51_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-h2902fa7_44_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-14.0.2-hf036a51_44_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-14.0.2-hf036a51_44_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-14.0.2-hd834827_44_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-sql-14.0.2-he1e86a1_44_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-gandiva-14.0.2-hfa04d5a_44_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-14.0.2-he1e86a1_44_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libasprintf-0.22.5-hdfe23c8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libasprintf-devel-0.22.5-hdfe23c8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.1.0-h00291cd_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.1.0-h00291cd_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.1.0-h00291cd_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.10.1-h58e7537_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-19.1.0-hf95d169_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.3-hac325c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgettextpo-0.22.5-hdfe23c8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgettextpo-devel-0.22.5-hdfe23c8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-5.0.0-13_2_0_h97931a8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-13.2.0-h2873a65_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-2.29.0-hecd3d69_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-2.29.0-h8126ed0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.62.2-h384b2fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-0.22.5-hdfe23c8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-devel-0.22.5-hdfe23c8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm16-16.0.6-hbedff68_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.27-openmp_h8869122_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-14.0.2-h808e2ea_44_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-4.25.3-hd4aba4c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2023.09.01-h81f5012_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.46.1-h4b8f8c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.20.0-h75589b3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.8.0-hb7f2c08_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.48.0-h67532ce_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.7-hc603aa4_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-h87427d6_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.8-h15ab845_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.9.4-hf0c8a7f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-hf036a51_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-20.9.0-hfc0f20e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py310h4bfa8fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.2-hd23fc13_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.0.2-h22b2039_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pcre2-10.42-h0ad2156_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/perl-5.32.1-7_h10d778d_perl5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.2-pyh8b19718_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.3.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-3.3.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py310hcd1d8fd_44_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.15-h6bafeb6_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.10-5_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.2-py310h837254d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.1-he1e6707_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h8827d51_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.0.1-py310hfa8da69_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.26.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.44.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.1-h87427d6_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.6-h915ae27_0.conda +packages: +- kind: conda + name: _go_select + version: 2.3.0 + build: cgo + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/_go_select-2.3.0-cgo.tar.bz2 + sha256: faf9b29f369ccf41da3998b00945e56daa331d01a8ffe7832e45651db0716028 + md5: 4c1913031a736507963a5fb938cefe85 + license: BSD-3-Clause + license_family: BSD + size: 4770 + timestamp: 1586504733574 +- kind: conda + name: aws-c-auth + version: 0.7.31 + build: hb28a666_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.31-hb28a666_0.conda + sha256: 51bf3047115f21c89e96999ec7a0c46a7684334ffe5a3584547a2e1f9e14ba2a + md5: d14e2cb987740374e14e871456356b76 + depends: + - __osx >=10.13 + - aws-c-cal >=0.7.4,<0.7.5.0a0 + - aws-c-common >=0.9.28,<0.9.29.0a0 + - aws-c-http >=0.8.10,<0.8.11.0a0 + - aws-c-io >=0.14.18,<0.14.19.0a0 + - aws-c-sdkutils >=0.1.19,<0.1.20.0a0 + license: Apache-2.0 + license_family: Apache + size: 94230 + timestamp: 1726544392579 +- kind: conda + name: aws-c-cal + version: 0.7.4 + build: h8128ea2_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.7.4-h8128ea2_1.conda + sha256: 6ffa143181fa40bbbe1b5dfad149b68e4c3fcb6e5d38a4f5a4490c8c3b4402df + md5: 195ef3e2d7dadb02a4b1f874a1e5e1e6 + depends: + - __osx >=10.13 + - aws-c-common >=0.9.28,<0.9.29.0a0 + - openssl >=3.3.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 39204 + timestamp: 1725829973 +- kind: conda + name: aws-c-common + version: 0.9.28 + build: h00291cd_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.28-h00291cd_0.conda + sha256: 9af8c4514526829de390bc5f5c103487dff1cd025463ea90b7f8dbb8f1d0ff16 + md5: ffe8898e6d97ecb791df1350ce273508 + depends: + - __osx >=10.13 + license: Apache-2.0 + license_family: Apache + size: 225877 + timestamp: 1725670122224 +- kind: conda + name: aws-c-compression + version: 0.2.19 + build: h8128ea2_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.2.19-h8128ea2_1.conda + sha256: f60f8bec5eddd1974367aac03a646996374d8f290bb4463dfbf1e7620462e7be + md5: 43be0637437461d48ff524c04459ee46 + depends: + - __osx >=10.13 + - aws-c-common >=0.9.28,<0.9.29.0a0 + license: Apache-2.0 + license_family: Apache + size: 17936 + timestamp: 1725829971987 +- kind: conda + name: aws-c-event-stream + version: 0.4.3 + build: hcd1ed9e_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.4.3-hcd1ed9e_2.conda + sha256: f717b5d9baa8206d7069f80cd2f5a2cd99747b3f1e3aed4bea7e392846979d9b + md5: 73bde3fabf8b8f6f2be9cc6f152d0606 + depends: + - __osx >=10.13 + - aws-c-common >=0.9.28,<0.9.29.0a0 + - aws-c-io >=0.14.18,<0.14.19.0a0 + - aws-checksums >=0.1.20,<0.1.21.0a0 + - libcxx >=17 + license: Apache-2.0 + license_family: Apache + size: 46699 + timestamp: 1726327279325 +- kind: conda + name: aws-c-http + version: 0.8.10 + build: h2f86973_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.8.10-h2f86973_0.conda + sha256: dae6a6be9a6fc1c2d6318c62d2b89e20fe75d8df5a4b7766b95be788cfb9516c + md5: 4160f0e92d2f25532ee52b625556e488 + depends: + - __osx >=10.13 + - aws-c-cal >=0.7.4,<0.7.5.0a0 + - aws-c-common >=0.9.28,<0.9.29.0a0 + - aws-c-compression >=0.2.19,<0.2.20.0a0 + - aws-c-io >=0.14.18,<0.14.19.0a0 + license: Apache-2.0 + license_family: Apache + size: 164396 + timestamp: 1726469195066 +- kind: conda + name: aws-c-io + version: 0.14.18 + build: hf9a0f1c_10 + build_number: 10 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.14.18-hf9a0f1c_10.conda + sha256: 05c3ddc17afefff534fdcbb3d11a5bc4c206ab978587b1ce4705819682812cf2 + md5: b67c9a5bb5ac35cafd8bb6246d5e1059 + depends: + - __osx >=10.13 + - aws-c-cal >=0.7.4,<0.7.5.0a0 + - aws-c-common >=0.9.28,<0.9.29.0a0 + license: Apache-2.0 + license_family: Apache + size: 138546 + timestamp: 1726903618199 +- kind: conda + name: aws-c-mqtt + version: 0.10.6 + build: h9d7d61c_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.10.6-h9d7d61c_0.conda + sha256: bd8cc5cdb47f3c6cd953e33269714df466a428e7a16ea30028f68829c4452216 + md5: 41ede335d3fb845c49043dab04db1576 + depends: + - __osx >=10.13 + - aws-c-common >=0.9.28,<0.9.29.0a0 + - aws-c-http >=0.8.10,<0.8.11.0a0 + - aws-c-io >=0.14.18,<0.14.19.0a0 + license: Apache-2.0 + license_family: Apache + size: 164343 + timestamp: 1726795118999 +- kind: conda + name: aws-c-s3 + version: 0.6.6 + build: hd01826e_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.6.6-hd01826e_0.conda + sha256: 24794cfcaf9d6da28192dda88449dad1e112408a96c51e5a0df6a1925c4e8a57 + md5: 7fa9af757e8376f738eb314518ec282b + depends: + - __osx >=10.13 + - aws-c-auth >=0.7.31,<0.7.32.0a0 + - aws-c-cal >=0.7.4,<0.7.5.0a0 + - aws-c-common >=0.9.28,<0.9.29.0a0 + - aws-c-http >=0.8.10,<0.8.11.0a0 + - aws-c-io >=0.14.18,<0.14.19.0a0 + - aws-checksums >=0.1.20,<0.1.21.0a0 + license: Apache-2.0 + license_family: Apache + size: 97414 + timestamp: 1726722505830 +- kind: conda + name: aws-c-sdkutils + version: 0.1.19 + build: h8128ea2_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.1.19-h8128ea2_3.conda + sha256: 50912641279d00a6ce12b1d72e74ea5d30078e91a0557a48a9e9fe285c2f6b2c + md5: 8d93b3603363214303737f74b6efb5da + depends: + - __osx >=10.13 + - aws-c-common >=0.9.28,<0.9.29.0a0 + license: Apache-2.0 + license_family: Apache + size: 50686 + timestamp: 1725836776385 +- kind: conda + name: aws-checksums + version: 0.1.20 + build: h8128ea2_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.20-h8128ea2_0.conda + sha256: 1953103f0ead6ffbcb73ddbcec617ce9195010fea838f63b5e8e93b8d4bf4bcb + md5: 1fbab35b839a3d822f1b39680298fd9f + depends: + - __osx >=10.13 + - aws-c-common >=0.9.28,<0.9.29.0a0 + license: Apache-2.0 + license_family: Apache + size: 70818 + timestamp: 1726281979944 +- kind: conda + name: aws-crt-cpp + version: 0.28.3 + build: h21c617a_5 + build_number: 5 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.28.3-h21c617a_5.conda + sha256: 95cc7a027ca0c06c4a77f9e08ea7d8f16d32cad36db9bc4670d5a1e970d15971 + md5: 6de09093d1c0f5aa1f4bd9d91923c9df + depends: + - __osx >=10.13 + - aws-c-auth >=0.7.31,<0.7.32.0a0 + - aws-c-cal >=0.7.4,<0.7.5.0a0 + - aws-c-common >=0.9.28,<0.9.29.0a0 + - aws-c-event-stream >=0.4.3,<0.4.4.0a0 + - aws-c-http >=0.8.10,<0.8.11.0a0 + - aws-c-io >=0.14.18,<0.14.19.0a0 + - aws-c-mqtt >=0.10.6,<0.10.7.0a0 + - aws-c-s3 >=0.6.6,<0.6.7.0a0 + - aws-c-sdkutils >=0.1.19,<0.1.20.0a0 + - libcxx >=17 + license: Apache-2.0 + license_family: Apache + size: 293921 + timestamp: 1726821921771 +- kind: conda + name: aws-sdk-cpp + version: 1.11.407 + build: h2e282c2_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.407-h2e282c2_0.conda + sha256: c6a88e7882325c56e1f25252a5529bd24650207ab44cb31e976daa9b5d8b1914 + md5: 16c5992e1c374f160128336cdf64e171 + depends: + - __osx >=10.13 + - aws-c-common >=0.9.28,<0.9.29.0a0 + - aws-c-event-stream >=0.4.3,<0.4.4.0a0 + - aws-checksums >=0.1.20,<0.1.21.0a0 + - aws-crt-cpp >=0.28.3,<0.28.4.0a0 + - libcurl >=8.10.0,<9.0a0 + - libcxx >=17 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.3.2,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 2787167 + timestamp: 1726638546148 +- kind: conda + name: bzip2 + version: 1.0.8 + build: hfdf4475_7 + build_number: 7 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-hfdf4475_7.conda + sha256: cad153608b81fb24fc8c509357daa9ae4e49dfc535b2cb49b91e23dbd68fc3c5 + md5: 7ed4301d437b59045be7e051a0308211 + depends: + - __osx >=10.13 + license: bzip2-1.0.6 + license_family: BSD + size: 134188 + timestamp: 1720974491916 +- kind: conda + name: c-ares + version: 1.33.1 + build: h44e7173_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.33.1-h44e7173_0.conda + sha256: 98b0ac09472e6737fc4685147d1755028cc650d428369cbe3cb74ab38b327095 + md5: b31a2de5edfddb308dda802eab2956dc + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + size: 163203 + timestamp: 1724438157472 +- kind: conda + name: ca-certificates + version: 2024.8.30 + build: h8857fd0_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.8.30-h8857fd0_0.conda + sha256: 593f302d0f44c2c771e1614ee6d56fffdc7d616e6f187669c8b0e34ffce3e1ae + md5: b7e5424e7f06547a903d28e4651dbb21 + license: ISC + size: 158665 + timestamp: 1725019059295 +- kind: conda + name: cffi + version: 1.17.1 + build: py310hfce808e_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.17.1-py310hfce808e_0.conda + sha256: a9a98a09031c4b5304ca04d29f9b35329e40a915e8e9c6431daee97c1b606d36 + md5: eefa80a0b01ffccf57c7c865bc6acfc4 + depends: + - __osx >=10.13 + - libffi >=3.4,<4.0a0 + - pycparser + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + size: 229844 + timestamp: 1725560765436 +- kind: conda + name: cfgv + version: 3.3.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.3.1-pyhd8ed1ab_0.tar.bz2 + sha256: fbc03537a27ef756162c49b1d0608bf7ab12fa5e38ceb8563d6f4859e835ac5c + md5: ebb5f5f7dc4f1a3780ef7ea7738db08c + depends: + - python >=3.6.1 + license: MIT + license_family: MIT + size: 10788 + timestamp: 1629909423398 +- kind: conda + name: colorama + version: 0.4.6 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + sha256: 2c1b2e9755ce3102bca8d69e8f26e4f087ece73f50418186aee7c74bef8e1698 + md5: 3faab06a954c2a04039983f2c4a50d99 + depends: + - python >=3.7 + license: BSD-3-Clause + license_family: BSD + size: 25170 + timestamp: 1666700778190 +- kind: conda + name: curl + version: 8.10.1 + build: h58e7537_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/curl-8.10.1-h58e7537_0.conda + sha256: 314ef19bca95a69396780cdc97bd8fcb72215e434873161c8bfd97a3e88187f4 + md5: c21fe6ee51849309dc7b3651ca3c75ad + depends: + - __osx >=10.13 + - krb5 >=1.21.3,<1.22.0a0 + - libcurl 8.10.1 h58e7537_0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.3.2,<4.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: curl + license_family: MIT + size: 159638 + timestamp: 1726660283789 +- kind: conda + name: distlib + version: 0.3.8 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.8-pyhd8ed1ab_0.conda + sha256: 3ff11acdd5cc2f80227682966916e878e45ced94f59c402efb94911a5774e84e + md5: db16c66b759a64dc5183d69cc3745a52 + depends: + - python 2.7|>=3.6 + license: Apache-2.0 + license_family: APACHE + size: 274915 + timestamp: 1702383349284 +- kind: conda + name: exceptiongroup + version: 1.2.2 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.2-pyhd8ed1ab_0.conda + sha256: e0edd30c4b7144406bb4da975e6bb97d6bc9c0e999aa4efe66ae108cada5d5b5 + md5: d02ae936e42063ca46af6cdad2dbd1e0 + depends: + - python >=3.7 + license: MIT and PSF-2.0 + size: 20418 + timestamp: 1720869435725 +- kind: conda + name: filelock + version: 3.16.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/filelock-3.16.1-pyhd8ed1ab_0.conda + sha256: 1da766da9dba05091af87977922fe60dc7464091a9ccffb3765d403189d39be4 + md5: 916f8ec5dd4128cd5f207a3c4c07b2c6 + depends: + - python >=3.7 + license: Unlicense + size: 17357 + timestamp: 1726613593584 +- kind: conda + name: gettext + version: 0.22.5 + build: hdfe23c8_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/gettext-0.22.5-hdfe23c8_3.conda + sha256: f68cd35c98394dc322f2695a720b31b77a9cdfe7d5c08ce53bc68c9e3fe4c6ec + md5: 4e53e0f241c09fcdf674e4a37c0c70e6 + depends: + - __osx >=10.13 + - gettext-tools 0.22.5 hdfe23c8_3 + - libasprintf 0.22.5 hdfe23c8_3 + - libasprintf-devel 0.22.5 hdfe23c8_3 + - libcxx >=16 + - libgettextpo 0.22.5 hdfe23c8_3 + - libgettextpo-devel 0.22.5 hdfe23c8_3 + - libiconv >=1.17,<2.0a0 + - libintl 0.22.5 hdfe23c8_3 + - libintl-devel 0.22.5 hdfe23c8_3 + license: LGPL-2.1-or-later AND GPL-3.0-or-later + size: 480155 + timestamp: 1723627002489 +- kind: conda + name: gettext-tools + version: 0.22.5 + build: hdfe23c8_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/gettext-tools-0.22.5-hdfe23c8_3.conda + sha256: 7fe97828eae5e067b68dd012811e614e057854ed51116bbd2fd2e8d05439ad63 + md5: 70a5bb1505016ebdba1214ba10de0503 + depends: + - __osx >=10.13 + - libiconv >=1.17,<2.0a0 + - libintl 0.22.5 hdfe23c8_3 + license: GPL-3.0-or-later + license_family: GPL + size: 2513986 + timestamp: 1723626957941 +- kind: conda + name: gflags + version: 2.2.2 + build: hac325c4_1005 + build_number: 1005 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda + sha256: c0bea66f71a6f4baa8d4f0248e17f65033d558d9e882c0af571b38bcca3e4b46 + md5: a26de8814083a6971f14f9c8c3cb36c2 + depends: + - __osx >=10.13 + - libcxx >=17 + license: BSD-3-Clause + license_family: BSD + size: 84946 + timestamp: 1726600054963 +- kind: conda + name: git + version: 2.42.0 + build: pl5321hba7a703_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/git-2.42.0-pl5321hba7a703_1.conda + sha256: fcb72f01d482c981f8a18c3313fcf8b4cd801dbea48ba22ea8b154a2c800e0ca + md5: 6b132a44d4c1d735284717c3157cc56e + depends: + - __osx >=10.9 + - curl + - gettext + - libexpat >=2.5.0,<3.0a0 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.2.0,<4.0a0 + - pcre2 >=10.42,<10.43.0a0 + - perl 5.* + license: GPL-2.0-or-later and LGPL-2.1-or-later + size: 7744105 + timestamp: 1701087084155 +- kind: conda + name: glog + version: 0.7.1 + build: h2790a97_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda + sha256: dd56547db8625eb5c91bb0a9fbe8bd6f5c7fbf5b6059d46365e94472c46b24f9 + md5: 06cf91665775b0da395229cd4331b27d + depends: + - __osx >=10.13 + - gflags >=2.2.2,<2.3.0a0 + - libcxx >=16 + license: BSD-3-Clause + license_family: BSD + size: 117017 + timestamp: 1718284325443 +- kind: conda + name: go + version: 1.21.7 + build: he277650_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/go-1.21.7-he277650_1.conda + sha256: 7517ded674f87b6f20e14f65278c02ca693a283b7bf267377ba2c1ae611946bc + md5: 7088f14421790ec079e65a1490ad349e + depends: + - __osx >=10.14 + - _go_select ==2.3.0 cgo + - libcxx >=17 + - libgfortran 5.* + - libgfortran5 >=13.2.0 + constrains: + - gfortran_osx-64 13.* + - clangxx_osx-64 17.* + - clang_osx-64 17.* + license: BSD-3-Clause + license_family: BSD + size: 52672347 + timestamp: 1727276337977 +- kind: conda + name: icu + version: '73.2' + build: hf5e326d_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + sha256: f66362dc36178ac9b7c7a9b012948a9d2d050b3debec24bbd94aadbc44854185 + md5: 5cc301d759ec03f28328428e28f65591 + license: MIT + license_family: MIT + size: 11787527 + timestamp: 1692901622519 +- kind: conda + name: identify + version: 2.6.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.1-pyhd8ed1ab_0.conda + sha256: dc752392f327e64e32bc3122758b2d8951aec9d6e6aa888463c73d18a10e3c56 + md5: 43f629202f9eec21be5f71171fb5daf8 + depends: + - python >=3.6 + - ukkonen + license: MIT + license_family: MIT + size: 78078 + timestamp: 1726369674008 +- kind: conda + name: iniconfig + version: 2.0.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + sha256: 38740c939b668b36a50ef455b077e8015b8c9cf89860d421b3fff86048f49666 + md5: f800d2da156d08e289b14e87e43c1ae5 + depends: + - python >=3.7 + license: MIT + license_family: MIT + size: 11101 + timestamp: 1673103208955 +- kind: conda + name: krb5 + version: 1.21.3 + build: h37d8d59_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda + sha256: 83b52685a4ce542772f0892a0f05764ac69d57187975579a0835ff255ae3ef9c + md5: d4765c524b1d91567886bde656fb514b + depends: + - __osx >=10.13 + - libcxx >=16 + - libedit >=3.1.20191231,<3.2.0a0 + - libedit >=3.1.20191231,<4.0a0 + - openssl >=3.3.1,<4.0a0 + license: MIT + license_family: MIT + size: 1185323 + timestamp: 1719463492984 +- kind: conda + name: libabseil + version: '20240116.2' + build: cxx17_hf036a51_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20240116.2-cxx17_hf036a51_1.conda + sha256: 396d18f39d5207ecae06fddcbc6e5f20865718939bc4e0ea9729e13952833aac + md5: d6c78ca84abed3fea5f308ac83b8f54e + depends: + - __osx >=10.13 + - libcxx >=16 + constrains: + - abseil-cpp =20240116.2 + - libabseil-static =20240116.2=cxx17* + license: Apache-2.0 + license_family: Apache + size: 1124364 + timestamp: 1720857589333 +- kind: conda + name: libarrow + version: 14.0.2 + build: h2902fa7_44_cpu + build_number: 44 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-h2902fa7_44_cpu.conda + sha256: 30bf881c015071d38a843de8785bd28098909637d2e325907ec74acc0dd1c5de + md5: 0ebd27395a10b7895863a4c67ea0579c + depends: + - __osx >=10.13 + - aws-crt-cpp >=0.28.3,<0.28.4.0a0 + - aws-sdk-cpp >=1.11.407,<1.11.408.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.1,<0.8.0a0 + - libabseil * cxx17* + - libabseil >=20240116.2,<20240117.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libcxx >=16 + - libgoogle-cloud >=2.29.0,<2.30.0a0 + - libgoogle-cloud-storage >=2.29.0,<2.30.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.3.1,<2.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - orc >=2.0.2,<2.0.3.0a0 + - re2 + - snappy >=1.2.1,<1.3.0a0 + - zstd >=1.5.6,<1.6.0a0 + constrains: + - apache-arrow-proc =*=cpu + - arrow-cpp <0.0a0 + - parquet-cpp <0.0a0 + license: Apache-2.0 + license_family: APACHE + size: 5583546 + timestamp: 1726708103572 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: hf036a51_44_cpu + build_number: 44 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-14.0.2-hf036a51_44_cpu.conda + sha256: f74634761d17dca0fd8dd19bbd6fff249c74fec1bb090dc6bad2a297862ddac9 + md5: 6b41721142152b215c73a59824330459 + depends: + - __osx >=10.13 + - libarrow 14.0.2 h2902fa7_44_cpu + - libcxx >=16 + license: Apache-2.0 + license_family: APACHE + size: 507916 + timestamp: 1726708213363 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: hf036a51_44_cpu + build_number: 44 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-14.0.2-hf036a51_44_cpu.conda + sha256: 74ccbe5e285f789b68f103c8cbf14e9a68ed6fd5512a2b96c1b87fbea1a9040c + md5: 4e93260003a6d6d5ea51e4ef735431a1 + depends: + - __osx >=10.13 + - libarrow 14.0.2 h2902fa7_44_cpu + - libarrow-acero 14.0.2 hf036a51_44_cpu + - libcxx >=16 + - libparquet 14.0.2 h808e2ea_44_cpu + license: Apache-2.0 + license_family: APACHE + size: 513046 + timestamp: 1726709126956 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: hd834827_44_cpu + build_number: 44 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-14.0.2-hd834827_44_cpu.conda + sha256: e4974e6bc170b99bbafddd60db7bdd09bd478703e3543361ff1239c77e6b36b3 + md5: 557e5288de9850a96c38078d230e8a2e + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.2,<20240117.0a0 + - libarrow 14.0.2 h2902fa7_44_cpu + - libcxx >=16 + - libgrpc >=1.62.2,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 324954 + timestamp: 1726708359132 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: he1e86a1_44_cpu + build_number: 44 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-sql-14.0.2-he1e86a1_44_cpu.conda + sha256: 13625883d7daf474b6fdd2bc2522bc2949518f0af9fdee64c058237f673751e8 + md5: 04c7dd293e7d3034d0b56a48bc6ecbbf + depends: + - __osx >=10.13 + - libarrow 14.0.2 h2902fa7_44_cpu + - libarrow-flight 14.0.2 hd834827_44_cpu + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 157572 + timestamp: 1726709179222 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: hfa04d5a_44_cpu + build_number: 44 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-gandiva-14.0.2-hfa04d5a_44_cpu.conda + sha256: 8fb907d2c43546cd8108edc855c401fcd9d1191f46d3589c793249d72b60576c + md5: 66af76fb864d894c1619f461013d8ce6 + depends: + - __osx >=10.13 + - libarrow 14.0.2 h2902fa7_44_cpu + - libcxx >=16 + - libllvm16 >=16.0.6,<16.1.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - openssl >=3.3.2,<4.0a0 + - re2 + license: Apache-2.0 + license_family: APACHE + size: 696386 + timestamp: 1726708998280 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: he1e86a1_44_cpu + build_number: 44 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-14.0.2-he1e86a1_44_cpu.conda + sha256: 6a21665498a816c340b1b799b80b9f83a6bc5cd348089ea537d3f1f7e22a14e1 + md5: c0995c610ed3d95e0a91e99135d2fc4a + depends: + - __osx >=10.13 + - libarrow 14.0.2 h2902fa7_44_cpu + - libarrow-acero 14.0.2 hf036a51_44_cpu + - libarrow-dataset 14.0.2 hf036a51_44_cpu + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 453586 + timestamp: 1726709259219 +- kind: conda + name: libasprintf + version: 0.22.5 + build: hdfe23c8_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libasprintf-0.22.5-hdfe23c8_3.conda + sha256: 9c6f3e2558e098dbbc63c9884b4af368ea6cc4185ea027563ac4f5ee8571b143 + md5: 55363e1d53635b3497cdf753ab0690c1 + depends: + - __osx >=10.13 + - libcxx >=16 + license: LGPL-2.1-or-later + size: 40442 + timestamp: 1723626787726 +- kind: conda + name: libasprintf-devel + version: 0.22.5 + build: hdfe23c8_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libasprintf-devel-0.22.5-hdfe23c8_3.conda + sha256: 408e59cc215b654b292f503d37552d319e71180d33798867975377c28fd3c6b3 + md5: e2ae0568825e62d439a921fdc7f6db64 + depends: + - __osx >=10.13 + - libasprintf 0.22.5 hdfe23c8_3 + license: LGPL-2.1-or-later + size: 34522 + timestamp: 1723626838677 +- kind: conda + name: libblas + version: 3.9.0 + build: 22_osx64_openblas + build_number: 22 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-22_osx64_openblas.conda + sha256: d72060239f904b3a81d2329efcf84dc62c2dfd66dbc4efc8dcae1afdf8f02b59 + md5: b80966a8c8dd0b531f8e65f709d732e8 + depends: + - libopenblas >=0.3.27,<0.3.28.0a0 + - libopenblas >=0.3.27,<1.0a0 + constrains: + - liblapacke 3.9.0 22_osx64_openblas + - blas * openblas + - libcblas 3.9.0 22_osx64_openblas + - liblapack 3.9.0 22_osx64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14749 + timestamp: 1712542279018 +- kind: conda + name: libbrotlicommon + version: 1.1.0 + build: h00291cd_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.1.0-h00291cd_2.conda + sha256: b377056470a9fb4a100aa3c51b3581aab6496ba84d21cd99bcc1d5ef0359b1b6 + md5: 58f2c4bdd56c46cc7451596e4ae68e0b + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + size: 67267 + timestamp: 1725267768667 +- kind: conda + name: libbrotlidec + version: 1.1.0 + build: h00291cd_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.1.0-h00291cd_2.conda + sha256: 4d49ea72e2f44d2d7a8be5472e4bd0bc2c6b89c55569de2c43576363a0685c0c + md5: 34709a1f5df44e054c4a12ab536c5459 + depends: + - __osx >=10.13 + - libbrotlicommon 1.1.0 h00291cd_2 + license: MIT + license_family: MIT + size: 29872 + timestamp: 1725267807289 +- kind: conda + name: libbrotlienc + version: 1.1.0 + build: h00291cd_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.1.0-h00291cd_2.conda + sha256: 477d236d389473413a1ccd2bec1b66b2f1d2d7d1b4a57bb56421b7b611a56cd1 + md5: 691f0dcb36f1ae67f5c489f20ae987ea + depends: + - __osx >=10.13 + - libbrotlicommon 1.1.0 h00291cd_2 + license: MIT + license_family: MIT + size: 296353 + timestamp: 1725267822076 +- kind: conda + name: libcblas + version: 3.9.0 + build: 22_osx64_openblas + build_number: 22 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-22_osx64_openblas.conda + sha256: 6a2ba9198e2320c3e22fe3d121310cf8a8ac663e94100c5693b34523fcb3cc04 + md5: b9fef82772330f61b2b0201c72d2c29b + depends: + - libblas 3.9.0 22_osx64_openblas + constrains: + - liblapacke 3.9.0 22_osx64_openblas + - blas * openblas + - liblapack 3.9.0 22_osx64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14636 + timestamp: 1712542311437 +- kind: conda + name: libcrc32c + version: 1.1.2 + build: he49afe7_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + sha256: 3043869ac1ee84554f177695e92f2f3c2c507b260edad38a0bf3981fce1632ff + md5: 23d6d5a69918a438355d7cbc4c3d54c9 + depends: + - libcxx >=11.1.0 + license: BSD-3-Clause + license_family: BSD + size: 20128 + timestamp: 1633683906221 +- kind: conda + name: libcurl + version: 8.10.1 + build: h58e7537_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.10.1-h58e7537_0.conda + sha256: 662fe145459ed58dee882e525588d1da4dcc4cbd10cfca0725d1fc3840461798 + md5: 6c8669d8228a2bbd0283911cc6d6726e + depends: + - __osx >=10.13 + - krb5 >=1.21.3,<1.22.0a0 + - libnghttp2 >=1.58.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.3.2,<4.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: curl + license_family: MIT + size: 402588 + timestamp: 1726660264675 +- kind: conda + name: libcxx + version: 19.1.0 + build: hf95d169_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libcxx-19.1.0-hf95d169_0.conda + sha256: 81e6bdf19cf202d769509d116c92046d164c23c91b6f791f439d10f3812629c9 + md5: 0ed117b4cbbf7917dd47b4390e511d2a + depends: + - __osx >=10.13 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 528123 + timestamp: 1726815971547 +- kind: conda + name: libedit + version: 3.1.20191231 + build: h0678c8f_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 + sha256: dbd3c3f2eca1d21c52e4c03b21930bbce414c4592f8ce805801575b9e9256095 + md5: 6016a8a1d0e63cac3de2c352cd40208b + depends: + - ncurses >=6.2,<7.0.0a0 + license: BSD-2-Clause + license_family: BSD + size: 105382 + timestamp: 1597616576726 +- kind: conda + name: libev + version: '4.33' + build: h10d778d_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + sha256: 0d238488564a7992942aa165ff994eca540f687753b4f0998b29b4e4d030ff43 + md5: 899db79329439820b7e8f8de41bca902 + license: BSD-2-Clause + license_family: BSD + size: 106663 + timestamp: 1702146352558 +- kind: conda + name: libevent + version: 2.1.12 + build: ha90c15b_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda + sha256: e0bd9af2a29f8dd74309c0ae4f17a7c2b8c4b89f875ff1d6540c941eefbd07fb + md5: e38e467e577bd193a7d5de7c2c540b04 + depends: + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 372661 + timestamp: 1685726378869 +- kind: conda + name: libexpat + version: 2.6.3 + build: hac325c4_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.3-hac325c4_0.conda + sha256: dd22dffad6731c352f4c14603868c9cce4d3b50ff5ff1e50f416a82dcb491947 + md5: c1db99b0a94a2f23bd6ce39e2d314e07 + depends: + - __osx >=10.13 + constrains: + - expat 2.6.3.* + license: MIT + license_family: MIT + size: 70517 + timestamp: 1725568864316 +- kind: conda + name: libffi + version: 3.4.2 + build: h0d85af4_5 + build_number: 5 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 + sha256: 7a2d27a936ceee6942ea4d397f9c7d136f12549d86f7617e8b6bad51e01a941f + md5: ccb34fb14960ad8b125962d3d79b31a9 + license: MIT + license_family: MIT + size: 51348 + timestamp: 1636488394370 +- kind: conda + name: libgettextpo + version: 0.22.5 + build: hdfe23c8_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgettextpo-0.22.5-hdfe23c8_3.conda + sha256: 8f7631d03a093272a5a8423181ac2c66514503e082e5494a2e942737af8a34ad + md5: ba6eeccaee150e24a544be8ae71aeca1 + depends: + - __osx >=10.13 + - libiconv >=1.17,<2.0a0 + - libintl 0.22.5 hdfe23c8_3 + license: GPL-3.0-or-later + license_family: GPL + size: 172305 + timestamp: 1723626852373 +- kind: conda + name: libgettextpo-devel + version: 0.22.5 + build: hdfe23c8_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgettextpo-devel-0.22.5-hdfe23c8_3.conda + sha256: 8ea6bcba8c002f547edfd51e27e1e81465c8838033877c56439d20bcbc8f32a3 + md5: efbba22e1657ef214c9ce9105b2ca562 + depends: + - __osx >=10.13 + - libgettextpo 0.22.5 hdfe23c8_3 + - libiconv >=1.17,<2.0a0 + - libintl 0.22.5 hdfe23c8_3 + license: GPL-3.0-or-later + license_family: GPL + size: 36977 + timestamp: 1723626874373 +- kind: conda + name: libgfortran + version: 5.0.0 + build: 13_2_0_h97931a8_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-5.0.0-13_2_0_h97931a8_3.conda + sha256: 4874422e567b68334705c135c17e5acdca1404de8255673ce30ad3510e00be0d + md5: 0b6e23a012ee7a9a5f6b244f5a92c1d5 + depends: + - libgfortran5 13.2.0 h2873a65_3 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 110106 + timestamp: 1707328956438 +- kind: conda + name: libgfortran5 + version: 13.2.0 + build: h2873a65_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-13.2.0-h2873a65_3.conda + sha256: da3db4b947e30aec7596a3ef92200d17e774cccbbf7efc47802529a4ca5ca31b + md5: e4fb4d23ec2870ff3c40d10afe305aec + depends: + - llvm-openmp >=8.0.0 + constrains: + - libgfortran 5.0.0 13_2_0_*_3 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 1571379 + timestamp: 1707328880361 +- kind: conda + name: libgoogle-cloud + version: 2.29.0 + build: hecd3d69_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-2.29.0-hecd3d69_0.conda + sha256: fb76eb738bf7a68b2ade5735d10cf8c5b43e558338b7dfa8157b3bbe2152e8d3 + md5: 3bbd93763e4b77411f252378a83ac595 + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.2,<20240117.0a0 + - libcurl >=8.9.1,<9.0a0 + - libcxx >=17 + - libgrpc >=1.62.2,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - openssl >=3.3.2,<4.0a0 + constrains: + - libgoogle-cloud 2.29.0 *_0 + license: Apache-2.0 + license_family: Apache + size: 882673 + timestamp: 1725640300891 +- kind: conda + name: libgoogle-cloud-storage + version: 2.29.0 + build: h8126ed0_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-2.29.0-h8126ed0_0.conda + sha256: de1e2579f7da3b23215ecdd9941f7137fd612208e5b7cc79bb0c907dacd5ab8c + md5: 3f66bd3748be4fee5cfea25fe9fdce62 + depends: + - __osx >=10.13 + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libcxx >=17 + - libgoogle-cloud 2.29.0 hecd3d69_0 + - libzlib >=1.3.1,<2.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + size: 551789 + timestamp: 1725641251227 +- kind: conda + name: libgrpc + version: 1.62.2 + build: h384b2fc_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.62.2-h384b2fc_0.conda + sha256: 7c228040e7dac4e5e7e6935a4decf6bc2155cc05fcfb0811d25ccb242d0036ba + md5: 9421f67cf8b4bc976fe5d0c3ab42de18 + depends: + - __osx >=10.13 + - c-ares >=1.28.1,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + constrains: + - grpc-cpp =1.62.2 + license: Apache-2.0 + license_family: APACHE + size: 5189573 + timestamp: 1713392887258 +- kind: conda + name: libiconv + version: '1.17' + build: hd75f5a5_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + sha256: 23d4923baeca359423a7347c2ed7aaf48c68603df0cf8b87cc94a10b0d4e9a23 + md5: 6c3628d047e151efba7cf08c5e54d1ca + license: LGPL-2.1-only + size: 666538 + timestamp: 1702682713201 +- kind: conda + name: libintl + version: 0.22.5 + build: hdfe23c8_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libintl-0.22.5-hdfe23c8_3.conda + sha256: 0dbb662440a73e20742f12d88e51785a5a5117b8b150783a032b8818a8c043af + md5: 52d4d643ed26c07599736326c46bf12f + depends: + - __osx >=10.13 + - libiconv >=1.17,<2.0a0 + license: LGPL-2.1-or-later + size: 88086 + timestamp: 1723626826235 +- kind: conda + name: libintl-devel + version: 0.22.5 + build: hdfe23c8_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libintl-devel-0.22.5-hdfe23c8_3.conda + sha256: 4913a20244520d6fae14452910613b652752982193a401482b7d699ee70bb13a + md5: aeb045f400ec2b068c6c142b16f87c7e + depends: + - __osx >=10.13 + - libiconv >=1.17,<2.0a0 + - libintl 0.22.5 hdfe23c8_3 + license: LGPL-2.1-or-later + size: 38249 + timestamp: 1723626863306 +- kind: conda + name: liblapack + version: 3.9.0 + build: 22_osx64_openblas + build_number: 22 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-22_osx64_openblas.conda + sha256: e36744f3e780564d6748b5dd05e15ad6a1af9184cf32ab9d1304c13a6bc3e16b + md5: f21b282ff7ba14df6134a0fe6ab42b1b + depends: + - libblas 3.9.0 22_osx64_openblas + constrains: + - liblapacke 3.9.0 22_osx64_openblas + - blas * openblas + - libcblas 3.9.0 22_osx64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14657 + timestamp: 1712542322711 +- kind: conda + name: libllvm16 + version: 16.0.6 + build: hbedff68_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libllvm16-16.0.6-hbedff68_3.conda + sha256: ad848dc0bb02b1dbe54324ee5700b050a2e5f63c095f5229b2de58249a3e268e + md5: 8fd56c0adc07a37f93bd44aa61a97c90 + depends: + - libcxx >=16 + - libxml2 >=2.12.1,<3.0.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 25196932 + timestamp: 1701379796962 +- kind: conda + name: libnghttp2 + version: 1.58.0 + build: h64cf6d3_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda + sha256: 412fd768e787e586602f8e9ea52bf089f3460fc630f6987f0cbd89b70e9a4380 + md5: faecc55c2a8155d9ff1c0ff9a0fef64f + depends: + - __osx >=10.9 + - c-ares >=1.23.0,<2.0a0 + - libcxx >=16.0.6 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.2.0,<4.0a0 + license: MIT + license_family: MIT + size: 599736 + timestamp: 1702130398536 +- kind: conda + name: libopenblas + version: 0.3.27 + build: openmp_h8869122_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.27-openmp_h8869122_1.conda + sha256: 83b0b9d3d09889b3648a81d2c18a2d78c405b03b115107941f0496a8b358ce6d + md5: c0798ad76ddd730dade6ff4dff66e0b5 + depends: + - __osx >=10.13 + - libgfortran 5.* + - libgfortran5 >=12.3.0 + - llvm-openmp >=16.0.6 + constrains: + - openblas >=0.3.27,<0.3.28.0a0 + license: BSD-3-Clause + license_family: BSD + size: 6047513 + timestamp: 1720426759731 +- kind: conda + name: libparquet + version: 14.0.2 + build: h808e2ea_44_cpu + build_number: 44 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libparquet-14.0.2-h808e2ea_44_cpu.conda + sha256: 13cce83283a0a9d6af1618f200fece36a8f61931b420a2c5fc6a75848a62f5a5 + md5: 71f417d137fb71006279d85871c814b8 + depends: + - __osx >=10.13 + - libarrow 14.0.2 h2902fa7_44_cpu + - libcxx >=16 + - libthrift >=0.20.0,<0.20.1.0a0 + - openssl >=3.3.2,<4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 912924 + timestamp: 1726709063239 +- kind: conda + name: libprotobuf + version: 4.25.3 + build: hd4aba4c_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-4.25.3-hd4aba4c_1.conda + sha256: f509cb24a164b84553b28837ec1e8311ceb0212a1dbb8c7fd99ca383d461ea6c + md5: 64ad501f0fd74955056169ec9c42c5c0 + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.2,<20240117.0a0 + - libcxx >=17 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2212274 + timestamp: 1727160957452 +- kind: conda + name: libre2-11 + version: 2023.09.01 + build: h81f5012_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2023.09.01-h81f5012_2.conda + sha256: 384b72a09bd4bb29c1aa085110b2f940dba431587ffb4e2c1a28f605887a1867 + md5: c5c36ec64e3c86504728c38b79011d08 + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcxx >=16 + constrains: + - re2 2023.09.01.* + license: BSD-3-Clause + license_family: BSD + size: 184017 + timestamp: 1708947106275 +- kind: conda + name: libsqlite + version: 3.46.1 + build: h4b8f8c9_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.46.1-h4b8f8c9_0.conda + sha256: 1d075cb823f0cad7e196871b7c57961d669cbbb6cd0e798bf50cbf520dda65fb + md5: 84de0078b58f899fc164303b0603ff0e + depends: + - __osx >=10.13 + - libzlib >=1.3.1,<2.0a0 + license: Unlicense + size: 908317 + timestamp: 1725353652135 +- kind: conda + name: libssh2 + version: 1.11.0 + build: hd019ec5_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda + sha256: f3886763b88f4b24265db6036535ef77b7b77ce91b1cbe588c0fbdd861eec515 + md5: ca3a72efba692c59a90d4b9fc0dfe774 + depends: + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 259556 + timestamp: 1685837820566 +- kind: conda + name: libthrift + version: 0.20.0 + build: h75589b3_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.20.0-h75589b3_1.conda + sha256: a1f40fcb9970fbfd6d0b825841b4127cf7dd7c54199d0b49bdbcd838b66f3b7a + md5: c20b01aa07ece86a237c580f7ba56923 + depends: + - __osx >=10.13 + - libcxx >=17 + - libevent >=2.1.12,<2.1.13.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.3.1,<4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 324391 + timestamp: 1724657549149 +- kind: conda + name: libutf8proc + version: 2.8.0 + build: hb7f2c08_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.8.0-hb7f2c08_0.tar.bz2 + sha256: 55a7f96b2802e94def207fdfe92bc52c24d705d139bb6cdb3d936cbe85e1c505 + md5: db98dc3e58cbc11583180609c429c17d + license: MIT + license_family: MIT + size: 98942 + timestamp: 1667316472080 +- kind: conda + name: libuv + version: 1.48.0 + build: h67532ce_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.48.0-h67532ce_0.conda + sha256: fb87f7bfd464a3a841d23f418c86a206818da0c4346984392071d9342c9ea367 + md5: c8e7344c74f0d86584f7ecdc9f25c198 + license: MIT + license_family: MIT + size: 407040 + timestamp: 1709913680478 +- kind: conda + name: libxml2 + version: 2.12.7 + build: hc603aa4_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.7-hc603aa4_3.conda + sha256: b0cf4a1d3e628876613665ea957a4c0adc30460be859fa859a1eed7eac87330b + md5: c188d96aea8eaa16efec573fe36a9a13 + depends: + - __osx >=10.13 + - icu >=73.2,<74.0a0 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + size: 620129 + timestamp: 1720772795289 +- kind: conda + name: libzlib + version: 1.3.1 + build: h87427d6_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-h87427d6_1.conda + sha256: 80a62db652b1da0ccc100812a1d86e94f75028968991bfb17f9536f3aa72d91d + md5: b7575b5aa92108dcc9aaab0f05f2dbce + depends: + - __osx >=10.13 + constrains: + - zlib 1.3.1 *_1 + license: Zlib + license_family: Other + size: 57372 + timestamp: 1716874211519 +- kind: conda + name: llvm-openmp + version: 18.1.8 + build: h15ab845_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.8-h15ab845_1.conda + sha256: 06a245abb6e6d8d6662a35ad162eacb39f431349edf7cea9b1ff73b2da213c58 + md5: ad0afa524866cc1c08b436865d0ae484 + depends: + - __osx >=10.13 + constrains: + - openmp 18.1.8|18.1.8.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + size: 300358 + timestamp: 1723605369115 +- kind: conda + name: lz4-c + version: 1.9.4 + build: hf0c8a7f_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.9.4-hf0c8a7f_0.conda + sha256: 39aa0c01696e4e202bf5e337413de09dfeec061d89acd5f28e9968b4e93c3f48 + md5: aa04f7143228308662696ac24023f991 + depends: + - libcxx >=14.0.6 + license: BSD-2-Clause + license_family: BSD + size: 156415 + timestamp: 1674727335352 +- kind: conda + name: ncurses + version: '6.5' + build: hf036a51_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-hf036a51_1.conda + sha256: b0b3180039ef19502525a2abd5833c00f9624af830fd391f851934d57bffb9af + md5: e102bbf8a6ceeaf429deab8032fc8977 + depends: + - __osx >=10.13 + license: X11 AND BSD-3-Clause + size: 822066 + timestamp: 1724658603042 +- kind: conda + name: nodeenv + version: 1.9.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_0.conda + sha256: 85ee07342ab055dc081f3de8292c5e7195e43e046db9c5750f242f928f6bb8f2 + md5: dfe0528d0f1c16c1f7c528ea5536ab30 + depends: + - python 2.7|>=3.7 + - setuptools + license: BSD-3-Clause + license_family: BSD + size: 34489 + timestamp: 1717585382642 +- kind: conda + name: nodejs + version: 20.9.0 + build: hfc0f20e_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/nodejs-20.9.0-hfc0f20e_1.conda + sha256: 41619708807c11bce58741f89e087a80a2c01bb4c2536d78d7790b0f0aae1e41 + md5: a72caa23202a8160d773906ceb4f647b + depends: + - icu >=73.2,<74.0a0 + - libcxx >=16 + - libuv >=1.48.0,<1.49.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.2.1,<4.0a0 + - zlib + constrains: + - __osx >=10.15 + license: MIT + license_family: MIT + size: 12147776 + timestamp: 1711534835829 +- kind: conda + name: numpy + version: 1.26.4 + build: py310h4bfa8fc_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py310h4bfa8fc_0.conda + sha256: 914476e2d3273fdf9c0419a7bdcb7b31a5ec25949e4afbc847297ff3a50c62c8 + md5: cd6a2298387f558c9ea70ee73a189791 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=16 + - liblapack >=3.9.0,<4.0a0 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + size: 6491938 + timestamp: 1707226191321 +- kind: conda + name: openssl + version: 3.3.2 + build: hd23fc13_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.2-hd23fc13_0.conda + sha256: 2b75d4b56e45992adf172b158143742daeb316c35274b36f385ccb6644e93268 + md5: 2ff47134c8e292868a4609519b1ea3b6 + depends: + - __osx >=10.13 + - ca-certificates + license: Apache-2.0 + license_family: Apache + size: 2544654 + timestamp: 1725410973572 +- kind: conda + name: orc + version: 2.0.2 + build: h22b2039_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/orc-2.0.2-h22b2039_0.conda + sha256: b5a0667937d9d2d8d50e624e67fdc54c898a33013cd3a6fada343f3c4e69ae6e + md5: f7c6463d97edb79a39df8e5e90c53b1b + depends: + - __osx >=10.13 + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libzlib >=1.3.1,<2.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.2.1,<1.3.0a0 + - tzdata + - zstd >=1.5.6,<1.6.0a0 + license: Apache-2.0 + license_family: Apache + size: 466353 + timestamp: 1723760915178 +- kind: conda + name: packaging + version: '24.1' + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/packaging-24.1-pyhd8ed1ab_0.conda + sha256: 36aca948219e2c9fdd6d80728bcc657519e02f06c2703d8db3446aec67f51d81 + md5: cbe1bb1f21567018ce595d9c2be0f0db + depends: + - python >=3.8 + license: Apache-2.0 + license_family: APACHE + size: 50290 + timestamp: 1718189540074 +- kind: conda + name: pcre2 + version: '10.42' + build: h0ad2156_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/pcre2-10.42-h0ad2156_0.conda + sha256: 689559d94b64914e503d2ced53b78afc19562ed1ccfb284040797a6d41bb564c + md5: 41de8bab2d5e5cd6daaba1896e81d366 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + license: BSD-3-Clause + license_family: BSD + size: 899794 + timestamp: 1698610978148 +- kind: conda + name: perl + version: 5.32.1 + build: 7_h10d778d_perl5 + build_number: 7 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/perl-5.32.1-7_h10d778d_perl5.conda + sha256: 8ebd35e2940055a93135b9fd11bef3662cecef72d6ee651f68d64a2f349863c7 + md5: dc442e0885c3a6b65e61c61558161a9e + license: GPL-1.0-or-later OR Artistic-1.0-Perl + size: 12334471 + timestamp: 1703311001432 +- kind: conda + name: pip + version: '24.2' + build: pyh8b19718_1 + build_number: 1 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pip-24.2-pyh8b19718_1.conda + sha256: d820e5358bcb117fa6286e55d4550c60b0332443df62121df839eab2d11c890b + md5: 6c78fbb8ddfd64bcb55b5cbafd2d2c43 + depends: + - python >=3.8,<3.13.0a0 + - setuptools + - wheel + license: MIT + license_family: MIT + size: 1237976 + timestamp: 1724954490262 +- kind: conda + name: platformdirs + version: 4.3.6 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.3.6-pyhd8ed1ab_0.conda + sha256: c81bdeadc4adcda216b2c7b373f0335f5c78cc480d1d55d10f21823590d7e46f + md5: fd8f2b18b65bbf62e8f653100690c8d2 + depends: + - python >=3.8 + license: MIT + license_family: MIT + size: 20625 + timestamp: 1726613611845 +- kind: conda + name: pluggy + version: 1.5.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.5.0-pyhd8ed1ab_0.conda + sha256: 33eaa3359948a260ebccf9cdc2fd862cea5a6029783289e13602d8e634cd9a26 + md5: d3483c8fc2dc2cc3f5cf43e26d60cabf + depends: + - python >=3.8 + license: MIT + license_family: MIT + size: 23815 + timestamp: 1713667175451 +- kind: conda + name: pre-commit + version: 3.3.3 + build: pyha770c72_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pre-commit-3.3.3-pyha770c72_0.conda + sha256: 3df1434057ce827d88cdd84578732030b3d4b5a0bc6c58bff12b7f8001c1be5b + md5: dd64a0e440754ed97610b3e6b502b6b1 + depends: + - cfgv >=2.0.0 + - identify >=1.0.0 + - nodeenv >=0.11.1 + - python >=3.8 + - pyyaml >=5.1 + - virtualenv >=20.10.0 + license: MIT + license_family: MIT + size: 179852 + timestamp: 1686749032780 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py310hcd1d8fd_44_cpu + build_number: 44 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py310hcd1d8fd_44_cpu.conda + sha256: 72e075dc04023f6e277f58401f7b92cb5449ac8140cbaff368955e316ce044a7 + md5: e71831e4a21b0c82a9d9576c58e53d54 + depends: + - __osx >=10.13 + - libarrow 14.0.2 h2902fa7_44_cpu + - libarrow-acero 14.0.2 hf036a51_44_cpu + - libarrow-dataset 14.0.2 hf036a51_44_cpu + - libarrow-flight 14.0.2 hd834827_44_cpu + - libarrow-flight-sql 14.0.2 he1e86a1_44_cpu + - libarrow-gandiva 14.0.2 hfa04d5a_44_cpu + - libarrow-substrait 14.0.2 he1e86a1_44_cpu + - libcxx >=16 + - libparquet 14.0.2 h808e2ea_44_cpu + - libzlib >=1.3.1,<2.0a0 + - numpy >=1.22.4,<2.0a0 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - tzdata + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 3917797 + timestamp: 1726709605670 +- kind: conda + name: pycparser + version: '2.22' + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda + sha256: 406001ebf017688b1a1554b49127ca3a4ac4626ec0fd51dc75ffa4415b720b64 + md5: 844d9eb3b43095b031874477f7d70088 + depends: + - python >=3.8 + license: BSD-3-Clause + license_family: BSD + size: 105098 + timestamp: 1711811634025 +- kind: conda + name: pytest + version: 8.3.3 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.3-pyhd8ed1ab_0.conda + sha256: e99376d0068455712109d233f5790458ff861aeceb458bfda74e353338e4d815 + md5: c03d61f31f38fdb9facf70c29958bf7a + depends: + - colorama + - exceptiongroup >=1.0.0rc8 + - iniconfig + - packaging + - pluggy <2,>=1.5 + - python >=3.8 + - tomli >=1 + constrains: + - pytest-faulthandler >=2 + license: MIT + license_family: MIT + size: 258293 + timestamp: 1725977334143 +- kind: conda + name: python + version: 3.10.15 + build: h6bafeb6_0_cpython + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.15-h6bafeb6_0_cpython.conda + sha256: 75a20a06c5844336e9e8c438097043ec02559e493feff51e6d11e365d7693a22 + md5: e83a11fdf5d883b29649c5c3075c2109 + depends: + - __osx >=10.13 + - bzip2 >=1.0.8,<2.0a0 + - libffi >=3.4,<4.0a0 + - libsqlite >=3.46.1,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.3.2,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + size: 11943878 + timestamp: 1726850340642 +- kind: conda + name: python_abi + version: '3.10' + build: 5_cp310 + build_number: 5 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.10-5_cp310.conda + sha256: 67eda423ceaf73e50be545464c289ad0c4aecf2df98cc3bbabd5eeded4ca0511 + md5: 5918a11cbc8e1650b2dde23b6ef7452c + constrains: + - python 3.10.* *_cpython + license: BSD-3-Clause + license_family: BSD + size: 6319 + timestamp: 1723823093772 +- kind: conda + name: pyyaml + version: 6.0.2 + build: py310h837254d_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.2-py310h837254d_1.conda + sha256: 9606edcb7578ee32c25688e16ca57eab590d047007d17f5ffbedc06438ba830c + md5: f66b37a401bdbf379080ba9c62854730 + depends: + - __osx >=10.13 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 164184 + timestamp: 1725456348769 +- kind: conda + name: re2 + version: 2023.09.01 + build: hb168e87_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda + sha256: 5739ed2cfa62ed7f828eb4b9e6e69ff1df56cb9a9aacdc296451a3cb647034eb + md5: 266f8ca8528fc7e0fa31066c309ad864 + depends: + - libre2-11 2023.09.01 h81f5012_2 + license: BSD-3-Clause + license_family: BSD + size: 26814 + timestamp: 1708947195067 +- kind: conda + name: readline + version: '8.2' + build: h9e318b2_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + sha256: 41e7d30a097d9b060037f0c6a2b1d4c4ae7e942c06c943d23f9d481548478568 + md5: f17f77f2acf4d344734bda76829ce14e + depends: + - ncurses >=6.3,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 255870 + timestamp: 1679532707590 +- kind: conda + name: setuptools + version: 75.1.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.1.0-pyhd8ed1ab_0.conda + sha256: 6725235722095c547edd24275053c615158d6163f396550840aebd6e209e4738 + md5: d5cd48392c67fb6849ba459c2c2b671f + depends: + - python >=3.8 + license: MIT + license_family: MIT + size: 777462 + timestamp: 1727249510532 +- kind: conda + name: snappy + version: 1.2.1 + build: he1e6707_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.1-he1e6707_0.conda + sha256: a979319cd4916f0e7450aa92bb3cf4c2518afa80be50de99f31d075e693a6dd9 + md5: ddceef5df973c8ff7d6b32353c0cb358 + depends: + - __osx >=10.13 + - libcxx >=16 + license: BSD-3-Clause + license_family: BSD + size: 37036 + timestamp: 1720003862906 +- kind: conda + name: tk + version: 8.6.13 + build: h1abcd95_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + sha256: 30412b2e9de4ff82d8c2a7e5d06a15f4f4fef1809a72138b6ccb53a33b26faf5 + md5: bf830ba5afc507c6232d4ef0fb1a882d + depends: + - libzlib >=1.2.13,<2.0.0a0 + license: TCL + license_family: BSD + size: 3270220 + timestamp: 1699202389792 +- kind: conda + name: tomli + version: 2.0.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + sha256: 4cd48aba7cd026d17e86886af48d0d2ebc67ed36f87f6534f4b67138f5a5a58f + md5: 5844808ffab9ebdb694585b50ba02a96 + depends: + - python >=3.7 + license: MIT + license_family: MIT + size: 15940 + timestamp: 1644342331069 +- kind: conda + name: tzdata + version: 2024a + build: h8827d51_1 + build_number: 1 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h8827d51_1.conda + sha256: 7d21c95f61319dba9209ca17d1935e6128af4235a67ee4e57a00908a1450081e + md5: 8bfdead4e0fff0383ae4c9c50d0531bd + license: LicenseRef-Public-Domain + size: 124164 + timestamp: 1724736371498 +- kind: conda + name: ukkonen + version: 1.0.1 + build: py310hfa8da69_5 + build_number: 5 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.0.1-py310hfa8da69_5.conda + sha256: 326ad0a36c09aa74fed9277ab8b12002512a91252d426b0baad34fe11cc59568 + md5: b33e406764d2ffc9d23a0133f3b5fead + depends: + - __osx >=10.13 + - cffi + - libcxx >=17 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + size: 12925 + timestamp: 1725784218557 +- kind: conda + name: virtualenv + version: 20.26.5 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.26.5-pyhd8ed1ab_0.conda + sha256: 09ee54637f1979c8e9955a363ff9637454cbf63af509cf45a44f184a9ed27a15 + md5: 949a6778521278cb96d7491bd99a5418 + depends: + - distlib <1,>=0.3.7 + - filelock <4,>=3.12.2 + - platformdirs <5,>=3.9.1 + - python >=3.8 + license: MIT + license_family: MIT + size: 4876524 + timestamp: 1726642673644 +- kind: conda + name: wheel + version: 0.44.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/wheel-0.44.0-pyhd8ed1ab_0.conda + sha256: d828764736babb4322b8102094de38074dedfc71f5ff405c9dfee89191c14ebc + md5: d44e3b085abcaef02983c6305b84b584 + depends: + - python >=3.8 + license: MIT + license_family: MIT + size: 58585 + timestamp: 1722797131787 +- kind: conda + name: xz + version: 5.2.6 + build: h775f41a_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + sha256: eb09823f34cc2dd663c0ec4ab13f246f45dcd52e5b8c47b9864361de5204a1c8 + md5: a72f9d4ea13d55d745ff1ed594747f10 + license: LGPL-2.1 and GPL-2.0 + size: 238119 + timestamp: 1660346964847 +- kind: conda + name: yaml + version: 0.2.5 + build: h0d85af4_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 + sha256: 5301417e2c8dea45b401ffee8df3957d2447d4ce80c83c5ff151fc6bfe1c4148 + md5: d7e08fcf8259d742156188e8762b4d20 + license: MIT + license_family: MIT + size: 84237 + timestamp: 1641347062780 +- kind: conda + name: zlib + version: 1.3.1 + build: h87427d6_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.1-h87427d6_1.conda + sha256: 41bd5fef28b2755d637e3a8ea5c84010628392fbcf80c7e3d7370aaced7ee4fe + md5: 3ac9ef8975965f9698dbedd2a4cc5894 + depends: + - __osx >=10.13 + - libzlib 1.3.1 h87427d6_1 + license: Zlib + license_family: Other + size: 88782 + timestamp: 1716874245467 +- kind: conda + name: zstd + version: 1.5.6 + build: h915ae27_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.6-h915ae27_0.conda + sha256: efa04a98cb149643fa54c4dad5a0179e36a5fbc88427ea0eec88ceed87fd0f96 + md5: 4cb2cd56f039b129bb0e491c1164167e + depends: + - __osx >=10.9 + - libzlib >=1.2.13,<2.0.0a0 + license: BSD-3-Clause + license_family: BSD + size: 498900 + timestamp: 1714723303098 diff --git a/pixi.toml b/pixi.toml new file mode 100644 index 0000000..a577f9d --- /dev/null +++ b/pixi.toml @@ -0,0 +1,21 @@ +[project] +name = "iteration" +version = "0.1.0" +description = "Add a short description here" +authors = ["Yuvraj "] +channels = ["conda-forge"] +platforms = ["osx-64"] + +[tasks] + +[dependencies] +# Dev dependencies +pre-commit = "~=3.3.0" + +git = "2.42.0.*" +python = "=3.10" +pip = "*" +go = "=1.21" +pyarrow = "14.0.2" +pytest = ">=7" +nodejs = ">=20.9.0,<20.11" diff --git a/pkg/config/config.go b/pkg/config/config.go new file mode 100644 index 0000000..d2ca66b --- /dev/null +++ b/pkg/config/config.go @@ -0,0 +1,45 @@ +package config + +import "fmt" + +// Config holds the application configuration +type Config struct { + ServerPort string `envconfig:"SERVER_PORT" default:"8080"` + WorkerCount int `envconfig:"WORKER_COUNT" default:"100"` + Database DatabaseConfig +} + +// DatabaseConfig holds the database connection configuration +type DatabaseConfig struct { + Username string `envconfig:"DB_USERNAME"` + Password string `envconfig:"DB_PASSWORD"` + Host string `envconfig:"DB_HOST"` + Port string `envconfig:"DB_PORT"` + Database string `envconfig:"DB_DATABASE"` + SSLMode string `envconfig:"DB_SSL_MODE" default:"require"` + PoolMaxConns int `envconfig:"DB_POOL_MAX_CONNS" default:"1"` +} + +// ToMigrationUri returns a string for the migration package with the correct prefix +func (d DatabaseConfig) ToMigrationUri() string { + return fmt.Sprintf("pgx5://%s:%s@%s:%s/%s?sslmode=%s", + d.Username, + d.Password, + d.Host, + d.Port, + d.Database, + d.SSLMode, + ) +} + +// ToDbConnectionUri returns a connection URI for the pgx package +func (d DatabaseConfig) ToDbConnectionUri() string { + return fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=%s", + d.Username, + d.Password, + d.Host, + d.Port, + d.Database, + d.SSLMode, + ) +} diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go new file mode 100644 index 0000000..0b4b0c3 --- /dev/null +++ b/pkg/config/config_test.go @@ -0,0 +1,43 @@ +package config + +import ( + "testing" +) + +func TestDatabaseConfig_ToMigrationUri(t *testing.T) { + // Test case + dbConfig := DatabaseConfig{ + Username: "testuser", + Password: "testpass", + Host: "testhost", + Port: "5432", + Database: "testdb", + SSLMode: "disable", + } + + expected := "pgx5://testuser:testpass@testhost:5432/testdb?sslmode=disable" + result := dbConfig.ToMigrationUri() + + if result != expected { + t.Errorf("ToMigrationUri() = %v, want %v", result, expected) + } +} + +func TestDatabaseConfig_ToDbConnectionUri(t *testing.T) { + // Test case + dbConfig := DatabaseConfig{ + Username: "testuser", + Password: "testpass", + Host: "testhost", + Port: "5432", + Database: "testdb", + SSLMode: "require", + } + + expected := "postgres://testuser:testpass@testhost:5432/testdb?sslmode=require" + result := dbConfig.ToDbConnectionUri() + + if result != expected { + t.Errorf("ToDbConnectionUri() = %v, want %v", result, expected) + } +} diff --git a/pkg/gen/cloud/v1/cloud.pb.go b/pkg/gen/cloud/v1/cloud.pb.go new file mode 100644 index 0000000..db2d24e --- /dev/null +++ b/pkg/gen/cloud/v1/cloud.pb.go @@ -0,0 +1,1312 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc (unknown) +// source: cloud/v1/cloud.proto + +package cloudv1 + +import ( + _ "github.com/envoyproxy/protoc-gen-validate/validate" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Enum for Task statuses +type TaskStatusEnum int32 + +const ( + TaskStatusEnum_QUEUED TaskStatusEnum = 0 // Task is in the queue, waiting to be processed + TaskStatusEnum_RUNNING TaskStatusEnum = 1 // Task is currently being executed + TaskStatusEnum_FAILED TaskStatusEnum = 2 // Task encountered an error and failed to complete + TaskStatusEnum_SUCCEEDED TaskStatusEnum = 3 // Task completed successfully + TaskStatusEnum_UNKNOWN TaskStatusEnum = 4 // Task status cannot be determined + TaskStatusEnum_ALL TaskStatusEnum = 5 // Task status cannot be determined +) + +// Enum value maps for TaskStatusEnum. +var ( + TaskStatusEnum_name = map[int32]string{ + 0: "QUEUED", + 1: "RUNNING", + 2: "FAILED", + 3: "SUCCEEDED", + 4: "UNKNOWN", + 5: "ALL", + } + TaskStatusEnum_value = map[string]int32{ + "QUEUED": 0, + "RUNNING": 1, + "FAILED": 2, + "SUCCEEDED": 3, + "UNKNOWN": 4, + "ALL": 5, + } +) + +func (x TaskStatusEnum) Enum() *TaskStatusEnum { + p := new(TaskStatusEnum) + *p = x + return p +} + +func (x TaskStatusEnum) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TaskStatusEnum) Descriptor() protoreflect.EnumDescriptor { + return file_cloud_v1_cloud_proto_enumTypes[0].Descriptor() +} + +func (TaskStatusEnum) Type() protoreflect.EnumType { + return &file_cloud_v1_cloud_proto_enumTypes[0] +} + +func (x TaskStatusEnum) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TaskStatusEnum.Descriptor instead. +func (TaskStatusEnum) EnumDescriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{0} +} + +// Message for Task Payload +type Payload struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Dynamic key-value pairs for task parameters. + // Keys must contain only alphanumeric characters, underscores, or dashes. + // Values are limited to 1024 characters to prevent excessive data storage. + Parameters map[string]string `protobuf:"bytes,1,rep,name=parameters,proto3" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *Payload) Reset() { + *x = Payload{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Payload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Payload) ProtoMessage() {} + +func (x *Payload) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Payload.ProtoReflect.Descriptor instead. +func (*Payload) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{0} +} + +func (x *Payload) GetParameters() map[string]string { + if x != nil { + return x.Parameters + } + return nil +} + +// Message for Task creation request +type CreateTaskRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Name of the task. Must contain only alphanumeric characters, underscores, or dashes, + // with a maximum length of 255 characters for readability and database compatibility. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Type of the task. Must be either SEND_EMAIL or RUN_QUERY. + // This field is an enum to ensure only predefined task types are used. + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + // Payload containing task parameters. This field is required to ensure + // all necessary information for task execution is provided. + Payload *Payload `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"` + // Description of the task. Allows for a detailed explanation of the task's purpose. + // Limited to 5000 characters to balance between providing sufficient detail and + // preventing excessively long descriptions. + Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` +} + +func (x *CreateTaskRequest) Reset() { + *x = CreateTaskRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateTaskRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateTaskRequest) ProtoMessage() {} + +func (x *CreateTaskRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateTaskRequest.ProtoReflect.Descriptor instead. +func (*CreateTaskRequest) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{1} +} + +func (x *CreateTaskRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CreateTaskRequest) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *CreateTaskRequest) GetPayload() *Payload { + if x != nil { + return x.Payload + } + return nil +} + +func (x *CreateTaskRequest) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +// Message for Task creation response +type CreateTaskResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Unique identifier for the created task. Must be >= 0. + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *CreateTaskResponse) Reset() { + *x = CreateTaskResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateTaskResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateTaskResponse) ProtoMessage() {} + +func (x *CreateTaskResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateTaskResponse.ProtoReflect.Descriptor instead. +func (*CreateTaskResponse) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateTaskResponse) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +// Message for Task status +type Task struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Unique identifier for the task. Must be >= 0. + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + // Name of the task. Must be alphanumeric, underscores, or dashes, + // with a maximum length of 255 characters. + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // Type of the task, must be either SEND_EMAIL or RUN_QUERY. + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` + // Current status of the task, must be one of the defined statuses. + Status TaskStatusEnum `protobuf:"varint,4,opt,name=status,proto3,enum=cloud.v1.TaskStatusEnum" json:"status,omitempty"` + // Number of retries attempted for this task. Limited to 10 to prevent + // infinite retry loops while allowing for reasonable error recovery. + Retries int32 `protobuf:"varint,5,opt,name=retries,proto3" json:"retries,omitempty"` + // Priority level of the task. Higher values indicate higher priority. + // Must be non-negative to ensure valid prioritization. + Priority int32 `protobuf:"varint,6,opt,name=priority,proto3" json:"priority,omitempty"` + // Timestamp of when the task was created, in ISO 8601 format (UTC). + // This format ensures consistent time representation across different systems. + CreatedAt string `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + // Payload containing task parameters. This field is required. + Payload *Payload `protobuf:"bytes,8,opt,name=payload,proto3" json:"payload,omitempty"` + // Description of the task. A large text string with a maximum length of 5000 characters. + Description string `protobuf:"bytes,9,opt,name=description,proto3" json:"description,omitempty"` +} + +func (x *Task) Reset() { + *x = Task{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Task) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Task) ProtoMessage() {} + +func (x *Task) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Task.ProtoReflect.Descriptor instead. +func (*Task) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{3} +} + +func (x *Task) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Task) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Task) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *Task) GetStatus() TaskStatusEnum { + if x != nil { + return x.Status + } + return TaskStatusEnum_QUEUED +} + +func (x *Task) GetRetries() int32 { + if x != nil { + return x.Retries + } + return 0 +} + +func (x *Task) GetPriority() int32 { + if x != nil { + return x.Priority + } + return 0 +} + +func (x *Task) GetCreatedAt() string { + if x != nil { + return x.CreatedAt + } + return "" +} + +func (x *Task) GetPayload() *Payload { + if x != nil { + return x.Payload + } + return nil +} + +func (x *Task) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +// Message for Task history +type TaskHistory struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Unique identifier for the history entry. Must be >= 0. + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + // Status of the task at the time of this history entry. + Status TaskStatusEnum `protobuf:"varint,2,opt,name=status,proto3,enum=cloud.v1.TaskStatusEnum" json:"status,omitempty"` + // Timestamp of when this history entry was created, in ISO 8601 format. + CreatedAt string `protobuf:"bytes,3,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + // Additional details about the task's execution or status. + // Maximum length of 2000 characters. + Details string `protobuf:"bytes,4,opt,name=details,proto3" json:"details,omitempty"` +} + +func (x *TaskHistory) Reset() { + *x = TaskHistory{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TaskHistory) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TaskHistory) ProtoMessage() {} + +func (x *TaskHistory) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TaskHistory.ProtoReflect.Descriptor instead. +func (*TaskHistory) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{4} +} + +func (x *TaskHistory) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *TaskHistory) GetStatus() TaskStatusEnum { + if x != nil { + return x.Status + } + return TaskStatusEnum_QUEUED +} + +func (x *TaskHistory) GetCreatedAt() string { + if x != nil { + return x.CreatedAt + } + return "" +} + +func (x *TaskHistory) GetDetails() string { + if x != nil { + return x.Details + } + return "" +} + +// Message for Task status request +type GetTaskRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Unique identifier for the task. Must be >= 0. + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *GetTaskRequest) Reset() { + *x = GetTaskRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTaskRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTaskRequest) ProtoMessage() {} + +func (x *GetTaskRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTaskRequest.ProtoReflect.Descriptor instead. +func (*GetTaskRequest) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{5} +} + +func (x *GetTaskRequest) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +// Message for Task history request +type GetTaskHistoryRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Unique identifier for the task. Must be >= 0. + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *GetTaskHistoryRequest) Reset() { + *x = GetTaskHistoryRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTaskHistoryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTaskHistoryRequest) ProtoMessage() {} + +func (x *GetTaskHistoryRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTaskHistoryRequest.ProtoReflect.Descriptor instead. +func (*GetTaskHistoryRequest) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{6} +} + +func (x *GetTaskHistoryRequest) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +// Message for Task history response +type GetTaskHistoryResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of task history entries. Minimum of 1 entry ensures that some history is always returned. + // Maximum of 1000 entries prevents excessive data transfer and processing for very long-running tasks. + History []*TaskHistory `protobuf:"bytes,1,rep,name=history,proto3" json:"history,omitempty"` +} + +func (x *GetTaskHistoryResponse) Reset() { + *x = GetTaskHistoryResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTaskHistoryResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTaskHistoryResponse) ProtoMessage() {} + +func (x *GetTaskHistoryResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTaskHistoryResponse.ProtoReflect.Descriptor instead. +func (*GetTaskHistoryResponse) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{7} +} + +func (x *GetTaskHistoryResponse) GetHistory() []*TaskHistory { + if x != nil { + return x.History + } + return nil +} + +// Message for Task status update request +type UpdateTaskStatusRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Unique identifier for the task. Must be >= 0. + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + // New status for the task, must be one of the defined statuses. + Status TaskStatusEnum `protobuf:"varint,2,opt,name=status,proto3,enum=cloud.v1.TaskStatusEnum" json:"status,omitempty"` + // Additional message about the status update. Maximum length of 2000 characters. + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *UpdateTaskStatusRequest) Reset() { + *x = UpdateTaskStatusRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateTaskStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateTaskStatusRequest) ProtoMessage() {} + +func (x *UpdateTaskStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateTaskStatusRequest.ProtoReflect.Descriptor instead. +func (*UpdateTaskStatusRequest) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{8} +} + +func (x *UpdateTaskStatusRequest) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *UpdateTaskStatusRequest) GetStatus() TaskStatusEnum { + if x != nil { + return x.Status + } + return TaskStatusEnum_QUEUED +} + +func (x *UpdateTaskStatusRequest) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +// Message for GetStatus request (empty) +type GetStatusRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetStatusRequest) Reset() { + *x = GetStatusRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetStatusRequest) ProtoMessage() {} + +func (x *GetStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetStatusRequest.ProtoReflect.Descriptor instead. +func (*GetStatusRequest) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{9} +} + +// Message for GetStatus response +type GetStatusResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Map of task statuses and their counts + StatusCounts map[int32]int64 `protobuf:"bytes,1,rep,name=status_counts,json=statusCounts,proto3" json:"status_counts,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` +} + +func (x *GetStatusResponse) Reset() { + *x = GetStatusResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetStatusResponse) ProtoMessage() {} + +func (x *GetStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetStatusResponse.ProtoReflect.Descriptor instead. +func (*GetStatusResponse) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{10} +} + +func (x *GetStatusResponse) GetStatusCounts() map[int32]int64 { + if x != nil { + return x.StatusCounts + } + return nil +} + +// Message for Task List +type TaskList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tasks []*Task `protobuf:"bytes,1,rep,name=tasks,proto3" json:"tasks,omitempty"` // List of tasks in the system. +} + +func (x *TaskList) Reset() { + *x = TaskList{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TaskList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TaskList) ProtoMessage() {} + +func (x *TaskList) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TaskList.ProtoReflect.Descriptor instead. +func (*TaskList) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{11} +} + +func (x *TaskList) GetTasks() []*Task { + if x != nil { + return x.Tasks + } + return nil +} + +// Message for Task List request +type TaskListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Maximum number of tasks to return in a single request. + // Limited between 1 and 100 to balance between minimizing requests and preventing excessive data transfer. + Limit int32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"` + // Number of tasks to skip before starting to return results. + // Allows for pagination of results. Must be non-negative. + Offset int32 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"` + // Optional filter for tasks by status. If not specified, tasks of all statuses will be returned. + Status *TaskStatusEnum `protobuf:"varint,3,opt,name=status,proto3,enum=cloud.v1.TaskStatusEnum,oneof" json:"status,omitempty"` + // Optional filter for tasks by type. Must be either SEND_EMAIL or RUN_QUERY if specified. + // If not specified, tasks of all types will be returned. + Type *string `protobuf:"bytes,4,opt,name=type,proto3,oneof" json:"type,omitempty"` +} + +func (x *TaskListRequest) Reset() { + *x = TaskListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cloud_v1_cloud_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TaskListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TaskListRequest) ProtoMessage() {} + +func (x *TaskListRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloud_v1_cloud_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TaskListRequest.ProtoReflect.Descriptor instead. +func (*TaskListRequest) Descriptor() ([]byte, []int) { + return file_cloud_v1_cloud_proto_rawDescGZIP(), []int{12} +} + +func (x *TaskListRequest) GetLimit() int32 { + if x != nil { + return x.Limit + } + return 0 +} + +func (x *TaskListRequest) GetOffset() int32 { + if x != nil { + return x.Offset + } + return 0 +} + +func (x *TaskListRequest) GetStatus() TaskStatusEnum { + if x != nil && x.Status != nil { + return *x.Status + } + return TaskStatusEnum_QUEUED +} + +func (x *TaskListRequest) GetType() string { + if x != nil && x.Type != nil { + return *x.Type + } + return "" +} + +var File_cloud_v1_cloud_proto protoreflect.FileDescriptor + +var file_cloud_v1_cloud_proto_rawDesc = []byte{ + 0x0a, 0x14, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, + 0x1a, 0x17, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb0, 0x01, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x12, 0x66, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x23, 0xfa, 0x42, 0x20, 0x9a, 0x01, + 0x1d, 0x22, 0x14, 0x72, 0x12, 0x32, 0x10, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, + 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2b, 0x24, 0x2a, 0x05, 0x72, 0x03, 0x18, 0x80, 0x08, 0x52, 0x0a, + 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc4, 0x01, 0x0a, 0x11, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x2e, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1a, 0xfa, + 0x42, 0x17, 0x72, 0x15, 0x18, 0xff, 0x01, 0x32, 0x10, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, + 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2b, 0x24, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x1c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, + 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x35, 0x0a, + 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x07, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x2a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, + 0x18, 0x88, 0x27, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2d, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x1a, 0x02, 0x28, 0x00, 0x52, 0x02, 0x69, 0x64, 0x22, + 0xa4, 0x03, 0x0a, 0x04, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x1a, 0x02, 0x28, 0x00, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x1a, 0xfa, 0x42, 0x17, 0x72, 0x15, 0x18, 0xff, 0x01, 0x32, 0x10, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, + 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2b, 0x24, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x1c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x3a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, + 0x02, 0x10, 0x01, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x07, 0x72, + 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x42, 0x09, 0xfa, 0x42, + 0x06, 0x1a, 0x04, 0x18, 0x0a, 0x28, 0x00, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, + 0x12, 0x23, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x05, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x1a, 0x02, 0x28, 0x00, 0x52, 0x08, 0x70, 0x72, 0x69, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x4c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2d, 0xfa, 0x42, 0x2a, 0x72, 0x28, + 0x32, 0x26, 0x5e, 0x5c, 0x64, 0x7b, 0x34, 0x7d, 0x2d, 0x5c, 0x64, 0x7b, 0x32, 0x7d, 0x2d, 0x5c, + 0x64, 0x7b, 0x32, 0x7d, 0x54, 0x5c, 0x64, 0x7b, 0x32, 0x7d, 0x3a, 0x5c, 0x64, 0x7b, 0x32, 0x7d, + 0x3a, 0x5c, 0x64, 0x7b, 0x32, 0x7d, 0x5a, 0x24, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x41, 0x74, 0x12, 0x35, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, + 0x01, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x2a, 0x0a, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x18, 0x88, 0x27, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xd4, 0x01, 0x0a, 0x0b, 0x54, 0x61, 0x73, 0x6b, 0x48, + 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x1a, 0x02, 0x28, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x3a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, + 0x02, 0x10, 0x01, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4c, 0x0a, 0x0a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x2d, 0xfa, 0x42, 0x2a, 0x72, 0x28, 0x32, 0x26, 0x5e, 0x5c, 0x64, 0x7b, 0x34, 0x7d, 0x2d, 0x5c, + 0x64, 0x7b, 0x32, 0x7d, 0x2d, 0x5c, 0x64, 0x7b, 0x32, 0x7d, 0x54, 0x5c, 0x64, 0x7b, 0x32, 0x7d, + 0x3a, 0x5c, 0x64, 0x7b, 0x32, 0x7d, 0x3a, 0x5c, 0x64, 0x7b, 0x32, 0x7d, 0x5a, 0x24, 0x52, 0x09, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x22, 0x0a, 0x07, 0x64, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, + 0x03, 0x18, 0xd0, 0x0f, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x29, 0x0a, + 0x0e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x42, 0x07, 0xfa, 0x42, 0x04, + 0x1a, 0x02, 0x28, 0x00, 0x52, 0x02, 0x69, 0x64, 0x22, 0x30, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, + 0x61, 0x73, 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x42, 0x07, 0xfa, + 0x42, 0x04, 0x1a, 0x02, 0x28, 0x00, 0x52, 0x02, 0x69, 0x64, 0x22, 0x56, 0x0a, 0x16, 0x47, 0x65, + 0x74, 0x54, 0x61, 0x73, 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x0b, 0xfa, 0x42, + 0x08, 0x92, 0x01, 0x05, 0x08, 0x01, 0x10, 0xe8, 0x07, 0x52, 0x07, 0x68, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x79, 0x22, 0x92, 0x01, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, + 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x1a, + 0x02, 0x28, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, + 0x6d, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x22, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x18, 0xd0, 0x0f, 0x52, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa8, 0x01, 0x0a, 0x11, + 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x1a, 0x3f, 0x0a, 0x11, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x30, 0x0a, 0x08, 0x54, 0x61, 0x73, 0x6b, 0x4c, 0x69, + 0x73, 0x74, 0x12, 0x24, 0x0a, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, + 0x6b, 0x52, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x22, 0xd5, 0x01, 0x0a, 0x0f, 0x54, 0x61, 0x73, + 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x05, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x42, 0x09, 0xfa, 0x42, 0x06, + 0x1a, 0x04, 0x18, 0x64, 0x28, 0x01, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1f, 0x0a, + 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x42, 0x07, 0xfa, + 0x42, 0x04, 0x1a, 0x02, 0x28, 0x00, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x35, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, + 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x1c, 0xfa, 0x42, 0x19, 0x72, 0x17, 0x52, 0x0a, 0x73, 0x65, 0x6e, 0x64, + 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x52, 0x09, 0x72, 0x75, 0x6e, 0x5f, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x48, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x2a, 0x5a, 0x0a, 0x0e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, + 0x75, 0x6d, 0x12, 0x0a, 0x0a, 0x06, 0x51, 0x55, 0x45, 0x55, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, + 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, + 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, + 0x45, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x04, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x05, 0x32, 0xc7, 0x03, 0x0a, + 0x15, 0x54, 0x61, 0x73, 0x6b, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x54, 0x61, 0x73, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x35, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x18, 0x2e, 0x63, + 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, + 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x12, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, + 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, + 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x48, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, + 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x21, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x46, + 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x7a, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1d, 0x74, 0x61, 0x73, 0x6b, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, + 0x65, 0x6e, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x43, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x5c, 0x56, 0x31, 0xe2, + 0x02, 0x14, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x3a, + 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_cloud_v1_cloud_proto_rawDescOnce sync.Once + file_cloud_v1_cloud_proto_rawDescData = file_cloud_v1_cloud_proto_rawDesc +) + +func file_cloud_v1_cloud_proto_rawDescGZIP() []byte { + file_cloud_v1_cloud_proto_rawDescOnce.Do(func() { + file_cloud_v1_cloud_proto_rawDescData = protoimpl.X.CompressGZIP(file_cloud_v1_cloud_proto_rawDescData) + }) + return file_cloud_v1_cloud_proto_rawDescData +} + +var file_cloud_v1_cloud_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_cloud_v1_cloud_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_cloud_v1_cloud_proto_goTypes = []any{ + (TaskStatusEnum)(0), // 0: cloud.v1.TaskStatusEnum + (*Payload)(nil), // 1: cloud.v1.Payload + (*CreateTaskRequest)(nil), // 2: cloud.v1.CreateTaskRequest + (*CreateTaskResponse)(nil), // 3: cloud.v1.CreateTaskResponse + (*Task)(nil), // 4: cloud.v1.Task + (*TaskHistory)(nil), // 5: cloud.v1.TaskHistory + (*GetTaskRequest)(nil), // 6: cloud.v1.GetTaskRequest + (*GetTaskHistoryRequest)(nil), // 7: cloud.v1.GetTaskHistoryRequest + (*GetTaskHistoryResponse)(nil), // 8: cloud.v1.GetTaskHistoryResponse + (*UpdateTaskStatusRequest)(nil), // 9: cloud.v1.UpdateTaskStatusRequest + (*GetStatusRequest)(nil), // 10: cloud.v1.GetStatusRequest + (*GetStatusResponse)(nil), // 11: cloud.v1.GetStatusResponse + (*TaskList)(nil), // 12: cloud.v1.TaskList + (*TaskListRequest)(nil), // 13: cloud.v1.TaskListRequest + nil, // 14: cloud.v1.Payload.ParametersEntry + nil, // 15: cloud.v1.GetStatusResponse.StatusCountsEntry + (*emptypb.Empty)(nil), // 16: google.protobuf.Empty +} +var file_cloud_v1_cloud_proto_depIdxs = []int32{ + 14, // 0: cloud.v1.Payload.parameters:type_name -> cloud.v1.Payload.ParametersEntry + 1, // 1: cloud.v1.CreateTaskRequest.payload:type_name -> cloud.v1.Payload + 0, // 2: cloud.v1.Task.status:type_name -> cloud.v1.TaskStatusEnum + 1, // 3: cloud.v1.Task.payload:type_name -> cloud.v1.Payload + 0, // 4: cloud.v1.TaskHistory.status:type_name -> cloud.v1.TaskStatusEnum + 5, // 5: cloud.v1.GetTaskHistoryResponse.history:type_name -> cloud.v1.TaskHistory + 0, // 6: cloud.v1.UpdateTaskStatusRequest.status:type_name -> cloud.v1.TaskStatusEnum + 15, // 7: cloud.v1.GetStatusResponse.status_counts:type_name -> cloud.v1.GetStatusResponse.StatusCountsEntry + 4, // 8: cloud.v1.TaskList.tasks:type_name -> cloud.v1.Task + 0, // 9: cloud.v1.TaskListRequest.status:type_name -> cloud.v1.TaskStatusEnum + 2, // 10: cloud.v1.TaskManagementService.CreateTask:input_type -> cloud.v1.CreateTaskRequest + 6, // 11: cloud.v1.TaskManagementService.GetTask:input_type -> cloud.v1.GetTaskRequest + 13, // 12: cloud.v1.TaskManagementService.ListTasks:input_type -> cloud.v1.TaskListRequest + 7, // 13: cloud.v1.TaskManagementService.GetTaskHistory:input_type -> cloud.v1.GetTaskHistoryRequest + 9, // 14: cloud.v1.TaskManagementService.UpdateTaskStatus:input_type -> cloud.v1.UpdateTaskStatusRequest + 10, // 15: cloud.v1.TaskManagementService.GetStatus:input_type -> cloud.v1.GetStatusRequest + 3, // 16: cloud.v1.TaskManagementService.CreateTask:output_type -> cloud.v1.CreateTaskResponse + 4, // 17: cloud.v1.TaskManagementService.GetTask:output_type -> cloud.v1.Task + 12, // 18: cloud.v1.TaskManagementService.ListTasks:output_type -> cloud.v1.TaskList + 8, // 19: cloud.v1.TaskManagementService.GetTaskHistory:output_type -> cloud.v1.GetTaskHistoryResponse + 16, // 20: cloud.v1.TaskManagementService.UpdateTaskStatus:output_type -> google.protobuf.Empty + 11, // 21: cloud.v1.TaskManagementService.GetStatus:output_type -> cloud.v1.GetStatusResponse + 16, // [16:22] is the sub-list for method output_type + 10, // [10:16] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name +} + +func init() { file_cloud_v1_cloud_proto_init() } +func file_cloud_v1_cloud_proto_init() { + if File_cloud_v1_cloud_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_cloud_v1_cloud_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*Payload); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*CreateTaskRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*CreateTaskResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*Task); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*TaskHistory); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[5].Exporter = func(v any, i int) any { + switch v := v.(*GetTaskRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[6].Exporter = func(v any, i int) any { + switch v := v.(*GetTaskHistoryRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[7].Exporter = func(v any, i int) any { + switch v := v.(*GetTaskHistoryResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[8].Exporter = func(v any, i int) any { + switch v := v.(*UpdateTaskStatusRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[9].Exporter = func(v any, i int) any { + switch v := v.(*GetStatusRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[10].Exporter = func(v any, i int) any { + switch v := v.(*GetStatusResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[11].Exporter = func(v any, i int) any { + switch v := v.(*TaskList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cloud_v1_cloud_proto_msgTypes[12].Exporter = func(v any, i int) any { + switch v := v.(*TaskListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_cloud_v1_cloud_proto_msgTypes[12].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_cloud_v1_cloud_proto_rawDesc, + NumEnums: 1, + NumMessages: 15, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_cloud_v1_cloud_proto_goTypes, + DependencyIndexes: file_cloud_v1_cloud_proto_depIdxs, + EnumInfos: file_cloud_v1_cloud_proto_enumTypes, + MessageInfos: file_cloud_v1_cloud_proto_msgTypes, + }.Build() + File_cloud_v1_cloud_proto = out.File + file_cloud_v1_cloud_proto_rawDesc = nil + file_cloud_v1_cloud_proto_goTypes = nil + file_cloud_v1_cloud_proto_depIdxs = nil +} diff --git a/pkg/gen/cloud/v1/cloud.swagger.json b/pkg/gen/cloud/v1/cloud.swagger.json new file mode 100644 index 0000000..6654d08 --- /dev/null +++ b/pkg/gen/cloud/v1/cloud.swagger.json @@ -0,0 +1,197 @@ +{ + "swagger": "2.0", + "info": { + "title": "cloud/v1/cloud.proto", + "version": "version not set" + }, + "tags": [ + { + "name": "TaskManagementService" + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + }, + "v1CreateTaskResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32", + "description": "Unique identifier for the created task. Must be \u003e= 0." + } + }, + "title": "Message for Task creation response" + }, + "v1GetStatusResponse": { + "type": "object", + "properties": { + "statusCounts": { + "type": "object", + "additionalProperties": { + "type": "string", + "format": "int64" + }, + "title": "Map of task statuses and their counts" + } + }, + "title": "Message for GetStatus response" + }, + "v1GetTaskHistoryResponse": { + "type": "object", + "properties": { + "history": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1TaskHistory" + }, + "description": "List of task history entries. Minimum of 1 entry ensures that some history is always returned.\nMaximum of 1000 entries prevents excessive data transfer and processing for very long-running tasks." + } + }, + "title": "Message for Task history response" + }, + "v1Payload": { + "type": "object", + "properties": { + "parameters": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Dynamic key-value pairs for task parameters. \nKeys must contain only alphanumeric characters, underscores, or dashes. \nValues are limited to 1024 characters to prevent excessive data storage." + } + }, + "title": "Message for Task Payload" + }, + "v1Task": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32", + "description": "Unique identifier for the task. Must be \u003e= 0." + }, + "name": { + "type": "string", + "description": "Name of the task. Must be alphanumeric, underscores, or dashes, \nwith a maximum length of 255 characters." + }, + "type": { + "type": "string", + "description": "Type of the task, must be either SEND_EMAIL or RUN_QUERY." + }, + "status": { + "$ref": "#/definitions/v1TaskStatusEnum", + "description": "Current status of the task, must be one of the defined statuses." + }, + "retries": { + "type": "integer", + "format": "int32", + "description": "Number of retries attempted for this task. Limited to 10 to prevent\ninfinite retry loops while allowing for reasonable error recovery." + }, + "priority": { + "type": "integer", + "format": "int32", + "description": "Priority level of the task. Higher values indicate higher priority.\nMust be non-negative to ensure valid prioritization." + }, + "createdAt": { + "type": "string", + "description": "Timestamp of when the task was created, in ISO 8601 format (UTC).\nThis format ensures consistent time representation across different systems." + }, + "payload": { + "$ref": "#/definitions/v1Payload", + "description": "Payload containing task parameters. This field is required." + }, + "description": { + "type": "string", + "description": "Description of the task. A large text string with a maximum length of 5000 characters." + } + }, + "title": "Message for Task status" + }, + "v1TaskHistory": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32", + "description": "Unique identifier for the history entry. Must be \u003e= 0." + }, + "status": { + "$ref": "#/definitions/v1TaskStatusEnum", + "description": "Status of the task at the time of this history entry." + }, + "createdAt": { + "type": "string", + "description": "Timestamp of when this history entry was created, in ISO 8601 format." + }, + "details": { + "type": "string", + "description": "Additional details about the task's execution or status. \nMaximum length of 2000 characters." + } + }, + "title": "Message for Task history" + }, + "v1TaskList": { + "type": "object", + "properties": { + "tasks": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Task" + }, + "description": "List of tasks in the system." + } + }, + "title": "Message for Task List" + }, + "v1TaskStatusEnum": { + "type": "string", + "enum": [ + "QUEUED", + "RUNNING", + "FAILED", + "SUCCEEDED", + "UNKNOWN", + "ALL" + ], + "default": "QUEUED", + "description": "- QUEUED: Task is in the queue, waiting to be processed\n - RUNNING: Task is currently being executed\n - FAILED: Task encountered an error and failed to complete\n - SUCCEEDED: Task completed successfully\n - UNKNOWN: Task status cannot be determined\n - ALL: Task status cannot be determined", + "title": "Enum for Task statuses" + } + } +} diff --git a/pkg/gen/cloud/v1/cloudv1connect/cloud.connect.go b/pkg/gen/cloud/v1/cloudv1connect/cloud.connect.go new file mode 100644 index 0000000..4466f59 --- /dev/null +++ b/pkg/gen/cloud/v1/cloudv1connect/cloud.connect.go @@ -0,0 +1,265 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: cloud/v1/cloud.proto + +package cloudv1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + emptypb "google.golang.org/protobuf/types/known/emptypb" + http "net/http" + strings "strings" + v1 "task/pkg/gen/cloud/v1" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion0_1_0 + +const ( + // TaskManagementServiceName is the fully-qualified name of the TaskManagementService service. + TaskManagementServiceName = "cloud.v1.TaskManagementService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // TaskManagementServiceCreateTaskProcedure is the fully-qualified name of the + // TaskManagementService's CreateTask RPC. + TaskManagementServiceCreateTaskProcedure = "/cloud.v1.TaskManagementService/CreateTask" + // TaskManagementServiceGetTaskProcedure is the fully-qualified name of the TaskManagementService's + // GetTask RPC. + TaskManagementServiceGetTaskProcedure = "/cloud.v1.TaskManagementService/GetTask" + // TaskManagementServiceListTasksProcedure is the fully-qualified name of the + // TaskManagementService's ListTasks RPC. + TaskManagementServiceListTasksProcedure = "/cloud.v1.TaskManagementService/ListTasks" + // TaskManagementServiceGetTaskHistoryProcedure is the fully-qualified name of the + // TaskManagementService's GetTaskHistory RPC. + TaskManagementServiceGetTaskHistoryProcedure = "/cloud.v1.TaskManagementService/GetTaskHistory" + // TaskManagementServiceUpdateTaskStatusProcedure is the fully-qualified name of the + // TaskManagementService's UpdateTaskStatus RPC. + TaskManagementServiceUpdateTaskStatusProcedure = "/cloud.v1.TaskManagementService/UpdateTaskStatus" + // TaskManagementServiceGetStatusProcedure is the fully-qualified name of the + // TaskManagementService's GetStatus RPC. + TaskManagementServiceGetStatusProcedure = "/cloud.v1.TaskManagementService/GetStatus" +) + +// TaskManagementServiceClient is a client for the cloud.v1.TaskManagementService service. +type TaskManagementServiceClient interface { + // Creates a new task based on the provided request. + // Returns a CreateTaskResponse containing the unique identifier of the created task. + CreateTask(context.Context, *connect.Request[v1.CreateTaskRequest]) (*connect.Response[v1.CreateTaskResponse], error) + // Retrieves the current status and details of the specified task. + // Returns a Task message containing all information about the requested task. + GetTask(context.Context, *connect.Request[v1.GetTaskRequest]) (*connect.Response[v1.Task], error) + // Lists tasks currently available in the system, with pagination support. + // Returns a TaskList containing the requested subset of tasks. + ListTasks(context.Context, *connect.Request[v1.TaskListRequest]) (*connect.Response[v1.TaskList], error) + // Retrieves the execution history of the specified task. + // Returns a GetTaskHistoryResponse containing a list of historical status updates. + GetTaskHistory(context.Context, *connect.Request[v1.GetTaskHistoryRequest]) (*connect.Response[v1.GetTaskHistoryResponse], error) + // Updates the status of the specified task. + // Returns an empty response to confirm the update was processed. + UpdateTaskStatus(context.Context, *connect.Request[v1.UpdateTaskStatusRequest]) (*connect.Response[emptypb.Empty], error) + // Retrieves the count of tasks for each status. + // Returns a GetStatusResponse containing a map of status counts. + GetStatus(context.Context, *connect.Request[v1.GetStatusRequest]) (*connect.Response[v1.GetStatusResponse], error) +} + +// NewTaskManagementServiceClient constructs a client for the cloud.v1.TaskManagementService +// service. By default, it uses the Connect protocol with the binary Protobuf Codec, asks for +// gzipped responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply +// the connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewTaskManagementServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) TaskManagementServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &taskManagementServiceClient{ + createTask: connect.NewClient[v1.CreateTaskRequest, v1.CreateTaskResponse]( + httpClient, + baseURL+TaskManagementServiceCreateTaskProcedure, + opts..., + ), + getTask: connect.NewClient[v1.GetTaskRequest, v1.Task]( + httpClient, + baseURL+TaskManagementServiceGetTaskProcedure, + opts..., + ), + listTasks: connect.NewClient[v1.TaskListRequest, v1.TaskList]( + httpClient, + baseURL+TaskManagementServiceListTasksProcedure, + opts..., + ), + getTaskHistory: connect.NewClient[v1.GetTaskHistoryRequest, v1.GetTaskHistoryResponse]( + httpClient, + baseURL+TaskManagementServiceGetTaskHistoryProcedure, + opts..., + ), + updateTaskStatus: connect.NewClient[v1.UpdateTaskStatusRequest, emptypb.Empty]( + httpClient, + baseURL+TaskManagementServiceUpdateTaskStatusProcedure, + opts..., + ), + getStatus: connect.NewClient[v1.GetStatusRequest, v1.GetStatusResponse]( + httpClient, + baseURL+TaskManagementServiceGetStatusProcedure, + opts..., + ), + } +} + +// taskManagementServiceClient implements TaskManagementServiceClient. +type taskManagementServiceClient struct { + createTask *connect.Client[v1.CreateTaskRequest, v1.CreateTaskResponse] + getTask *connect.Client[v1.GetTaskRequest, v1.Task] + listTasks *connect.Client[v1.TaskListRequest, v1.TaskList] + getTaskHistory *connect.Client[v1.GetTaskHistoryRequest, v1.GetTaskHistoryResponse] + updateTaskStatus *connect.Client[v1.UpdateTaskStatusRequest, emptypb.Empty] + getStatus *connect.Client[v1.GetStatusRequest, v1.GetStatusResponse] +} + +// CreateTask calls cloud.v1.TaskManagementService.CreateTask. +func (c *taskManagementServiceClient) CreateTask(ctx context.Context, req *connect.Request[v1.CreateTaskRequest]) (*connect.Response[v1.CreateTaskResponse], error) { + return c.createTask.CallUnary(ctx, req) +} + +// GetTask calls cloud.v1.TaskManagementService.GetTask. +func (c *taskManagementServiceClient) GetTask(ctx context.Context, req *connect.Request[v1.GetTaskRequest]) (*connect.Response[v1.Task], error) { + return c.getTask.CallUnary(ctx, req) +} + +// ListTasks calls cloud.v1.TaskManagementService.ListTasks. +func (c *taskManagementServiceClient) ListTasks(ctx context.Context, req *connect.Request[v1.TaskListRequest]) (*connect.Response[v1.TaskList], error) { + return c.listTasks.CallUnary(ctx, req) +} + +// GetTaskHistory calls cloud.v1.TaskManagementService.GetTaskHistory. +func (c *taskManagementServiceClient) GetTaskHistory(ctx context.Context, req *connect.Request[v1.GetTaskHistoryRequest]) (*connect.Response[v1.GetTaskHistoryResponse], error) { + return c.getTaskHistory.CallUnary(ctx, req) +} + +// UpdateTaskStatus calls cloud.v1.TaskManagementService.UpdateTaskStatus. +func (c *taskManagementServiceClient) UpdateTaskStatus(ctx context.Context, req *connect.Request[v1.UpdateTaskStatusRequest]) (*connect.Response[emptypb.Empty], error) { + return c.updateTaskStatus.CallUnary(ctx, req) +} + +// GetStatus calls cloud.v1.TaskManagementService.GetStatus. +func (c *taskManagementServiceClient) GetStatus(ctx context.Context, req *connect.Request[v1.GetStatusRequest]) (*connect.Response[v1.GetStatusResponse], error) { + return c.getStatus.CallUnary(ctx, req) +} + +// TaskManagementServiceHandler is an implementation of the cloud.v1.TaskManagementService service. +type TaskManagementServiceHandler interface { + // Creates a new task based on the provided request. + // Returns a CreateTaskResponse containing the unique identifier of the created task. + CreateTask(context.Context, *connect.Request[v1.CreateTaskRequest]) (*connect.Response[v1.CreateTaskResponse], error) + // Retrieves the current status and details of the specified task. + // Returns a Task message containing all information about the requested task. + GetTask(context.Context, *connect.Request[v1.GetTaskRequest]) (*connect.Response[v1.Task], error) + // Lists tasks currently available in the system, with pagination support. + // Returns a TaskList containing the requested subset of tasks. + ListTasks(context.Context, *connect.Request[v1.TaskListRequest]) (*connect.Response[v1.TaskList], error) + // Retrieves the execution history of the specified task. + // Returns a GetTaskHistoryResponse containing a list of historical status updates. + GetTaskHistory(context.Context, *connect.Request[v1.GetTaskHistoryRequest]) (*connect.Response[v1.GetTaskHistoryResponse], error) + // Updates the status of the specified task. + // Returns an empty response to confirm the update was processed. + UpdateTaskStatus(context.Context, *connect.Request[v1.UpdateTaskStatusRequest]) (*connect.Response[emptypb.Empty], error) + // Retrieves the count of tasks for each status. + // Returns a GetStatusResponse containing a map of status counts. + GetStatus(context.Context, *connect.Request[v1.GetStatusRequest]) (*connect.Response[v1.GetStatusResponse], error) +} + +// NewTaskManagementServiceHandler builds an HTTP handler from the service implementation. It +// returns the path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewTaskManagementServiceHandler(svc TaskManagementServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + taskManagementServiceCreateTaskHandler := connect.NewUnaryHandler( + TaskManagementServiceCreateTaskProcedure, + svc.CreateTask, + opts..., + ) + taskManagementServiceGetTaskHandler := connect.NewUnaryHandler( + TaskManagementServiceGetTaskProcedure, + svc.GetTask, + opts..., + ) + taskManagementServiceListTasksHandler := connect.NewUnaryHandler( + TaskManagementServiceListTasksProcedure, + svc.ListTasks, + opts..., + ) + taskManagementServiceGetTaskHistoryHandler := connect.NewUnaryHandler( + TaskManagementServiceGetTaskHistoryProcedure, + svc.GetTaskHistory, + opts..., + ) + taskManagementServiceUpdateTaskStatusHandler := connect.NewUnaryHandler( + TaskManagementServiceUpdateTaskStatusProcedure, + svc.UpdateTaskStatus, + opts..., + ) + taskManagementServiceGetStatusHandler := connect.NewUnaryHandler( + TaskManagementServiceGetStatusProcedure, + svc.GetStatus, + opts..., + ) + return "/cloud.v1.TaskManagementService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case TaskManagementServiceCreateTaskProcedure: + taskManagementServiceCreateTaskHandler.ServeHTTP(w, r) + case TaskManagementServiceGetTaskProcedure: + taskManagementServiceGetTaskHandler.ServeHTTP(w, r) + case TaskManagementServiceListTasksProcedure: + taskManagementServiceListTasksHandler.ServeHTTP(w, r) + case TaskManagementServiceGetTaskHistoryProcedure: + taskManagementServiceGetTaskHistoryHandler.ServeHTTP(w, r) + case TaskManagementServiceUpdateTaskStatusProcedure: + taskManagementServiceUpdateTaskStatusHandler.ServeHTTP(w, r) + case TaskManagementServiceGetStatusProcedure: + taskManagementServiceGetStatusHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedTaskManagementServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedTaskManagementServiceHandler struct{} + +func (UnimplementedTaskManagementServiceHandler) CreateTask(context.Context, *connect.Request[v1.CreateTaskRequest]) (*connect.Response[v1.CreateTaskResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("cloud.v1.TaskManagementService.CreateTask is not implemented")) +} + +func (UnimplementedTaskManagementServiceHandler) GetTask(context.Context, *connect.Request[v1.GetTaskRequest]) (*connect.Response[v1.Task], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("cloud.v1.TaskManagementService.GetTask is not implemented")) +} + +func (UnimplementedTaskManagementServiceHandler) ListTasks(context.Context, *connect.Request[v1.TaskListRequest]) (*connect.Response[v1.TaskList], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("cloud.v1.TaskManagementService.ListTasks is not implemented")) +} + +func (UnimplementedTaskManagementServiceHandler) GetTaskHistory(context.Context, *connect.Request[v1.GetTaskHistoryRequest]) (*connect.Response[v1.GetTaskHistoryResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("cloud.v1.TaskManagementService.GetTaskHistory is not implemented")) +} + +func (UnimplementedTaskManagementServiceHandler) UpdateTaskStatus(context.Context, *connect.Request[v1.UpdateTaskStatusRequest]) (*connect.Response[emptypb.Empty], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("cloud.v1.TaskManagementService.UpdateTaskStatus is not implemented")) +} + +func (UnimplementedTaskManagementServiceHandler) GetStatus(context.Context, *connect.Request[v1.GetStatusRequest]) (*connect.Response[v1.GetStatusResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("cloud.v1.TaskManagementService.GetStatus is not implemented")) +} diff --git a/pkg/gen/index.html b/pkg/gen/index.html new file mode 100644 index 0000000..4160ae0 --- /dev/null +++ b/pkg/gen/index.html @@ -0,0 +1,3718 @@ + + + + + Protocol Documentation + + + + + + + + + + +

Protocol Documentation

+ +

Table of Contents

+ + + + + +
+

validate/validate.proto

Top +
+

+ + +

AnyRules

+

AnyRules describe constraints applied exclusively to the

`google.protobuf.Any` well-known type

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
requiredbooloptional

Required specifies that this field must be set

instringrepeated

In specifies that this field's `type_url` must be equal to one of the +specified values.

not_instringrepeated

NotIn specifies that this field's `type_url` must not be equal to any of +the specified values.

+ + + + + +

BoolRules

+

BoolRules describes the constraints applied to `bool` values

+ + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constbooloptional

Const specifies that this field must be exactly the specified value

+ + + + + +

BytesRules

+

BytesRules describe the constraints applied to `bytes` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constbytesoptional

Const specifies that this field must be exactly the specified value

lenuint64optional

Len specifies that this field must be the specified number of bytes

min_lenuint64optional

MinLen specifies that this field must be the specified number of bytes +at a minimum

max_lenuint64optional

MaxLen specifies that this field must be the specified number of bytes +at a maximum

patternstringoptional

Pattern specifies that this field must match against the specified +regular expression (RE2 syntax). The included expression should elide +any delimiters.

prefixbytesoptional

Prefix specifies that this field must have the specified bytes at the +beginning of the string.

suffixbytesoptional

Suffix specifies that this field must have the specified bytes at the +end of the string.

containsbytesoptional

Contains specifies that this field must have the specified bytes +anywhere in the string.

inbytesrepeated

In specifies that this field must be equal to one of the specified +values

not_inbytesrepeated

NotIn specifies that this field cannot be equal to one of the specified +values

ipbooloptional

Ip specifies that the field must be a valid IP (v4 or v6) address in +byte format

ipv4booloptional

Ipv4 specifies that the field must be a valid IPv4 address in byte +format

ipv6booloptional

Ipv6 specifies that the field must be a valid IPv6 address in byte +format

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

DoubleRules

+

DoubleRules describes the constraints applied to `double` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constdoubleoptional

Const specifies that this field must be exactly the specified value

ltdoubleoptional

Lt specifies that this field must be less than the specified value, +exclusive

ltedoubleoptional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtdoubleoptional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gtedoubleoptional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

indoublerepeated

In specifies that this field must be equal to one of the specified +values

not_indoublerepeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

DurationRules

+

DurationRules describe the constraints applied exclusively to the

`google.protobuf.Duration` well-known type

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
requiredbooloptional

Required specifies that this field must be set

constgoogle.protobuf.Durationoptional

Const specifies that this field must be exactly the specified value

ltgoogle.protobuf.Durationoptional

Lt specifies that this field must be less than the specified value, +exclusive

ltegoogle.protobuf.Durationoptional

Lt specifies that this field must be less than the specified value, +inclusive

gtgoogle.protobuf.Durationoptional

Gt specifies that this field must be greater than the specified value, +exclusive

gtegoogle.protobuf.Durationoptional

Gte specifies that this field must be greater than the specified value, +inclusive

ingoogle.protobuf.Durationrepeated

In specifies that this field must be equal to one of the specified +values

not_ingoogle.protobuf.Durationrepeated

NotIn specifies that this field cannot be equal to one of the specified +values

+ + + + + +

EnumRules

+

EnumRules describe the constraints applied to enum values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constint32optional

Const specifies that this field must be exactly the specified value

defined_onlybooloptional

DefinedOnly specifies that this field must be only one of the defined +values for this enum, failing on any undefined value.

inint32repeated

In specifies that this field must be equal to one of the specified +values

not_inint32repeated

NotIn specifies that this field cannot be equal to one of the specified +values

+ + + + + +

FieldRules

+

FieldRules encapsulates the rules for each type of field. Depending on the

field, the correct set should be used to ensure proper validations.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
messageMessageRulesoptional

floatFloatRulesoptional

Scalar Field Types

doubleDoubleRulesoptional

int32Int32Rulesoptional

int64Int64Rulesoptional

uint32UInt32Rulesoptional

uint64UInt64Rulesoptional

sint32SInt32Rulesoptional

sint64SInt64Rulesoptional

fixed32Fixed32Rulesoptional

fixed64Fixed64Rulesoptional

sfixed32SFixed32Rulesoptional

sfixed64SFixed64Rulesoptional

boolBoolRulesoptional

stringStringRulesoptional

bytesBytesRulesoptional

enumEnumRulesoptional

Complex Field Types

repeatedRepeatedRulesoptional

mapMapRulesoptional

anyAnyRulesoptional

Well-Known Field Types

durationDurationRulesoptional

timestampTimestampRulesoptional

+ + + + + +

Fixed32Rules

+

Fixed32Rules describes the constraints applied to `fixed32` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constfixed32optional

Const specifies that this field must be exactly the specified value

ltfixed32optional

Lt specifies that this field must be less than the specified value, +exclusive

ltefixed32optional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtfixed32optional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gtefixed32optional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

infixed32repeated

In specifies that this field must be equal to one of the specified +values

not_infixed32repeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

Fixed64Rules

+

Fixed64Rules describes the constraints applied to `fixed64` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constfixed64optional

Const specifies that this field must be exactly the specified value

ltfixed64optional

Lt specifies that this field must be less than the specified value, +exclusive

ltefixed64optional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtfixed64optional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gtefixed64optional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

infixed64repeated

In specifies that this field must be equal to one of the specified +values

not_infixed64repeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

FloatRules

+

FloatRules describes the constraints applied to `float` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constfloatoptional

Const specifies that this field must be exactly the specified value

ltfloatoptional

Lt specifies that this field must be less than the specified value, +exclusive

ltefloatoptional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtfloatoptional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gtefloatoptional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

infloatrepeated

In specifies that this field must be equal to one of the specified +values

not_infloatrepeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

Int32Rules

+

Int32Rules describes the constraints applied to `int32` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constint32optional

Const specifies that this field must be exactly the specified value

ltint32optional

Lt specifies that this field must be less than the specified value, +exclusive

lteint32optional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtint32optional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gteint32optional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

inint32repeated

In specifies that this field must be equal to one of the specified +values

not_inint32repeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

Int64Rules

+

Int64Rules describes the constraints applied to `int64` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constint64optional

Const specifies that this field must be exactly the specified value

ltint64optional

Lt specifies that this field must be less than the specified value, +exclusive

lteint64optional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtint64optional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gteint64optional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

inint64repeated

In specifies that this field must be equal to one of the specified +values

not_inint64repeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

MapRules

+

MapRules describe the constraints applied to `map` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
min_pairsuint64optional

MinPairs specifies that this field must have the specified number of +KVs at a minimum

max_pairsuint64optional

MaxPairs specifies that this field must have the specified number of +KVs at a maximum

no_sparsebooloptional

NoSparse specifies values in this field cannot be unset. This only +applies to map's with message value types.

keysFieldRulesoptional

Keys specifies the constraints to be applied to each key in the field.

valuesFieldRulesoptional

Values specifies the constraints to be applied to the value of each key +in the field. Message values will still have their validations evaluated +unless skip is specified here.

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

MessageRules

+

MessageRules describe the constraints applied to embedded message values.

For message-type fields, validation is performed recursively.

+ + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
skipbooloptional

Skip specifies that the validation rules of this field should not be +evaluated

requiredbooloptional

Required specifies that this field must be set

+ + + + + +

RepeatedRules

+

RepeatedRules describe the constraints applied to `repeated` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
min_itemsuint64optional

MinItems specifies that this field must have the specified number of +items at a minimum

max_itemsuint64optional

MaxItems specifies that this field must have the specified number of +items at a maximum

uniquebooloptional

Unique specifies that all elements in this field must be unique. This +constraint is only applicable to scalar and enum types (messages are not +supported).

itemsFieldRulesoptional

Items specifies the constraints to be applied to each item in the field. +Repeated message fields will still execute validation against each item +unless skip is specified here.

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

SFixed32Rules

+

SFixed32Rules describes the constraints applied to `sfixed32` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constsfixed32optional

Const specifies that this field must be exactly the specified value

ltsfixed32optional

Lt specifies that this field must be less than the specified value, +exclusive

ltesfixed32optional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtsfixed32optional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gtesfixed32optional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

insfixed32repeated

In specifies that this field must be equal to one of the specified +values

not_insfixed32repeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

SFixed64Rules

+

SFixed64Rules describes the constraints applied to `sfixed64` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constsfixed64optional

Const specifies that this field must be exactly the specified value

ltsfixed64optional

Lt specifies that this field must be less than the specified value, +exclusive

ltesfixed64optional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtsfixed64optional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gtesfixed64optional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

insfixed64repeated

In specifies that this field must be equal to one of the specified +values

not_insfixed64repeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

SInt32Rules

+

SInt32Rules describes the constraints applied to `sint32` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constsint32optional

Const specifies that this field must be exactly the specified value

ltsint32optional

Lt specifies that this field must be less than the specified value, +exclusive

ltesint32optional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtsint32optional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gtesint32optional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

insint32repeated

In specifies that this field must be equal to one of the specified +values

not_insint32repeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

SInt64Rules

+

SInt64Rules describes the constraints applied to `sint64` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constsint64optional

Const specifies that this field must be exactly the specified value

ltsint64optional

Lt specifies that this field must be less than the specified value, +exclusive

ltesint64optional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtsint64optional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gtesint64optional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

insint64repeated

In specifies that this field must be equal to one of the specified +values

not_insint64repeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

StringRules

+

StringRules describe the constraints applied to `string` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
conststringoptional

Const specifies that this field must be exactly the specified value

lenuint64optional

Len specifies that this field must be the specified number of +characters (Unicode code points). Note that the number of +characters may differ from the number of bytes in the string.

min_lenuint64optional

MinLen specifies that this field must be the specified number of +characters (Unicode code points) at a minimum. Note that the number of +characters may differ from the number of bytes in the string.

max_lenuint64optional

MaxLen specifies that this field must be the specified number of +characters (Unicode code points) at a maximum. Note that the number of +characters may differ from the number of bytes in the string.

len_bytesuint64optional

LenBytes specifies that this field must be the specified number of bytes

min_bytesuint64optional

MinBytes specifies that this field must be the specified number of bytes +at a minimum

max_bytesuint64optional

MaxBytes specifies that this field must be the specified number of bytes +at a maximum

patternstringoptional

Pattern specifies that this field must match against the specified +regular expression (RE2 syntax). The included expression should elide +any delimiters.

prefixstringoptional

Prefix specifies that this field must have the specified substring at +the beginning of the string.

suffixstringoptional

Suffix specifies that this field must have the specified substring at +the end of the string.

containsstringoptional

Contains specifies that this field must have the specified substring +anywhere in the string.

not_containsstringoptional

NotContains specifies that this field cannot have the specified substring +anywhere in the string.

instringrepeated

In specifies that this field must be equal to one of the specified +values

not_instringrepeated

NotIn specifies that this field cannot be equal to one of the specified +values

emailbooloptional

Email specifies that the field must be a valid email address as +defined by RFC 5322

hostnamebooloptional

Hostname specifies that the field must be a valid hostname as +defined by RFC 1034. This constraint does not support +internationalized domain names (IDNs).

ipbooloptional

Ip specifies that the field must be a valid IP (v4 or v6) address. +Valid IPv6 addresses should not include surrounding square brackets.

ipv4booloptional

Ipv4 specifies that the field must be a valid IPv4 address.

ipv6booloptional

Ipv6 specifies that the field must be a valid IPv6 address. Valid +IPv6 addresses should not include surrounding square brackets.

uribooloptional

Uri specifies that the field must be a valid, absolute URI as defined +by RFC 3986

uri_refbooloptional

UriRef specifies that the field must be a valid URI as defined by RFC +3986 and may be relative or absolute.

addressbooloptional

Address specifies that the field must be either a valid hostname as +defined by RFC 1034 (which does not support internationalized domain +names or IDNs), or it can be a valid IP (v4 or v6).

uuidbooloptional

Uuid specifies that the field must be a valid UUID as defined by +RFC 4122

well_known_regexKnownRegexoptional

WellKnownRegex specifies a common well known pattern defined as a regex.

strictbooloptional

This applies to regexes HTTP_HEADER_NAME and HTTP_HEADER_VALUE to enable +strict header validation. +By default, this is true, and HTTP header validations are RFC-compliant. +Setting to false will enable a looser validations that only disallows +\r\n\0 characters, which can be used to bypass header matching rules. Default: true

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

TimestampRules

+

TimestampRules describe the constraints applied exclusively to the

`google.protobuf.Timestamp` well-known type

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
requiredbooloptional

Required specifies that this field must be set

constgoogle.protobuf.Timestampoptional

Const specifies that this field must be exactly the specified value

ltgoogle.protobuf.Timestampoptional

Lt specifies that this field must be less than the specified value, +exclusive

ltegoogle.protobuf.Timestampoptional

Lte specifies that this field must be less than the specified value, +inclusive

gtgoogle.protobuf.Timestampoptional

Gt specifies that this field must be greater than the specified value, +exclusive

gtegoogle.protobuf.Timestampoptional

Gte specifies that this field must be greater than the specified value, +inclusive

lt_nowbooloptional

LtNow specifies that this must be less than the current time. LtNow +can only be used with the Within rule.

gt_nowbooloptional

GtNow specifies that this must be greater than the current time. GtNow +can only be used with the Within rule.

withingoogle.protobuf.Durationoptional

Within specifies that this field must be within this duration of the +current time. This constraint can be used alone or with the LtNow and +GtNow rules.

+ + + + + +

UInt32Rules

+

UInt32Rules describes the constraints applied to `uint32` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constuint32optional

Const specifies that this field must be exactly the specified value

ltuint32optional

Lt specifies that this field must be less than the specified value, +exclusive

lteuint32optional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtuint32optional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gteuint32optional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

inuint32repeated

In specifies that this field must be equal to one of the specified +values

not_inuint32repeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + +

UInt64Rules

+

UInt64Rules describes the constraints applied to `uint64` values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
constuint64optional

Const specifies that this field must be exactly the specified value

ltuint64optional

Lt specifies that this field must be less than the specified value, +exclusive

lteuint64optional

Lte specifies that this field must be less than or equal to the +specified value, inclusive

gtuint64optional

Gt specifies that this field must be greater than the specified value, +exclusive. If the value of Gt is larger than a specified Lt or Lte, the +range is reversed.

gteuint64optional

Gte specifies that this field must be greater than or equal to the +specified value, inclusive. If the value of Gte is larger than a +specified Lt or Lte, the range is reversed.

inuint64repeated

In specifies that this field must be equal to one of the specified +values

not_inuint64repeated

NotIn specifies that this field cannot be equal to one of the specified +values

ignore_emptybooloptional

IgnoreEmpty specifies that the validation rules of this field should be +evaluated only if the field is not empty

+ + + + + + + +

KnownRegex

+

WellKnownRegex contain some well-known patterns.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
NameNumberDescription
UNKNOWN0

HTTP_HEADER_NAME1

HTTP header name as defined by RFC 7230.

HTTP_HEADER_VALUE2

HTTP header value as defined by RFC 7230.

+ + + +

File-level Extensions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExtensionTypeBaseNumberDescription
rulesFieldRules.google.protobuf.FieldOptions1071

Rules specify the validations to be performed on this field. By default, +no validation is performed against a field.

disabledbool.google.protobuf.MessageOptions1071

Disabled nullifies any validation rules for this message, including any +message fields associated with it that do support validation.

ignoredbool.google.protobuf.MessageOptions1072

Ignore skips generation of validation methods for this message.

requiredbool.google.protobuf.OneofOptions1071

Required ensures that exactly one the field options in a oneof is set; +validation fails if no fields in the oneof are set.

+ + + + + +
+

cloud/v1/cloud.proto

Top +
+

+ + +

CreateTaskRequest

+

Message for Task creation request

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
namestring

Name of the task. Must contain only alphanumeric characters, underscores, or dashes, +with a maximum length of 255 characters for readability and database compatibility.

typestring

Type of the task. Must be either SEND_EMAIL or RUN_QUERY. +This field is an enum to ensure only predefined task types are used.

payloadPayload

Payload containing task parameters. This field is required to ensure +all necessary information for task execution is provided.

descriptionstring

Description of the task. Allows for a detailed explanation of the task's purpose. +Limited to 5000 characters to balance between providing sufficient detail and +preventing excessively long descriptions.

+ + + + +

Validated Fields

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldValidations
name +
    + +
  • string.max_len: 255
  • + +
  • string.pattern: ^[a-zA-Z0-9_-]+$
  • + +
+
type +
    + +
  • enum.defined_only: true
  • + +
+
payload +
    + +
  • message.required: true
  • + +
+
description +
    + +
  • string.max_len: 5000
  • + +
+
+ + + + + +

CreateTaskResponse

+

Message for Task creation response

+ + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
idint32

Unique identifier for the created task. Must be >= 0.

+ + + + +

Validated Fields

+ + + + + + + + + + + + + + + +
FieldValidations
id +
    + +
  • int32.gte: 0
  • + +
+
+ + + + + +

GetStatusRequest

+

Message for GetStatus request (empty)

+ + + + + +

GetStatusResponse

+

Message for GetStatus response

+ + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
status_countsGetStatusResponse.StatusCountsEntryrepeated

Map of task statuses and their counts

+ + + + + +

GetStatusResponse.StatusCountsEntry

+

+ + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
keyint32

valueint64

+ + + + + +

GetTaskHistoryRequest

+

Message for Task history request

+ + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
idint32

Unique identifier for the task. Must be >= 0.

+ + + + +

Validated Fields

+ + + + + + + + + + + + + + + +
FieldValidations
id +
    + +
  • int32.gte: 0
  • + +
+
+ + + + + +

GetTaskHistoryResponse

+

Message for Task history response

+ + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
historyTaskHistoryrepeated

List of task history entries. Minimum of 1 entry ensures that some history is always returned. +Maximum of 1000 entries prevents excessive data transfer and processing for very long-running tasks.

+ + + + +

Validated Fields

+ + + + + + + + + + + + + + + +
FieldValidations
history +
    + +
  • repeated.min_items: 1
  • + +
  • repeated.max_items: 1000
  • + +
+
+ + + + + +

GetTaskRequest

+

Message for Task status request

+ + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
idint32

Unique identifier for the task. Must be >= 0.

+ + + + +

Validated Fields

+ + + + + + + + + + + + + + + +
FieldValidations
id +
    + +
  • int32.gte: 0
  • + +
+
+ + + + + +

Payload

+

Message for Task Payload

+ + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
parametersPayload.ParametersEntryrepeated

Dynamic key-value pairs for task parameters. +Keys must contain only alphanumeric characters, underscores, or dashes. +Values are limited to 1024 characters to prevent excessive data storage.

+ + + + +

Validated Fields

+ + + + + + + + + + + + + + + +
FieldValidations
parameters +
    + +
  • map.keys.string.pattern: ^[a-zA-Z0-9_-]+$
  • + +
  • map.values.string.max_len: 1024
  • + +
+
+ + + + + +

Payload.ParametersEntry

+

+ + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
keystring

valuestring

+ + + + + +

Task

+

Message for Task status

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
idint32

Unique identifier for the task. Must be >= 0.

namestring

Name of the task. Must be alphanumeric, underscores, or dashes, +with a maximum length of 255 characters.

typestring

Type of the task, must be either SEND_EMAIL or RUN_QUERY.

statusTaskStatusEnum

Current status of the task, must be one of the defined statuses.

retriesint32

Number of retries attempted for this task. Limited to 10 to prevent +infinite retry loops while allowing for reasonable error recovery.

priorityint32

Priority level of the task. Higher values indicate higher priority. +Must be non-negative to ensure valid prioritization.

created_atstring

Timestamp of when the task was created, in ISO 8601 format (UTC). +This format ensures consistent time representation across different systems.

payloadPayload

Payload containing task parameters. This field is required.

descriptionstring

Description of the task. A large text string with a maximum length of 5000 characters.

+ + + + +

Validated Fields

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldValidations
id +
    + +
  • int32.gte: 0
  • + +
+
name +
    + +
  • string.max_len: 255
  • + +
  • string.pattern: ^[a-zA-Z0-9_-]+$
  • + +
+
type +
    + +
  • enum.defined_only: true
  • + +
+
status +
    + +
  • enum.defined_only: true
  • + +
+
retries +
    + +
  • int32.lte: 10
  • + +
  • int32.gte: 0
  • + +
+
priority +
    + +
  • int32.gte: 0
  • + +
+
created_at +
    + +
  • string.pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$
  • + +
+
payload +
    + +
  • message.required: true
  • + +
+
description +
    + +
  • string.max_len: 5000
  • + +
+
+ + + + + +

TaskHistory

+

Message for Task history

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
idint32

Unique identifier for the history entry. Must be >= 0.

statusTaskStatusEnum

Status of the task at the time of this history entry.

created_atstring

Timestamp of when this history entry was created, in ISO 8601 format.

detailsstring

Additional details about the task's execution or status. +Maximum length of 2000 characters.

+ + + + +

Validated Fields

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldValidations
id +
    + +
  • int32.gte: 0
  • + +
+
status +
    + +
  • enum.defined_only: true
  • + +
+
created_at +
    + +
  • string.pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$
  • + +
+
details +
    + +
  • string.max_len: 2000
  • + +
+
+ + + + + +

TaskList

+

Message for Task List

+ + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
tasksTaskrepeated

List of tasks in the system.

+ + + + + +

TaskListRequest

+

Message for Task List request

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
limitint32

Maximum number of tasks to return in a single request. +Limited between 1 and 100 to balance between minimizing requests and preventing excessive data transfer.

offsetint32

Number of tasks to skip before starting to return results. +Allows for pagination of results. Must be non-negative.

statusTaskStatusEnumoptional

Optional filter for tasks by status. If not specified, tasks of all statuses will be returned.

typestringoptional

Optional filter for tasks by type. Must be either SEND_EMAIL or RUN_QUERY if specified. +If not specified, tasks of all types will be returned.

+ + + + +

Validated Fields

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldValidations
limit +
    + +
  • int32.lte: 100
  • + +
  • int32.gte: 1
  • + +
+
offset +
    + +
  • int32.gte: 0
  • + +
+
type +
    + +
  • string.in: [send_email run_query]
  • + +
+
+ + + + + +

UpdateTaskStatusRequest

+

Message for Task status update request

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeLabelDescription
idint32

Unique identifier for the task. Must be >= 0.

statusTaskStatusEnum

New status for the task, must be one of the defined statuses.

messagestring

Additional message about the status update. Maximum length of 2000 characters.

+ + + + +

Validated Fields

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldValidations
id +
    + +
  • int32.gte: 0
  • + +
+
status +
    + +
  • enum.defined_only: true
  • + +
+
message +
    + +
  • string.max_len: 2000
  • + +
+
+ + + + + + + +

TaskStatusEnum

+

Enum for Task statuses

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameNumberDescription
QUEUED0

Task is in the queue, waiting to be processed

RUNNING1

Task is currently being executed

FAILED2

Task encountered an error and failed to complete

SUCCEEDED3

Task completed successfully

UNKNOWN4

Task status cannot be determined

ALL5

Task status cannot be determined

+ + + + + +

TaskManagementService

+

Task Management service definition

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method NameRequest TypeResponse TypeDescription
CreateTaskCreateTaskRequestCreateTaskResponse

Creates a new task based on the provided request. +Returns a CreateTaskResponse containing the unique identifier of the created task.

GetTaskGetTaskRequestTask

Retrieves the current status and details of the specified task. +Returns a Task message containing all information about the requested task.

ListTasksTaskListRequestTaskList

Lists tasks currently available in the system, with pagination support. +Returns a TaskList containing the requested subset of tasks.

GetTaskHistoryGetTaskHistoryRequestGetTaskHistoryResponse

Retrieves the execution history of the specified task. +Returns a GetTaskHistoryResponse containing a list of historical status updates.

UpdateTaskStatusUpdateTaskStatusRequest.google.protobuf.Empty

Updates the status of the specified task. +Returns an empty response to confirm the update was processed.

GetStatusGetStatusRequestGetStatusResponse

Retrieves the count of tasks for each status. +Returns a GetStatusResponse containing a map of status counts.

+ + + + +

Scalar Value Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
.proto TypeNotesC++JavaPythonGoC#PHPRuby
doubledoubledoublefloatfloat64doublefloatFloat
floatfloatfloatfloatfloat32floatfloatFloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32intintegerBignum or Fixnum (as required)
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/longint64longinteger/stringBignum
uint32Uses variable-length encoding.uint32intint/longuint32uintintegerBignum or Fixnum (as required)
uint64Uses variable-length encoding.uint64longint/longuint64ulonginteger/stringBignum or Fixnum (as required)
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32intintegerBignum or Fixnum (as required)
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/longint64longinteger/stringBignum
fixed32Always four bytes. More efficient than uint32 if values are often greater than 2^28.uint32intintuint32uintintegerBignum or Fixnum (as required)
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 2^56.uint64longint/longuint64ulonginteger/stringBignum
sfixed32Always four bytes.int32intintint32intintegerBignum or Fixnum (as required)
sfixed64Always eight bytes.int64longint/longint64longinteger/stringBignum
boolboolbooleanbooleanboolboolbooleanTrueClass/FalseClass
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicodestringstringstringString (UTF-8)
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteByteStringstringString (ASCII-8BIT)
+ + + diff --git a/pkg/gen/validate/validate.pb.go b/pkg/gen/validate/validate.pb.go new file mode 100644 index 0000000..31f91c2 --- /dev/null +++ b/pkg/gen/validate/validate.pb.go @@ -0,0 +1,4111 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc (unknown) +// source: validate/validate.proto + +package validate + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + descriptorpb "google.golang.org/protobuf/types/descriptorpb" + durationpb "google.golang.org/protobuf/types/known/durationpb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// WellKnownRegex contain some well-known patterns. +type KnownRegex int32 + +const ( + KnownRegex_UNKNOWN KnownRegex = 0 + // HTTP header name as defined by RFC 7230. + KnownRegex_HTTP_HEADER_NAME KnownRegex = 1 + // HTTP header value as defined by RFC 7230. + KnownRegex_HTTP_HEADER_VALUE KnownRegex = 2 +) + +// Enum value maps for KnownRegex. +var ( + KnownRegex_name = map[int32]string{ + 0: "UNKNOWN", + 1: "HTTP_HEADER_NAME", + 2: "HTTP_HEADER_VALUE", + } + KnownRegex_value = map[string]int32{ + "UNKNOWN": 0, + "HTTP_HEADER_NAME": 1, + "HTTP_HEADER_VALUE": 2, + } +) + +func (x KnownRegex) Enum() *KnownRegex { + p := new(KnownRegex) + *p = x + return p +} + +func (x KnownRegex) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (KnownRegex) Descriptor() protoreflect.EnumDescriptor { + return file_validate_validate_proto_enumTypes[0].Descriptor() +} + +func (KnownRegex) Type() protoreflect.EnumType { + return &file_validate_validate_proto_enumTypes[0] +} + +func (x KnownRegex) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Do not use. +func (x *KnownRegex) UnmarshalJSON(b []byte) error { + num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) + if err != nil { + return err + } + *x = KnownRegex(num) + return nil +} + +// Deprecated: Use KnownRegex.Descriptor instead. +func (KnownRegex) EnumDescriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{0} +} + +// FieldRules encapsulates the rules for each type of field. Depending on the +// field, the correct set should be used to ensure proper validations. +type FieldRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message *MessageRules `protobuf:"bytes,17,opt,name=message" json:"message,omitempty"` + // Types that are assignable to Type: + // + // *FieldRules_Float + // *FieldRules_Double + // *FieldRules_Int32 + // *FieldRules_Int64 + // *FieldRules_Uint32 + // *FieldRules_Uint64 + // *FieldRules_Sint32 + // *FieldRules_Sint64 + // *FieldRules_Fixed32 + // *FieldRules_Fixed64 + // *FieldRules_Sfixed32 + // *FieldRules_Sfixed64 + // *FieldRules_Bool + // *FieldRules_String_ + // *FieldRules_Bytes + // *FieldRules_Enum + // *FieldRules_Repeated + // *FieldRules_Map + // *FieldRules_Any + // *FieldRules_Duration + // *FieldRules_Timestamp + Type isFieldRules_Type `protobuf_oneof:"type"` +} + +func (x *FieldRules) Reset() { + *x = FieldRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FieldRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FieldRules) ProtoMessage() {} + +func (x *FieldRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FieldRules.ProtoReflect.Descriptor instead. +func (*FieldRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{0} +} + +func (x *FieldRules) GetMessage() *MessageRules { + if x != nil { + return x.Message + } + return nil +} + +func (m *FieldRules) GetType() isFieldRules_Type { + if m != nil { + return m.Type + } + return nil +} + +func (x *FieldRules) GetFloat() *FloatRules { + if x, ok := x.GetType().(*FieldRules_Float); ok { + return x.Float + } + return nil +} + +func (x *FieldRules) GetDouble() *DoubleRules { + if x, ok := x.GetType().(*FieldRules_Double); ok { + return x.Double + } + return nil +} + +func (x *FieldRules) GetInt32() *Int32Rules { + if x, ok := x.GetType().(*FieldRules_Int32); ok { + return x.Int32 + } + return nil +} + +func (x *FieldRules) GetInt64() *Int64Rules { + if x, ok := x.GetType().(*FieldRules_Int64); ok { + return x.Int64 + } + return nil +} + +func (x *FieldRules) GetUint32() *UInt32Rules { + if x, ok := x.GetType().(*FieldRules_Uint32); ok { + return x.Uint32 + } + return nil +} + +func (x *FieldRules) GetUint64() *UInt64Rules { + if x, ok := x.GetType().(*FieldRules_Uint64); ok { + return x.Uint64 + } + return nil +} + +func (x *FieldRules) GetSint32() *SInt32Rules { + if x, ok := x.GetType().(*FieldRules_Sint32); ok { + return x.Sint32 + } + return nil +} + +func (x *FieldRules) GetSint64() *SInt64Rules { + if x, ok := x.GetType().(*FieldRules_Sint64); ok { + return x.Sint64 + } + return nil +} + +func (x *FieldRules) GetFixed32() *Fixed32Rules { + if x, ok := x.GetType().(*FieldRules_Fixed32); ok { + return x.Fixed32 + } + return nil +} + +func (x *FieldRules) GetFixed64() *Fixed64Rules { + if x, ok := x.GetType().(*FieldRules_Fixed64); ok { + return x.Fixed64 + } + return nil +} + +func (x *FieldRules) GetSfixed32() *SFixed32Rules { + if x, ok := x.GetType().(*FieldRules_Sfixed32); ok { + return x.Sfixed32 + } + return nil +} + +func (x *FieldRules) GetSfixed64() *SFixed64Rules { + if x, ok := x.GetType().(*FieldRules_Sfixed64); ok { + return x.Sfixed64 + } + return nil +} + +func (x *FieldRules) GetBool() *BoolRules { + if x, ok := x.GetType().(*FieldRules_Bool); ok { + return x.Bool + } + return nil +} + +func (x *FieldRules) GetString_() *StringRules { + if x, ok := x.GetType().(*FieldRules_String_); ok { + return x.String_ + } + return nil +} + +func (x *FieldRules) GetBytes() *BytesRules { + if x, ok := x.GetType().(*FieldRules_Bytes); ok { + return x.Bytes + } + return nil +} + +func (x *FieldRules) GetEnum() *EnumRules { + if x, ok := x.GetType().(*FieldRules_Enum); ok { + return x.Enum + } + return nil +} + +func (x *FieldRules) GetRepeated() *RepeatedRules { + if x, ok := x.GetType().(*FieldRules_Repeated); ok { + return x.Repeated + } + return nil +} + +func (x *FieldRules) GetMap() *MapRules { + if x, ok := x.GetType().(*FieldRules_Map); ok { + return x.Map + } + return nil +} + +func (x *FieldRules) GetAny() *AnyRules { + if x, ok := x.GetType().(*FieldRules_Any); ok { + return x.Any + } + return nil +} + +func (x *FieldRules) GetDuration() *DurationRules { + if x, ok := x.GetType().(*FieldRules_Duration); ok { + return x.Duration + } + return nil +} + +func (x *FieldRules) GetTimestamp() *TimestampRules { + if x, ok := x.GetType().(*FieldRules_Timestamp); ok { + return x.Timestamp + } + return nil +} + +type isFieldRules_Type interface { + isFieldRules_Type() +} + +type FieldRules_Float struct { + // Scalar Field Types + Float *FloatRules `protobuf:"bytes,1,opt,name=float,oneof"` +} + +type FieldRules_Double struct { + Double *DoubleRules `protobuf:"bytes,2,opt,name=double,oneof"` +} + +type FieldRules_Int32 struct { + Int32 *Int32Rules `protobuf:"bytes,3,opt,name=int32,oneof"` +} + +type FieldRules_Int64 struct { + Int64 *Int64Rules `protobuf:"bytes,4,opt,name=int64,oneof"` +} + +type FieldRules_Uint32 struct { + Uint32 *UInt32Rules `protobuf:"bytes,5,opt,name=uint32,oneof"` +} + +type FieldRules_Uint64 struct { + Uint64 *UInt64Rules `protobuf:"bytes,6,opt,name=uint64,oneof"` +} + +type FieldRules_Sint32 struct { + Sint32 *SInt32Rules `protobuf:"bytes,7,opt,name=sint32,oneof"` +} + +type FieldRules_Sint64 struct { + Sint64 *SInt64Rules `protobuf:"bytes,8,opt,name=sint64,oneof"` +} + +type FieldRules_Fixed32 struct { + Fixed32 *Fixed32Rules `protobuf:"bytes,9,opt,name=fixed32,oneof"` +} + +type FieldRules_Fixed64 struct { + Fixed64 *Fixed64Rules `protobuf:"bytes,10,opt,name=fixed64,oneof"` +} + +type FieldRules_Sfixed32 struct { + Sfixed32 *SFixed32Rules `protobuf:"bytes,11,opt,name=sfixed32,oneof"` +} + +type FieldRules_Sfixed64 struct { + Sfixed64 *SFixed64Rules `protobuf:"bytes,12,opt,name=sfixed64,oneof"` +} + +type FieldRules_Bool struct { + Bool *BoolRules `protobuf:"bytes,13,opt,name=bool,oneof"` +} + +type FieldRules_String_ struct { + String_ *StringRules `protobuf:"bytes,14,opt,name=string,oneof"` +} + +type FieldRules_Bytes struct { + Bytes *BytesRules `protobuf:"bytes,15,opt,name=bytes,oneof"` +} + +type FieldRules_Enum struct { + // Complex Field Types + Enum *EnumRules `protobuf:"bytes,16,opt,name=enum,oneof"` +} + +type FieldRules_Repeated struct { + Repeated *RepeatedRules `protobuf:"bytes,18,opt,name=repeated,oneof"` +} + +type FieldRules_Map struct { + Map *MapRules `protobuf:"bytes,19,opt,name=map,oneof"` +} + +type FieldRules_Any struct { + // Well-Known Field Types + Any *AnyRules `protobuf:"bytes,20,opt,name=any,oneof"` +} + +type FieldRules_Duration struct { + Duration *DurationRules `protobuf:"bytes,21,opt,name=duration,oneof"` +} + +type FieldRules_Timestamp struct { + Timestamp *TimestampRules `protobuf:"bytes,22,opt,name=timestamp,oneof"` +} + +func (*FieldRules_Float) isFieldRules_Type() {} + +func (*FieldRules_Double) isFieldRules_Type() {} + +func (*FieldRules_Int32) isFieldRules_Type() {} + +func (*FieldRules_Int64) isFieldRules_Type() {} + +func (*FieldRules_Uint32) isFieldRules_Type() {} + +func (*FieldRules_Uint64) isFieldRules_Type() {} + +func (*FieldRules_Sint32) isFieldRules_Type() {} + +func (*FieldRules_Sint64) isFieldRules_Type() {} + +func (*FieldRules_Fixed32) isFieldRules_Type() {} + +func (*FieldRules_Fixed64) isFieldRules_Type() {} + +func (*FieldRules_Sfixed32) isFieldRules_Type() {} + +func (*FieldRules_Sfixed64) isFieldRules_Type() {} + +func (*FieldRules_Bool) isFieldRules_Type() {} + +func (*FieldRules_String_) isFieldRules_Type() {} + +func (*FieldRules_Bytes) isFieldRules_Type() {} + +func (*FieldRules_Enum) isFieldRules_Type() {} + +func (*FieldRules_Repeated) isFieldRules_Type() {} + +func (*FieldRules_Map) isFieldRules_Type() {} + +func (*FieldRules_Any) isFieldRules_Type() {} + +func (*FieldRules_Duration) isFieldRules_Type() {} + +func (*FieldRules_Timestamp) isFieldRules_Type() {} + +// FloatRules describes the constraints applied to `float` values +type FloatRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *float32 `protobuf:"fixed32,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *float32 `protobuf:"fixed32,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *float32 `protobuf:"fixed32,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *float32 `protobuf:"fixed32,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *float32 `protobuf:"fixed32,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []float32 `protobuf:"fixed32,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []float32 `protobuf:"fixed32,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *FloatRules) Reset() { + *x = FloatRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FloatRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FloatRules) ProtoMessage() {} + +func (x *FloatRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FloatRules.ProtoReflect.Descriptor instead. +func (*FloatRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{1} +} + +func (x *FloatRules) GetConst() float32 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *FloatRules) GetLt() float32 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *FloatRules) GetLte() float32 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *FloatRules) GetGt() float32 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *FloatRules) GetGte() float32 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *FloatRules) GetIn() []float32 { + if x != nil { + return x.In + } + return nil +} + +func (x *FloatRules) GetNotIn() []float32 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *FloatRules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// DoubleRules describes the constraints applied to `double` values +type DoubleRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *float64 `protobuf:"fixed64,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *float64 `protobuf:"fixed64,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *float64 `protobuf:"fixed64,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *float64 `protobuf:"fixed64,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *float64 `protobuf:"fixed64,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []float64 `protobuf:"fixed64,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []float64 `protobuf:"fixed64,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *DoubleRules) Reset() { + *x = DoubleRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DoubleRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DoubleRules) ProtoMessage() {} + +func (x *DoubleRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DoubleRules.ProtoReflect.Descriptor instead. +func (*DoubleRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{2} +} + +func (x *DoubleRules) GetConst() float64 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *DoubleRules) GetLt() float64 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *DoubleRules) GetLte() float64 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *DoubleRules) GetGt() float64 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *DoubleRules) GetGte() float64 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *DoubleRules) GetIn() []float64 { + if x != nil { + return x.In + } + return nil +} + +func (x *DoubleRules) GetNotIn() []float64 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *DoubleRules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// Int32Rules describes the constraints applied to `int32` values +type Int32Rules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *int32 `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *int32 `protobuf:"varint,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *int32 `protobuf:"varint,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *int32 `protobuf:"varint,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *int32 `protobuf:"varint,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []int32 `protobuf:"varint,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []int32 `protobuf:"varint,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *Int32Rules) Reset() { + *x = Int32Rules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Int32Rules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Int32Rules) ProtoMessage() {} + +func (x *Int32Rules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Int32Rules.ProtoReflect.Descriptor instead. +func (*Int32Rules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{3} +} + +func (x *Int32Rules) GetConst() int32 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *Int32Rules) GetLt() int32 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *Int32Rules) GetLte() int32 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *Int32Rules) GetGt() int32 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *Int32Rules) GetGte() int32 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *Int32Rules) GetIn() []int32 { + if x != nil { + return x.In + } + return nil +} + +func (x *Int32Rules) GetNotIn() []int32 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *Int32Rules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// Int64Rules describes the constraints applied to `int64` values +type Int64Rules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *int64 `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *int64 `protobuf:"varint,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *int64 `protobuf:"varint,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *int64 `protobuf:"varint,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *int64 `protobuf:"varint,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []int64 `protobuf:"varint,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []int64 `protobuf:"varint,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *Int64Rules) Reset() { + *x = Int64Rules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Int64Rules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Int64Rules) ProtoMessage() {} + +func (x *Int64Rules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Int64Rules.ProtoReflect.Descriptor instead. +func (*Int64Rules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{4} +} + +func (x *Int64Rules) GetConst() int64 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *Int64Rules) GetLt() int64 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *Int64Rules) GetLte() int64 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *Int64Rules) GetGt() int64 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *Int64Rules) GetGte() int64 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *Int64Rules) GetIn() []int64 { + if x != nil { + return x.In + } + return nil +} + +func (x *Int64Rules) GetNotIn() []int64 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *Int64Rules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// UInt32Rules describes the constraints applied to `uint32` values +type UInt32Rules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *uint32 `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *uint32 `protobuf:"varint,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *uint32 `protobuf:"varint,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *uint32 `protobuf:"varint,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *uint32 `protobuf:"varint,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []uint32 `protobuf:"varint,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []uint32 `protobuf:"varint,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *UInt32Rules) Reset() { + *x = UInt32Rules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UInt32Rules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UInt32Rules) ProtoMessage() {} + +func (x *UInt32Rules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UInt32Rules.ProtoReflect.Descriptor instead. +func (*UInt32Rules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{5} +} + +func (x *UInt32Rules) GetConst() uint32 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *UInt32Rules) GetLt() uint32 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *UInt32Rules) GetLte() uint32 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *UInt32Rules) GetGt() uint32 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *UInt32Rules) GetGte() uint32 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *UInt32Rules) GetIn() []uint32 { + if x != nil { + return x.In + } + return nil +} + +func (x *UInt32Rules) GetNotIn() []uint32 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *UInt32Rules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// UInt64Rules describes the constraints applied to `uint64` values +type UInt64Rules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *uint64 `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *uint64 `protobuf:"varint,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *uint64 `protobuf:"varint,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *uint64 `protobuf:"varint,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *uint64 `protobuf:"varint,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []uint64 `protobuf:"varint,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []uint64 `protobuf:"varint,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *UInt64Rules) Reset() { + *x = UInt64Rules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UInt64Rules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UInt64Rules) ProtoMessage() {} + +func (x *UInt64Rules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UInt64Rules.ProtoReflect.Descriptor instead. +func (*UInt64Rules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{6} +} + +func (x *UInt64Rules) GetConst() uint64 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *UInt64Rules) GetLt() uint64 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *UInt64Rules) GetLte() uint64 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *UInt64Rules) GetGt() uint64 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *UInt64Rules) GetGte() uint64 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *UInt64Rules) GetIn() []uint64 { + if x != nil { + return x.In + } + return nil +} + +func (x *UInt64Rules) GetNotIn() []uint64 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *UInt64Rules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// SInt32Rules describes the constraints applied to `sint32` values +type SInt32Rules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *int32 `protobuf:"zigzag32,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *int32 `protobuf:"zigzag32,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *int32 `protobuf:"zigzag32,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *int32 `protobuf:"zigzag32,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *int32 `protobuf:"zigzag32,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []int32 `protobuf:"zigzag32,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []int32 `protobuf:"zigzag32,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *SInt32Rules) Reset() { + *x = SInt32Rules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SInt32Rules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SInt32Rules) ProtoMessage() {} + +func (x *SInt32Rules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SInt32Rules.ProtoReflect.Descriptor instead. +func (*SInt32Rules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{7} +} + +func (x *SInt32Rules) GetConst() int32 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *SInt32Rules) GetLt() int32 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *SInt32Rules) GetLte() int32 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *SInt32Rules) GetGt() int32 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *SInt32Rules) GetGte() int32 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *SInt32Rules) GetIn() []int32 { + if x != nil { + return x.In + } + return nil +} + +func (x *SInt32Rules) GetNotIn() []int32 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *SInt32Rules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// SInt64Rules describes the constraints applied to `sint64` values +type SInt64Rules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *int64 `protobuf:"zigzag64,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *int64 `protobuf:"zigzag64,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *int64 `protobuf:"zigzag64,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *int64 `protobuf:"zigzag64,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *int64 `protobuf:"zigzag64,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []int64 `protobuf:"zigzag64,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []int64 `protobuf:"zigzag64,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *SInt64Rules) Reset() { + *x = SInt64Rules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SInt64Rules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SInt64Rules) ProtoMessage() {} + +func (x *SInt64Rules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SInt64Rules.ProtoReflect.Descriptor instead. +func (*SInt64Rules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{8} +} + +func (x *SInt64Rules) GetConst() int64 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *SInt64Rules) GetLt() int64 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *SInt64Rules) GetLte() int64 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *SInt64Rules) GetGt() int64 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *SInt64Rules) GetGte() int64 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *SInt64Rules) GetIn() []int64 { + if x != nil { + return x.In + } + return nil +} + +func (x *SInt64Rules) GetNotIn() []int64 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *SInt64Rules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// Fixed32Rules describes the constraints applied to `fixed32` values +type Fixed32Rules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *uint32 `protobuf:"fixed32,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *uint32 `protobuf:"fixed32,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *uint32 `protobuf:"fixed32,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *uint32 `protobuf:"fixed32,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *uint32 `protobuf:"fixed32,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []uint32 `protobuf:"fixed32,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []uint32 `protobuf:"fixed32,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *Fixed32Rules) Reset() { + *x = Fixed32Rules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Fixed32Rules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Fixed32Rules) ProtoMessage() {} + +func (x *Fixed32Rules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Fixed32Rules.ProtoReflect.Descriptor instead. +func (*Fixed32Rules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{9} +} + +func (x *Fixed32Rules) GetConst() uint32 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *Fixed32Rules) GetLt() uint32 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *Fixed32Rules) GetLte() uint32 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *Fixed32Rules) GetGt() uint32 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *Fixed32Rules) GetGte() uint32 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *Fixed32Rules) GetIn() []uint32 { + if x != nil { + return x.In + } + return nil +} + +func (x *Fixed32Rules) GetNotIn() []uint32 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *Fixed32Rules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// Fixed64Rules describes the constraints applied to `fixed64` values +type Fixed64Rules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *uint64 `protobuf:"fixed64,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *uint64 `protobuf:"fixed64,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *uint64 `protobuf:"fixed64,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *uint64 `protobuf:"fixed64,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *uint64 `protobuf:"fixed64,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []uint64 `protobuf:"fixed64,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []uint64 `protobuf:"fixed64,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *Fixed64Rules) Reset() { + *x = Fixed64Rules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Fixed64Rules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Fixed64Rules) ProtoMessage() {} + +func (x *Fixed64Rules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Fixed64Rules.ProtoReflect.Descriptor instead. +func (*Fixed64Rules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{10} +} + +func (x *Fixed64Rules) GetConst() uint64 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *Fixed64Rules) GetLt() uint64 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *Fixed64Rules) GetLte() uint64 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *Fixed64Rules) GetGt() uint64 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *Fixed64Rules) GetGte() uint64 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *Fixed64Rules) GetIn() []uint64 { + if x != nil { + return x.In + } + return nil +} + +func (x *Fixed64Rules) GetNotIn() []uint64 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *Fixed64Rules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// SFixed32Rules describes the constraints applied to `sfixed32` values +type SFixed32Rules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *int32 `protobuf:"fixed32,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *int32 `protobuf:"fixed32,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *int32 `protobuf:"fixed32,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *int32 `protobuf:"fixed32,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *int32 `protobuf:"fixed32,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []int32 `protobuf:"fixed32,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []int32 `protobuf:"fixed32,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *SFixed32Rules) Reset() { + *x = SFixed32Rules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SFixed32Rules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SFixed32Rules) ProtoMessage() {} + +func (x *SFixed32Rules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SFixed32Rules.ProtoReflect.Descriptor instead. +func (*SFixed32Rules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{11} +} + +func (x *SFixed32Rules) GetConst() int32 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *SFixed32Rules) GetLt() int32 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *SFixed32Rules) GetLte() int32 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *SFixed32Rules) GetGt() int32 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *SFixed32Rules) GetGte() int32 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *SFixed32Rules) GetIn() []int32 { + if x != nil { + return x.In + } + return nil +} + +func (x *SFixed32Rules) GetNotIn() []int32 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *SFixed32Rules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// SFixed64Rules describes the constraints applied to `sfixed64` values +type SFixed64Rules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *int64 `protobuf:"fixed64,1,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *int64 `protobuf:"fixed64,2,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than or equal to the + // specified value, inclusive + Lte *int64 `protobuf:"fixed64,3,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive. If the value of Gt is larger than a specified Lt or Lte, the + // range is reversed. + Gt *int64 `protobuf:"fixed64,4,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than or equal to the + // specified value, inclusive. If the value of Gte is larger than a + // specified Lt or Lte, the range is reversed. + Gte *int64 `protobuf:"fixed64,5,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []int64 `protobuf:"fixed64,6,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []int64 `protobuf:"fixed64,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *SFixed64Rules) Reset() { + *x = SFixed64Rules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SFixed64Rules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SFixed64Rules) ProtoMessage() {} + +func (x *SFixed64Rules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SFixed64Rules.ProtoReflect.Descriptor instead. +func (*SFixed64Rules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{12} +} + +func (x *SFixed64Rules) GetConst() int64 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *SFixed64Rules) GetLt() int64 { + if x != nil && x.Lt != nil { + return *x.Lt + } + return 0 +} + +func (x *SFixed64Rules) GetLte() int64 { + if x != nil && x.Lte != nil { + return *x.Lte + } + return 0 +} + +func (x *SFixed64Rules) GetGt() int64 { + if x != nil && x.Gt != nil { + return *x.Gt + } + return 0 +} + +func (x *SFixed64Rules) GetGte() int64 { + if x != nil && x.Gte != nil { + return *x.Gte + } + return 0 +} + +func (x *SFixed64Rules) GetIn() []int64 { + if x != nil { + return x.In + } + return nil +} + +func (x *SFixed64Rules) GetNotIn() []int64 { + if x != nil { + return x.NotIn + } + return nil +} + +func (x *SFixed64Rules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// BoolRules describes the constraints applied to `bool` values +type BoolRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *bool `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` +} + +func (x *BoolRules) Reset() { + *x = BoolRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BoolRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BoolRules) ProtoMessage() {} + +func (x *BoolRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BoolRules.ProtoReflect.Descriptor instead. +func (*BoolRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{13} +} + +func (x *BoolRules) GetConst() bool { + if x != nil && x.Const != nil { + return *x.Const + } + return false +} + +// StringRules describe the constraints applied to `string` values +type StringRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *string `protobuf:"bytes,1,opt,name=const" json:"const,omitempty"` + // Len specifies that this field must be the specified number of + // characters (Unicode code points). Note that the number of + // characters may differ from the number of bytes in the string. + Len *uint64 `protobuf:"varint,19,opt,name=len" json:"len,omitempty"` + // MinLen specifies that this field must be the specified number of + // characters (Unicode code points) at a minimum. Note that the number of + // characters may differ from the number of bytes in the string. + MinLen *uint64 `protobuf:"varint,2,opt,name=min_len,json=minLen" json:"min_len,omitempty"` + // MaxLen specifies that this field must be the specified number of + // characters (Unicode code points) at a maximum. Note that the number of + // characters may differ from the number of bytes in the string. + MaxLen *uint64 `protobuf:"varint,3,opt,name=max_len,json=maxLen" json:"max_len,omitempty"` + // LenBytes specifies that this field must be the specified number of bytes + LenBytes *uint64 `protobuf:"varint,20,opt,name=len_bytes,json=lenBytes" json:"len_bytes,omitempty"` + // MinBytes specifies that this field must be the specified number of bytes + // at a minimum + MinBytes *uint64 `protobuf:"varint,4,opt,name=min_bytes,json=minBytes" json:"min_bytes,omitempty"` + // MaxBytes specifies that this field must be the specified number of bytes + // at a maximum + MaxBytes *uint64 `protobuf:"varint,5,opt,name=max_bytes,json=maxBytes" json:"max_bytes,omitempty"` + // Pattern specifies that this field must match against the specified + // regular expression (RE2 syntax). The included expression should elide + // any delimiters. + Pattern *string `protobuf:"bytes,6,opt,name=pattern" json:"pattern,omitempty"` + // Prefix specifies that this field must have the specified substring at + // the beginning of the string. + Prefix *string `protobuf:"bytes,7,opt,name=prefix" json:"prefix,omitempty"` + // Suffix specifies that this field must have the specified substring at + // the end of the string. + Suffix *string `protobuf:"bytes,8,opt,name=suffix" json:"suffix,omitempty"` + // Contains specifies that this field must have the specified substring + // anywhere in the string. + Contains *string `protobuf:"bytes,9,opt,name=contains" json:"contains,omitempty"` + // NotContains specifies that this field cannot have the specified substring + // anywhere in the string. + NotContains *string `protobuf:"bytes,23,opt,name=not_contains,json=notContains" json:"not_contains,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []string `protobuf:"bytes,10,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []string `protobuf:"bytes,11,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // WellKnown rules provide advanced constraints against common string + // patterns + // + // Types that are assignable to WellKnown: + // + // *StringRules_Email + // *StringRules_Hostname + // *StringRules_Ip + // *StringRules_Ipv4 + // *StringRules_Ipv6 + // *StringRules_Uri + // *StringRules_UriRef + // *StringRules_Address + // *StringRules_Uuid + // *StringRules_WellKnownRegex + WellKnown isStringRules_WellKnown `protobuf_oneof:"well_known"` + // This applies to regexes HTTP_HEADER_NAME and HTTP_HEADER_VALUE to enable + // strict header validation. + // By default, this is true, and HTTP header validations are RFC-compliant. + // Setting to false will enable a looser validations that only disallows + // \r\n\0 characters, which can be used to bypass header matching rules. + Strict *bool `protobuf:"varint,25,opt,name=strict,def=1" json:"strict,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,26,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +// Default values for StringRules fields. +const ( + Default_StringRules_Strict = bool(true) +) + +func (x *StringRules) Reset() { + *x = StringRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StringRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StringRules) ProtoMessage() {} + +func (x *StringRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StringRules.ProtoReflect.Descriptor instead. +func (*StringRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{14} +} + +func (x *StringRules) GetConst() string { + if x != nil && x.Const != nil { + return *x.Const + } + return "" +} + +func (x *StringRules) GetLen() uint64 { + if x != nil && x.Len != nil { + return *x.Len + } + return 0 +} + +func (x *StringRules) GetMinLen() uint64 { + if x != nil && x.MinLen != nil { + return *x.MinLen + } + return 0 +} + +func (x *StringRules) GetMaxLen() uint64 { + if x != nil && x.MaxLen != nil { + return *x.MaxLen + } + return 0 +} + +func (x *StringRules) GetLenBytes() uint64 { + if x != nil && x.LenBytes != nil { + return *x.LenBytes + } + return 0 +} + +func (x *StringRules) GetMinBytes() uint64 { + if x != nil && x.MinBytes != nil { + return *x.MinBytes + } + return 0 +} + +func (x *StringRules) GetMaxBytes() uint64 { + if x != nil && x.MaxBytes != nil { + return *x.MaxBytes + } + return 0 +} + +func (x *StringRules) GetPattern() string { + if x != nil && x.Pattern != nil { + return *x.Pattern + } + return "" +} + +func (x *StringRules) GetPrefix() string { + if x != nil && x.Prefix != nil { + return *x.Prefix + } + return "" +} + +func (x *StringRules) GetSuffix() string { + if x != nil && x.Suffix != nil { + return *x.Suffix + } + return "" +} + +func (x *StringRules) GetContains() string { + if x != nil && x.Contains != nil { + return *x.Contains + } + return "" +} + +func (x *StringRules) GetNotContains() string { + if x != nil && x.NotContains != nil { + return *x.NotContains + } + return "" +} + +func (x *StringRules) GetIn() []string { + if x != nil { + return x.In + } + return nil +} + +func (x *StringRules) GetNotIn() []string { + if x != nil { + return x.NotIn + } + return nil +} + +func (m *StringRules) GetWellKnown() isStringRules_WellKnown { + if m != nil { + return m.WellKnown + } + return nil +} + +func (x *StringRules) GetEmail() bool { + if x, ok := x.GetWellKnown().(*StringRules_Email); ok { + return x.Email + } + return false +} + +func (x *StringRules) GetHostname() bool { + if x, ok := x.GetWellKnown().(*StringRules_Hostname); ok { + return x.Hostname + } + return false +} + +func (x *StringRules) GetIp() bool { + if x, ok := x.GetWellKnown().(*StringRules_Ip); ok { + return x.Ip + } + return false +} + +func (x *StringRules) GetIpv4() bool { + if x, ok := x.GetWellKnown().(*StringRules_Ipv4); ok { + return x.Ipv4 + } + return false +} + +func (x *StringRules) GetIpv6() bool { + if x, ok := x.GetWellKnown().(*StringRules_Ipv6); ok { + return x.Ipv6 + } + return false +} + +func (x *StringRules) GetUri() bool { + if x, ok := x.GetWellKnown().(*StringRules_Uri); ok { + return x.Uri + } + return false +} + +func (x *StringRules) GetUriRef() bool { + if x, ok := x.GetWellKnown().(*StringRules_UriRef); ok { + return x.UriRef + } + return false +} + +func (x *StringRules) GetAddress() bool { + if x, ok := x.GetWellKnown().(*StringRules_Address); ok { + return x.Address + } + return false +} + +func (x *StringRules) GetUuid() bool { + if x, ok := x.GetWellKnown().(*StringRules_Uuid); ok { + return x.Uuid + } + return false +} + +func (x *StringRules) GetWellKnownRegex() KnownRegex { + if x, ok := x.GetWellKnown().(*StringRules_WellKnownRegex); ok { + return x.WellKnownRegex + } + return KnownRegex_UNKNOWN +} + +func (x *StringRules) GetStrict() bool { + if x != nil && x.Strict != nil { + return *x.Strict + } + return Default_StringRules_Strict +} + +func (x *StringRules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +type isStringRules_WellKnown interface { + isStringRules_WellKnown() +} + +type StringRules_Email struct { + // Email specifies that the field must be a valid email address as + // defined by RFC 5322 + Email bool `protobuf:"varint,12,opt,name=email,oneof"` +} + +type StringRules_Hostname struct { + // Hostname specifies that the field must be a valid hostname as + // defined by RFC 1034. This constraint does not support + // internationalized domain names (IDNs). + Hostname bool `protobuf:"varint,13,opt,name=hostname,oneof"` +} + +type StringRules_Ip struct { + // Ip specifies that the field must be a valid IP (v4 or v6) address. + // Valid IPv6 addresses should not include surrounding square brackets. + Ip bool `protobuf:"varint,14,opt,name=ip,oneof"` +} + +type StringRules_Ipv4 struct { + // Ipv4 specifies that the field must be a valid IPv4 address. + Ipv4 bool `protobuf:"varint,15,opt,name=ipv4,oneof"` +} + +type StringRules_Ipv6 struct { + // Ipv6 specifies that the field must be a valid IPv6 address. Valid + // IPv6 addresses should not include surrounding square brackets. + Ipv6 bool `protobuf:"varint,16,opt,name=ipv6,oneof"` +} + +type StringRules_Uri struct { + // Uri specifies that the field must be a valid, absolute URI as defined + // by RFC 3986 + Uri bool `protobuf:"varint,17,opt,name=uri,oneof"` +} + +type StringRules_UriRef struct { + // UriRef specifies that the field must be a valid URI as defined by RFC + // 3986 and may be relative or absolute. + UriRef bool `protobuf:"varint,18,opt,name=uri_ref,json=uriRef,oneof"` +} + +type StringRules_Address struct { + // Address specifies that the field must be either a valid hostname as + // defined by RFC 1034 (which does not support internationalized domain + // names or IDNs), or it can be a valid IP (v4 or v6). + Address bool `protobuf:"varint,21,opt,name=address,oneof"` +} + +type StringRules_Uuid struct { + // Uuid specifies that the field must be a valid UUID as defined by + // RFC 4122 + Uuid bool `protobuf:"varint,22,opt,name=uuid,oneof"` +} + +type StringRules_WellKnownRegex struct { + // WellKnownRegex specifies a common well known pattern defined as a regex. + WellKnownRegex KnownRegex `protobuf:"varint,24,opt,name=well_known_regex,json=wellKnownRegex,enum=validate.KnownRegex,oneof"` +} + +func (*StringRules_Email) isStringRules_WellKnown() {} + +func (*StringRules_Hostname) isStringRules_WellKnown() {} + +func (*StringRules_Ip) isStringRules_WellKnown() {} + +func (*StringRules_Ipv4) isStringRules_WellKnown() {} + +func (*StringRules_Ipv6) isStringRules_WellKnown() {} + +func (*StringRules_Uri) isStringRules_WellKnown() {} + +func (*StringRules_UriRef) isStringRules_WellKnown() {} + +func (*StringRules_Address) isStringRules_WellKnown() {} + +func (*StringRules_Uuid) isStringRules_WellKnown() {} + +func (*StringRules_WellKnownRegex) isStringRules_WellKnown() {} + +// BytesRules describe the constraints applied to `bytes` values +type BytesRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const []byte `protobuf:"bytes,1,opt,name=const" json:"const,omitempty"` + // Len specifies that this field must be the specified number of bytes + Len *uint64 `protobuf:"varint,13,opt,name=len" json:"len,omitempty"` + // MinLen specifies that this field must be the specified number of bytes + // at a minimum + MinLen *uint64 `protobuf:"varint,2,opt,name=min_len,json=minLen" json:"min_len,omitempty"` + // MaxLen specifies that this field must be the specified number of bytes + // at a maximum + MaxLen *uint64 `protobuf:"varint,3,opt,name=max_len,json=maxLen" json:"max_len,omitempty"` + // Pattern specifies that this field must match against the specified + // regular expression (RE2 syntax). The included expression should elide + // any delimiters. + Pattern *string `protobuf:"bytes,4,opt,name=pattern" json:"pattern,omitempty"` + // Prefix specifies that this field must have the specified bytes at the + // beginning of the string. + Prefix []byte `protobuf:"bytes,5,opt,name=prefix" json:"prefix,omitempty"` + // Suffix specifies that this field must have the specified bytes at the + // end of the string. + Suffix []byte `protobuf:"bytes,6,opt,name=suffix" json:"suffix,omitempty"` + // Contains specifies that this field must have the specified bytes + // anywhere in the string. + Contains []byte `protobuf:"bytes,7,opt,name=contains" json:"contains,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In [][]byte `protobuf:"bytes,8,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn [][]byte `protobuf:"bytes,9,rep,name=not_in,json=notIn" json:"not_in,omitempty"` + // WellKnown rules provide advanced constraints against common byte + // patterns + // + // Types that are assignable to WellKnown: + // + // *BytesRules_Ip + // *BytesRules_Ipv4 + // *BytesRules_Ipv6 + WellKnown isBytesRules_WellKnown `protobuf_oneof:"well_known"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,14,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *BytesRules) Reset() { + *x = BytesRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BytesRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BytesRules) ProtoMessage() {} + +func (x *BytesRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BytesRules.ProtoReflect.Descriptor instead. +func (*BytesRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{15} +} + +func (x *BytesRules) GetConst() []byte { + if x != nil { + return x.Const + } + return nil +} + +func (x *BytesRules) GetLen() uint64 { + if x != nil && x.Len != nil { + return *x.Len + } + return 0 +} + +func (x *BytesRules) GetMinLen() uint64 { + if x != nil && x.MinLen != nil { + return *x.MinLen + } + return 0 +} + +func (x *BytesRules) GetMaxLen() uint64 { + if x != nil && x.MaxLen != nil { + return *x.MaxLen + } + return 0 +} + +func (x *BytesRules) GetPattern() string { + if x != nil && x.Pattern != nil { + return *x.Pattern + } + return "" +} + +func (x *BytesRules) GetPrefix() []byte { + if x != nil { + return x.Prefix + } + return nil +} + +func (x *BytesRules) GetSuffix() []byte { + if x != nil { + return x.Suffix + } + return nil +} + +func (x *BytesRules) GetContains() []byte { + if x != nil { + return x.Contains + } + return nil +} + +func (x *BytesRules) GetIn() [][]byte { + if x != nil { + return x.In + } + return nil +} + +func (x *BytesRules) GetNotIn() [][]byte { + if x != nil { + return x.NotIn + } + return nil +} + +func (m *BytesRules) GetWellKnown() isBytesRules_WellKnown { + if m != nil { + return m.WellKnown + } + return nil +} + +func (x *BytesRules) GetIp() bool { + if x, ok := x.GetWellKnown().(*BytesRules_Ip); ok { + return x.Ip + } + return false +} + +func (x *BytesRules) GetIpv4() bool { + if x, ok := x.GetWellKnown().(*BytesRules_Ipv4); ok { + return x.Ipv4 + } + return false +} + +func (x *BytesRules) GetIpv6() bool { + if x, ok := x.GetWellKnown().(*BytesRules_Ipv6); ok { + return x.Ipv6 + } + return false +} + +func (x *BytesRules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +type isBytesRules_WellKnown interface { + isBytesRules_WellKnown() +} + +type BytesRules_Ip struct { + // Ip specifies that the field must be a valid IP (v4 or v6) address in + // byte format + Ip bool `protobuf:"varint,10,opt,name=ip,oneof"` +} + +type BytesRules_Ipv4 struct { + // Ipv4 specifies that the field must be a valid IPv4 address in byte + // format + Ipv4 bool `protobuf:"varint,11,opt,name=ipv4,oneof"` +} + +type BytesRules_Ipv6 struct { + // Ipv6 specifies that the field must be a valid IPv6 address in byte + // format + Ipv6 bool `protobuf:"varint,12,opt,name=ipv6,oneof"` +} + +func (*BytesRules_Ip) isBytesRules_WellKnown() {} + +func (*BytesRules_Ipv4) isBytesRules_WellKnown() {} + +func (*BytesRules_Ipv6) isBytesRules_WellKnown() {} + +// EnumRules describe the constraints applied to enum values +type EnumRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Const specifies that this field must be exactly the specified value + Const *int32 `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` + // DefinedOnly specifies that this field must be only one of the defined + // values for this enum, failing on any undefined value. + DefinedOnly *bool `protobuf:"varint,2,opt,name=defined_only,json=definedOnly" json:"defined_only,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []int32 `protobuf:"varint,3,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []int32 `protobuf:"varint,4,rep,name=not_in,json=notIn" json:"not_in,omitempty"` +} + +func (x *EnumRules) Reset() { + *x = EnumRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnumRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnumRules) ProtoMessage() {} + +func (x *EnumRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EnumRules.ProtoReflect.Descriptor instead. +func (*EnumRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{16} +} + +func (x *EnumRules) GetConst() int32 { + if x != nil && x.Const != nil { + return *x.Const + } + return 0 +} + +func (x *EnumRules) GetDefinedOnly() bool { + if x != nil && x.DefinedOnly != nil { + return *x.DefinedOnly + } + return false +} + +func (x *EnumRules) GetIn() []int32 { + if x != nil { + return x.In + } + return nil +} + +func (x *EnumRules) GetNotIn() []int32 { + if x != nil { + return x.NotIn + } + return nil +} + +// MessageRules describe the constraints applied to embedded message values. +// For message-type fields, validation is performed recursively. +type MessageRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Skip specifies that the validation rules of this field should not be + // evaluated + Skip *bool `protobuf:"varint,1,opt,name=skip" json:"skip,omitempty"` + // Required specifies that this field must be set + Required *bool `protobuf:"varint,2,opt,name=required" json:"required,omitempty"` +} + +func (x *MessageRules) Reset() { + *x = MessageRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MessageRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MessageRules) ProtoMessage() {} + +func (x *MessageRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MessageRules.ProtoReflect.Descriptor instead. +func (*MessageRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{17} +} + +func (x *MessageRules) GetSkip() bool { + if x != nil && x.Skip != nil { + return *x.Skip + } + return false +} + +func (x *MessageRules) GetRequired() bool { + if x != nil && x.Required != nil { + return *x.Required + } + return false +} + +// RepeatedRules describe the constraints applied to `repeated` values +type RepeatedRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // MinItems specifies that this field must have the specified number of + // items at a minimum + MinItems *uint64 `protobuf:"varint,1,opt,name=min_items,json=minItems" json:"min_items,omitempty"` + // MaxItems specifies that this field must have the specified number of + // items at a maximum + MaxItems *uint64 `protobuf:"varint,2,opt,name=max_items,json=maxItems" json:"max_items,omitempty"` + // Unique specifies that all elements in this field must be unique. This + // constraint is only applicable to scalar and enum types (messages are not + // supported). + Unique *bool `protobuf:"varint,3,opt,name=unique" json:"unique,omitempty"` + // Items specifies the constraints to be applied to each item in the field. + // Repeated message fields will still execute validation against each item + // unless skip is specified here. + Items *FieldRules `protobuf:"bytes,4,opt,name=items" json:"items,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,5,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *RepeatedRules) Reset() { + *x = RepeatedRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RepeatedRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepeatedRules) ProtoMessage() {} + +func (x *RepeatedRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RepeatedRules.ProtoReflect.Descriptor instead. +func (*RepeatedRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{18} +} + +func (x *RepeatedRules) GetMinItems() uint64 { + if x != nil && x.MinItems != nil { + return *x.MinItems + } + return 0 +} + +func (x *RepeatedRules) GetMaxItems() uint64 { + if x != nil && x.MaxItems != nil { + return *x.MaxItems + } + return 0 +} + +func (x *RepeatedRules) GetUnique() bool { + if x != nil && x.Unique != nil { + return *x.Unique + } + return false +} + +func (x *RepeatedRules) GetItems() *FieldRules { + if x != nil { + return x.Items + } + return nil +} + +func (x *RepeatedRules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// MapRules describe the constraints applied to `map` values +type MapRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // MinPairs specifies that this field must have the specified number of + // KVs at a minimum + MinPairs *uint64 `protobuf:"varint,1,opt,name=min_pairs,json=minPairs" json:"min_pairs,omitempty"` + // MaxPairs specifies that this field must have the specified number of + // KVs at a maximum + MaxPairs *uint64 `protobuf:"varint,2,opt,name=max_pairs,json=maxPairs" json:"max_pairs,omitempty"` + // NoSparse specifies values in this field cannot be unset. This only + // applies to map's with message value types. + NoSparse *bool `protobuf:"varint,3,opt,name=no_sparse,json=noSparse" json:"no_sparse,omitempty"` + // Keys specifies the constraints to be applied to each key in the field. + Keys *FieldRules `protobuf:"bytes,4,opt,name=keys" json:"keys,omitempty"` + // Values specifies the constraints to be applied to the value of each key + // in the field. Message values will still have their validations evaluated + // unless skip is specified here. + Values *FieldRules `protobuf:"bytes,5,opt,name=values" json:"values,omitempty"` + // IgnoreEmpty specifies that the validation rules of this field should be + // evaluated only if the field is not empty + IgnoreEmpty *bool `protobuf:"varint,6,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` +} + +func (x *MapRules) Reset() { + *x = MapRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MapRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MapRules) ProtoMessage() {} + +func (x *MapRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MapRules.ProtoReflect.Descriptor instead. +func (*MapRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{19} +} + +func (x *MapRules) GetMinPairs() uint64 { + if x != nil && x.MinPairs != nil { + return *x.MinPairs + } + return 0 +} + +func (x *MapRules) GetMaxPairs() uint64 { + if x != nil && x.MaxPairs != nil { + return *x.MaxPairs + } + return 0 +} + +func (x *MapRules) GetNoSparse() bool { + if x != nil && x.NoSparse != nil { + return *x.NoSparse + } + return false +} + +func (x *MapRules) GetKeys() *FieldRules { + if x != nil { + return x.Keys + } + return nil +} + +func (x *MapRules) GetValues() *FieldRules { + if x != nil { + return x.Values + } + return nil +} + +func (x *MapRules) GetIgnoreEmpty() bool { + if x != nil && x.IgnoreEmpty != nil { + return *x.IgnoreEmpty + } + return false +} + +// AnyRules describe constraints applied exclusively to the +// `google.protobuf.Any` well-known type +type AnyRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required specifies that this field must be set + Required *bool `protobuf:"varint,1,opt,name=required" json:"required,omitempty"` + // In specifies that this field's `type_url` must be equal to one of the + // specified values. + In []string `protobuf:"bytes,2,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field's `type_url` must not be equal to any of + // the specified values. + NotIn []string `protobuf:"bytes,3,rep,name=not_in,json=notIn" json:"not_in,omitempty"` +} + +func (x *AnyRules) Reset() { + *x = AnyRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AnyRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnyRules) ProtoMessage() {} + +func (x *AnyRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnyRules.ProtoReflect.Descriptor instead. +func (*AnyRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{20} +} + +func (x *AnyRules) GetRequired() bool { + if x != nil && x.Required != nil { + return *x.Required + } + return false +} + +func (x *AnyRules) GetIn() []string { + if x != nil { + return x.In + } + return nil +} + +func (x *AnyRules) GetNotIn() []string { + if x != nil { + return x.NotIn + } + return nil +} + +// DurationRules describe the constraints applied exclusively to the +// `google.protobuf.Duration` well-known type +type DurationRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required specifies that this field must be set + Required *bool `protobuf:"varint,1,opt,name=required" json:"required,omitempty"` + // Const specifies that this field must be exactly the specified value + Const *durationpb.Duration `protobuf:"bytes,2,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *durationpb.Duration `protobuf:"bytes,3,opt,name=lt" json:"lt,omitempty"` + // Lt specifies that this field must be less than the specified value, + // inclusive + Lte *durationpb.Duration `protobuf:"bytes,4,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive + Gt *durationpb.Duration `protobuf:"bytes,5,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than the specified value, + // inclusive + Gte *durationpb.Duration `protobuf:"bytes,6,opt,name=gte" json:"gte,omitempty"` + // In specifies that this field must be equal to one of the specified + // values + In []*durationpb.Duration `protobuf:"bytes,7,rep,name=in" json:"in,omitempty"` + // NotIn specifies that this field cannot be equal to one of the specified + // values + NotIn []*durationpb.Duration `protobuf:"bytes,8,rep,name=not_in,json=notIn" json:"not_in,omitempty"` +} + +func (x *DurationRules) Reset() { + *x = DurationRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DurationRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DurationRules) ProtoMessage() {} + +func (x *DurationRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DurationRules.ProtoReflect.Descriptor instead. +func (*DurationRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{21} +} + +func (x *DurationRules) GetRequired() bool { + if x != nil && x.Required != nil { + return *x.Required + } + return false +} + +func (x *DurationRules) GetConst() *durationpb.Duration { + if x != nil { + return x.Const + } + return nil +} + +func (x *DurationRules) GetLt() *durationpb.Duration { + if x != nil { + return x.Lt + } + return nil +} + +func (x *DurationRules) GetLte() *durationpb.Duration { + if x != nil { + return x.Lte + } + return nil +} + +func (x *DurationRules) GetGt() *durationpb.Duration { + if x != nil { + return x.Gt + } + return nil +} + +func (x *DurationRules) GetGte() *durationpb.Duration { + if x != nil { + return x.Gte + } + return nil +} + +func (x *DurationRules) GetIn() []*durationpb.Duration { + if x != nil { + return x.In + } + return nil +} + +func (x *DurationRules) GetNotIn() []*durationpb.Duration { + if x != nil { + return x.NotIn + } + return nil +} + +// TimestampRules describe the constraints applied exclusively to the +// `google.protobuf.Timestamp` well-known type +type TimestampRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required specifies that this field must be set + Required *bool `protobuf:"varint,1,opt,name=required" json:"required,omitempty"` + // Const specifies that this field must be exactly the specified value + Const *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=const" json:"const,omitempty"` + // Lt specifies that this field must be less than the specified value, + // exclusive + Lt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=lt" json:"lt,omitempty"` + // Lte specifies that this field must be less than the specified value, + // inclusive + Lte *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=lte" json:"lte,omitempty"` + // Gt specifies that this field must be greater than the specified value, + // exclusive + Gt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=gt" json:"gt,omitempty"` + // Gte specifies that this field must be greater than the specified value, + // inclusive + Gte *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=gte" json:"gte,omitempty"` + // LtNow specifies that this must be less than the current time. LtNow + // can only be used with the Within rule. + LtNow *bool `protobuf:"varint,7,opt,name=lt_now,json=ltNow" json:"lt_now,omitempty"` + // GtNow specifies that this must be greater than the current time. GtNow + // can only be used with the Within rule. + GtNow *bool `protobuf:"varint,8,opt,name=gt_now,json=gtNow" json:"gt_now,omitempty"` + // Within specifies that this field must be within this duration of the + // current time. This constraint can be used alone or with the LtNow and + // GtNow rules. + Within *durationpb.Duration `protobuf:"bytes,9,opt,name=within" json:"within,omitempty"` +} + +func (x *TimestampRules) Reset() { + *x = TimestampRules{} + if protoimpl.UnsafeEnabled { + mi := &file_validate_validate_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TimestampRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TimestampRules) ProtoMessage() {} + +func (x *TimestampRules) ProtoReflect() protoreflect.Message { + mi := &file_validate_validate_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TimestampRules.ProtoReflect.Descriptor instead. +func (*TimestampRules) Descriptor() ([]byte, []int) { + return file_validate_validate_proto_rawDescGZIP(), []int{22} +} + +func (x *TimestampRules) GetRequired() bool { + if x != nil && x.Required != nil { + return *x.Required + } + return false +} + +func (x *TimestampRules) GetConst() *timestamppb.Timestamp { + if x != nil { + return x.Const + } + return nil +} + +func (x *TimestampRules) GetLt() *timestamppb.Timestamp { + if x != nil { + return x.Lt + } + return nil +} + +func (x *TimestampRules) GetLte() *timestamppb.Timestamp { + if x != nil { + return x.Lte + } + return nil +} + +func (x *TimestampRules) GetGt() *timestamppb.Timestamp { + if x != nil { + return x.Gt + } + return nil +} + +func (x *TimestampRules) GetGte() *timestamppb.Timestamp { + if x != nil { + return x.Gte + } + return nil +} + +func (x *TimestampRules) GetLtNow() bool { + if x != nil && x.LtNow != nil { + return *x.LtNow + } + return false +} + +func (x *TimestampRules) GetGtNow() bool { + if x != nil && x.GtNow != nil { + return *x.GtNow + } + return false +} + +func (x *TimestampRules) GetWithin() *durationpb.Duration { + if x != nil { + return x.Within + } + return nil +} + +var file_validate_validate_proto_extTypes = []protoimpl.ExtensionInfo{ + { + ExtendedType: (*descriptorpb.MessageOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 1071, + Name: "validate.disabled", + Tag: "varint,1071,opt,name=disabled", + Filename: "validate/validate.proto", + }, + { + ExtendedType: (*descriptorpb.MessageOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 1072, + Name: "validate.ignored", + Tag: "varint,1072,opt,name=ignored", + Filename: "validate/validate.proto", + }, + { + ExtendedType: (*descriptorpb.OneofOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 1071, + Name: "validate.required", + Tag: "varint,1071,opt,name=required", + Filename: "validate/validate.proto", + }, + { + ExtendedType: (*descriptorpb.FieldOptions)(nil), + ExtensionType: (*FieldRules)(nil), + Field: 1071, + Name: "validate.rules", + Tag: "bytes,1071,opt,name=rules", + Filename: "validate/validate.proto", + }, +} + +// Extension fields to descriptorpb.MessageOptions. +var ( + // Disabled nullifies any validation rules for this message, including any + // message fields associated with it that do support validation. + // + // optional bool disabled = 1071; + E_Disabled = &file_validate_validate_proto_extTypes[0] + // Ignore skips generation of validation methods for this message. + // + // optional bool ignored = 1072; + E_Ignored = &file_validate_validate_proto_extTypes[1] +) + +// Extension fields to descriptorpb.OneofOptions. +var ( + // Required ensures that exactly one the field options in a oneof is set; + // validation fails if no fields in the oneof are set. + // + // optional bool required = 1071; + E_Required = &file_validate_validate_proto_extTypes[2] +) + +// Extension fields to descriptorpb.FieldOptions. +var ( + // Rules specify the validations to be performed on this field. By default, + // no validation is performed against a field. + // + // optional validate.FieldRules rules = 1071; + E_Rules = &file_validate_validate_proto_extTypes[3] +) + +var File_validate_validate_proto protoreflect.FileDescriptor + +var file_validate_validate_proto_rawDesc = []byte{ + 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc8, 0x08, 0x0a, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x05, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x65, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x05, + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x2e, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, + 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x12, 0x2c, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x05, 0x69, + 0x6e, 0x74, 0x33, 0x32, 0x12, 0x2c, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x49, + 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x74, + 0x36, 0x34, 0x12, 0x2f, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x49, + 0x6e, 0x74, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, 0x75, 0x69, 0x6e, + 0x74, 0x33, 0x32, 0x12, 0x2f, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x55, + 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, 0x75, 0x69, + 0x6e, 0x74, 0x36, 0x34, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, + 0x53, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, + 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x2e, 0x53, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, + 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x32, 0x0a, 0x07, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, + 0x32, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, + 0x00, 0x52, 0x07, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x12, 0x32, 0x0a, 0x07, 0x66, 0x69, + 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x52, 0x75, + 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x07, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x12, 0x35, + 0x0a, 0x08, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x46, 0x69, 0x78, + 0x65, 0x64, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x08, 0x73, 0x66, 0x69, + 0x78, 0x65, 0x64, 0x33, 0x32, 0x12, 0x35, 0x0a, 0x08, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, + 0x34, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x2e, 0x53, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x48, 0x00, 0x52, 0x08, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x12, 0x29, 0x0a, 0x04, + 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, + 0x00, 0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6c, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, + 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x2c, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, + 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x04, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x10, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, + 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x04, 0x65, 0x6e, 0x75, + 0x6d, 0x12, 0x35, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x12, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x52, + 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x08, + 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x03, 0x6d, 0x61, 0x70, 0x18, + 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x2e, 0x4d, 0x61, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x03, 0x6d, 0x61, 0x70, + 0x12, 0x26, 0x0a, 0x03, 0x61, 0x6e, 0x79, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x75, 0x6c, 0x65, + 0x73, 0x48, 0x00, 0x52, 0x03, 0x61, 0x6e, 0x79, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, + 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x16, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, + 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x02, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x02, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x02, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x02, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x02, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, + 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x02, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, + 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, + 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb1, 0x01, 0x0a, 0x0b, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x52, + 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, + 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, + 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x01, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, + 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x01, 0x52, 0x05, + 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, + 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, + 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x49, 0x6e, 0x74, + 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, + 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, + 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x67, 0x74, 0x12, + 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x67, 0x74, + 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x05, 0x52, 0x02, 0x69, + 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x05, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, + 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, + 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb0, 0x01, 0x0a, 0x0a, + 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x6c, 0x74, + 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6c, + 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, + 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x03, + 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb1, + 0x01, 0x0a, 0x0b, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, + 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, + 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, + 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0xb1, 0x01, 0x0a, 0x0b, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, + 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x04, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, + 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x04, 0x52, 0x05, 0x6e, 0x6f, + 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, + 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, + 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb1, 0x01, 0x0a, 0x0b, 0x53, 0x49, 0x6e, 0x74, 0x33, + 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, + 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x11, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, + 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x11, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, + 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x11, 0x52, 0x03, 0x67, 0x74, 0x65, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x11, 0x52, 0x02, 0x69, 0x6e, + 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x11, + 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, + 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb1, 0x01, 0x0a, 0x0b, 0x53, + 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x12, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x12, 0x52, 0x02, 0x6c, 0x74, + 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x12, 0x52, 0x03, 0x6c, + 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x12, 0x52, 0x02, + 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x12, 0x52, + 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x12, + 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x12, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb2, + 0x01, 0x0a, 0x0c, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x07, 0x52, 0x05, + 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x07, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x07, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x07, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x07, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x07, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, + 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x07, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, + 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x22, 0xb2, 0x01, 0x0a, 0x0c, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x52, + 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x06, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x06, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x06, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, + 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x06, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, + 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x06, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x06, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, + 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x06, 0x52, 0x05, + 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, + 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, + 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb3, 0x01, 0x0a, 0x0d, 0x53, 0x46, 0x69, + 0x78, 0x65, 0x64, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x02, 0x6c, 0x74, + 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x03, 0x6c, + 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x02, + 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0f, 0x52, + 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0f, + 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x0f, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb3, + 0x01, 0x0a, 0x0d, 0x53, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x10, 0x52, + 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x10, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x10, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x10, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x10, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x10, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, + 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x10, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, + 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, + 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x22, 0x21, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x75, 0x6c, 0x65, + 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x22, 0xd4, 0x05, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x6c, 0x65, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6c, 0x65, 0x6e, 0x12, + 0x17, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x06, 0x6d, 0x69, 0x6e, 0x4c, 0x65, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, + 0x6c, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x4c, 0x65, + 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x65, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x14, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6c, 0x65, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, + 0x0a, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x08, 0x6d, 0x69, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, + 0x61, 0x78, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, + 0x6d, 0x61, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, + 0x65, 0x72, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, + 0x72, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, + 0x66, 0x66, 0x69, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x75, 0x66, 0x66, + 0x69, 0x78, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x21, + 0x0a, 0x0c, 0x6e, 0x6f, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x17, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x0b, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, + 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, + 0x12, 0x1c, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, + 0x0a, 0x02, 0x69, 0x70, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x02, 0x69, 0x70, + 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, + 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36, 0x18, 0x10, + 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, 0x12, 0x12, 0x0a, 0x03, + 0x75, 0x72, 0x69, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x03, 0x75, 0x72, 0x69, + 0x12, 0x19, 0x0a, 0x07, 0x75, 0x72, 0x69, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x12, 0x20, 0x01, 0x28, + 0x08, 0x48, 0x00, 0x52, 0x06, 0x75, 0x72, 0x69, 0x52, 0x65, 0x66, 0x12, 0x1a, 0x0a, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, + 0x16, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x40, 0x0a, + 0x10, 0x77, 0x65, 0x6c, 0x6c, 0x5f, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x65, + 0x78, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x2e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x48, 0x00, 0x52, + 0x0e, 0x77, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, + 0x1c, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x3a, + 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x12, 0x21, 0x0a, + 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x1a, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x42, 0x0c, 0x0a, 0x0a, 0x77, 0x65, 0x6c, 0x6c, 0x5f, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x22, 0xe2, + 0x02, 0x0a, 0x0a, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, + 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x65, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x03, 0x6c, 0x65, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x6e, 0x4c, 0x65, 0x6e, 0x12, 0x17, + 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x06, 0x6d, 0x61, 0x78, 0x4c, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, + 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, + 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, 0x66, + 0x66, 0x69, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, + 0x78, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, + 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x6e, + 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x10, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, + 0x48, 0x00, 0x52, 0x02, 0x69, 0x70, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x14, 0x0a, 0x04, + 0x69, 0x70, 0x76, 0x36, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, + 0x76, 0x36, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, + 0x74, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x0c, 0x0a, 0x0a, 0x77, 0x65, 0x6c, 0x6c, 0x5f, 0x6b, 0x6e, + 0x6f, 0x77, 0x6e, 0x22, 0x6b, 0x0a, 0x09, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, + 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x64, 0x65, + 0x66, 0x69, 0x6e, 0x65, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x05, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, + 0x5f, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, + 0x22, 0x3e, 0x0a, 0x0c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6b, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, + 0x73, 0x6b, 0x69, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x22, 0xb0, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6c, + 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x69, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, + 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x6e, + 0x69, 0x71, 0x75, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, + 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x22, 0xdc, 0x01, 0x0a, 0x08, 0x4d, 0x61, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x69, 0x6e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x1b, 0x0a, + 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x08, 0x6d, 0x61, 0x78, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, + 0x5f, 0x73, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, + 0x6f, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x04, 0x6b, 0x65, 0x79, + 0x73, 0x12, 0x2c, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, + 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x4d, 0x0a, 0x08, 0x41, 0x6e, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, + 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, + 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, + 0x6e, 0x22, 0xe9, 0x02, 0x0a, 0x0d, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, + 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, + 0x2f, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x12, 0x29, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x6c, + 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x29, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x02, 0x67, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x67, 0x74, 0x65, + 0x12, 0x29, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x30, 0x0a, 0x06, 0x6e, + 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x22, 0xf3, 0x02, + 0x0a, 0x0e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x05, + 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x2a, + 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x2c, 0x0a, 0x03, 0x6c, 0x74, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x02, 0x67, 0x74, 0x12, 0x2c, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x67, + 0x74, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6c, 0x74, 0x5f, 0x6e, 0x6f, 0x77, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x05, 0x6c, 0x74, 0x4e, 0x6f, 0x77, 0x12, 0x15, 0x0a, 0x06, 0x67, 0x74, 0x5f, + 0x6e, 0x6f, 0x77, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x67, 0x74, 0x4e, 0x6f, 0x77, + 0x12, 0x31, 0x0a, 0x06, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x77, 0x69, 0x74, + 0x68, 0x69, 0x6e, 0x2a, 0x46, 0x0a, 0x0a, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x67, 0x65, + 0x78, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x14, + 0x0a, 0x10, 0x48, 0x54, 0x54, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x4e, 0x41, + 0x4d, 0x45, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x48, 0x54, 0x54, 0x50, 0x5f, 0x48, 0x45, 0x41, + 0x44, 0x45, 0x52, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x02, 0x3a, 0x3c, 0x0a, 0x08, 0x64, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xaf, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x3a, 0x3a, 0x0a, 0x07, 0x69, 0x67, 0x6e, + 0x6f, 0x72, 0x65, 0x64, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb0, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x67, + 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x3a, 0x3a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0xaf, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x64, 0x3a, 0x4a, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xaf, 0x08, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x42, 0x91, 0x01, + 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x42, 0x0d, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x76, 0x6f, + 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, + 0x6e, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0xa2, 0x02, 0x03, 0x56, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x65, 0xca, 0x02, 0x08, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0xe2, + 0x02, 0x14, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x65, +} + +var ( + file_validate_validate_proto_rawDescOnce sync.Once + file_validate_validate_proto_rawDescData = file_validate_validate_proto_rawDesc +) + +func file_validate_validate_proto_rawDescGZIP() []byte { + file_validate_validate_proto_rawDescOnce.Do(func() { + file_validate_validate_proto_rawDescData = protoimpl.X.CompressGZIP(file_validate_validate_proto_rawDescData) + }) + return file_validate_validate_proto_rawDescData +} + +var file_validate_validate_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_validate_validate_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_validate_validate_proto_goTypes = []any{ + (KnownRegex)(0), // 0: validate.KnownRegex + (*FieldRules)(nil), // 1: validate.FieldRules + (*FloatRules)(nil), // 2: validate.FloatRules + (*DoubleRules)(nil), // 3: validate.DoubleRules + (*Int32Rules)(nil), // 4: validate.Int32Rules + (*Int64Rules)(nil), // 5: validate.Int64Rules + (*UInt32Rules)(nil), // 6: validate.UInt32Rules + (*UInt64Rules)(nil), // 7: validate.UInt64Rules + (*SInt32Rules)(nil), // 8: validate.SInt32Rules + (*SInt64Rules)(nil), // 9: validate.SInt64Rules + (*Fixed32Rules)(nil), // 10: validate.Fixed32Rules + (*Fixed64Rules)(nil), // 11: validate.Fixed64Rules + (*SFixed32Rules)(nil), // 12: validate.SFixed32Rules + (*SFixed64Rules)(nil), // 13: validate.SFixed64Rules + (*BoolRules)(nil), // 14: validate.BoolRules + (*StringRules)(nil), // 15: validate.StringRules + (*BytesRules)(nil), // 16: validate.BytesRules + (*EnumRules)(nil), // 17: validate.EnumRules + (*MessageRules)(nil), // 18: validate.MessageRules + (*RepeatedRules)(nil), // 19: validate.RepeatedRules + (*MapRules)(nil), // 20: validate.MapRules + (*AnyRules)(nil), // 21: validate.AnyRules + (*DurationRules)(nil), // 22: validate.DurationRules + (*TimestampRules)(nil), // 23: validate.TimestampRules + (*durationpb.Duration)(nil), // 24: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp + (*descriptorpb.MessageOptions)(nil), // 26: google.protobuf.MessageOptions + (*descriptorpb.OneofOptions)(nil), // 27: google.protobuf.OneofOptions + (*descriptorpb.FieldOptions)(nil), // 28: google.protobuf.FieldOptions +} +var file_validate_validate_proto_depIdxs = []int32{ + 18, // 0: validate.FieldRules.message:type_name -> validate.MessageRules + 2, // 1: validate.FieldRules.float:type_name -> validate.FloatRules + 3, // 2: validate.FieldRules.double:type_name -> validate.DoubleRules + 4, // 3: validate.FieldRules.int32:type_name -> validate.Int32Rules + 5, // 4: validate.FieldRules.int64:type_name -> validate.Int64Rules + 6, // 5: validate.FieldRules.uint32:type_name -> validate.UInt32Rules + 7, // 6: validate.FieldRules.uint64:type_name -> validate.UInt64Rules + 8, // 7: validate.FieldRules.sint32:type_name -> validate.SInt32Rules + 9, // 8: validate.FieldRules.sint64:type_name -> validate.SInt64Rules + 10, // 9: validate.FieldRules.fixed32:type_name -> validate.Fixed32Rules + 11, // 10: validate.FieldRules.fixed64:type_name -> validate.Fixed64Rules + 12, // 11: validate.FieldRules.sfixed32:type_name -> validate.SFixed32Rules + 13, // 12: validate.FieldRules.sfixed64:type_name -> validate.SFixed64Rules + 14, // 13: validate.FieldRules.bool:type_name -> validate.BoolRules + 15, // 14: validate.FieldRules.string:type_name -> validate.StringRules + 16, // 15: validate.FieldRules.bytes:type_name -> validate.BytesRules + 17, // 16: validate.FieldRules.enum:type_name -> validate.EnumRules + 19, // 17: validate.FieldRules.repeated:type_name -> validate.RepeatedRules + 20, // 18: validate.FieldRules.map:type_name -> validate.MapRules + 21, // 19: validate.FieldRules.any:type_name -> validate.AnyRules + 22, // 20: validate.FieldRules.duration:type_name -> validate.DurationRules + 23, // 21: validate.FieldRules.timestamp:type_name -> validate.TimestampRules + 0, // 22: validate.StringRules.well_known_regex:type_name -> validate.KnownRegex + 1, // 23: validate.RepeatedRules.items:type_name -> validate.FieldRules + 1, // 24: validate.MapRules.keys:type_name -> validate.FieldRules + 1, // 25: validate.MapRules.values:type_name -> validate.FieldRules + 24, // 26: validate.DurationRules.const:type_name -> google.protobuf.Duration + 24, // 27: validate.DurationRules.lt:type_name -> google.protobuf.Duration + 24, // 28: validate.DurationRules.lte:type_name -> google.protobuf.Duration + 24, // 29: validate.DurationRules.gt:type_name -> google.protobuf.Duration + 24, // 30: validate.DurationRules.gte:type_name -> google.protobuf.Duration + 24, // 31: validate.DurationRules.in:type_name -> google.protobuf.Duration + 24, // 32: validate.DurationRules.not_in:type_name -> google.protobuf.Duration + 25, // 33: validate.TimestampRules.const:type_name -> google.protobuf.Timestamp + 25, // 34: validate.TimestampRules.lt:type_name -> google.protobuf.Timestamp + 25, // 35: validate.TimestampRules.lte:type_name -> google.protobuf.Timestamp + 25, // 36: validate.TimestampRules.gt:type_name -> google.protobuf.Timestamp + 25, // 37: validate.TimestampRules.gte:type_name -> google.protobuf.Timestamp + 24, // 38: validate.TimestampRules.within:type_name -> google.protobuf.Duration + 26, // 39: validate.disabled:extendee -> google.protobuf.MessageOptions + 26, // 40: validate.ignored:extendee -> google.protobuf.MessageOptions + 27, // 41: validate.required:extendee -> google.protobuf.OneofOptions + 28, // 42: validate.rules:extendee -> google.protobuf.FieldOptions + 1, // 43: validate.rules:type_name -> validate.FieldRules + 44, // [44:44] is the sub-list for method output_type + 44, // [44:44] is the sub-list for method input_type + 43, // [43:44] is the sub-list for extension type_name + 39, // [39:43] is the sub-list for extension extendee + 0, // [0:39] is the sub-list for field type_name +} + +func init() { file_validate_validate_proto_init() } +func file_validate_validate_proto_init() { + if File_validate_validate_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_validate_validate_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*FieldRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*FloatRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*DoubleRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*Int32Rules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*Int64Rules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[5].Exporter = func(v any, i int) any { + switch v := v.(*UInt32Rules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[6].Exporter = func(v any, i int) any { + switch v := v.(*UInt64Rules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[7].Exporter = func(v any, i int) any { + switch v := v.(*SInt32Rules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[8].Exporter = func(v any, i int) any { + switch v := v.(*SInt64Rules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[9].Exporter = func(v any, i int) any { + switch v := v.(*Fixed32Rules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[10].Exporter = func(v any, i int) any { + switch v := v.(*Fixed64Rules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[11].Exporter = func(v any, i int) any { + switch v := v.(*SFixed32Rules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[12].Exporter = func(v any, i int) any { + switch v := v.(*SFixed64Rules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[13].Exporter = func(v any, i int) any { + switch v := v.(*BoolRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[14].Exporter = func(v any, i int) any { + switch v := v.(*StringRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[15].Exporter = func(v any, i int) any { + switch v := v.(*BytesRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[16].Exporter = func(v any, i int) any { + switch v := v.(*EnumRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[17].Exporter = func(v any, i int) any { + switch v := v.(*MessageRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[18].Exporter = func(v any, i int) any { + switch v := v.(*RepeatedRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[19].Exporter = func(v any, i int) any { + switch v := v.(*MapRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[20].Exporter = func(v any, i int) any { + switch v := v.(*AnyRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[21].Exporter = func(v any, i int) any { + switch v := v.(*DurationRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validate_validate_proto_msgTypes[22].Exporter = func(v any, i int) any { + switch v := v.(*TimestampRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_validate_validate_proto_msgTypes[0].OneofWrappers = []any{ + (*FieldRules_Float)(nil), + (*FieldRules_Double)(nil), + (*FieldRules_Int32)(nil), + (*FieldRules_Int64)(nil), + (*FieldRules_Uint32)(nil), + (*FieldRules_Uint64)(nil), + (*FieldRules_Sint32)(nil), + (*FieldRules_Sint64)(nil), + (*FieldRules_Fixed32)(nil), + (*FieldRules_Fixed64)(nil), + (*FieldRules_Sfixed32)(nil), + (*FieldRules_Sfixed64)(nil), + (*FieldRules_Bool)(nil), + (*FieldRules_String_)(nil), + (*FieldRules_Bytes)(nil), + (*FieldRules_Enum)(nil), + (*FieldRules_Repeated)(nil), + (*FieldRules_Map)(nil), + (*FieldRules_Any)(nil), + (*FieldRules_Duration)(nil), + (*FieldRules_Timestamp)(nil), + } + file_validate_validate_proto_msgTypes[14].OneofWrappers = []any{ + (*StringRules_Email)(nil), + (*StringRules_Hostname)(nil), + (*StringRules_Ip)(nil), + (*StringRules_Ipv4)(nil), + (*StringRules_Ipv6)(nil), + (*StringRules_Uri)(nil), + (*StringRules_UriRef)(nil), + (*StringRules_Address)(nil), + (*StringRules_Uuid)(nil), + (*StringRules_WellKnownRegex)(nil), + } + file_validate_validate_proto_msgTypes[15].OneofWrappers = []any{ + (*BytesRules_Ip)(nil), + (*BytesRules_Ipv4)(nil), + (*BytesRules_Ipv6)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_validate_validate_proto_rawDesc, + NumEnums: 1, + NumMessages: 23, + NumExtensions: 4, + NumServices: 0, + }, + GoTypes: file_validate_validate_proto_goTypes, + DependencyIndexes: file_validate_validate_proto_depIdxs, + EnumInfos: file_validate_validate_proto_enumTypes, + MessageInfos: file_validate_validate_proto_msgTypes, + ExtensionInfos: file_validate_validate_proto_extTypes, + }.Build() + File_validate_validate_proto = out.File + file_validate_validate_proto_rawDesc = nil + file_validate_validate_proto_goTypes = nil + file_validate_validate_proto_depIdxs = nil +} diff --git a/pkg/gen/validate/validate.swagger.json b/pkg/gen/validate/validate.swagger.json new file mode 100644 index 0000000..44c5594 --- /dev/null +++ b/pkg/gen/validate/validate.swagger.json @@ -0,0 +1,44 @@ +{ + "swagger": "2.0", + "info": { + "title": "validate/validate.proto", + "version": "version not set" + }, + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/pkg/plugins/email/email.go b/pkg/plugins/email/email.go new file mode 100644 index 0000000..f1726b2 --- /dev/null +++ b/pkg/plugins/email/email.go @@ -0,0 +1,24 @@ +package email + +import ( + "os" + "strconv" + "time" +) + +var PLUGIN_NAME = "send_email" + +type Email struct { +} + +func (e *Email) Run(parameters map[string]string) error { + // Get timeout from TASK_TIME_OUT env variable or use 10 seconds as default + timeout := 10 + if timeoutStr := os.Getenv("TASK_TIME_OUT"); timeoutStr != "" { + if parsedTimeout, err := strconv.Atoi(timeoutStr); err == nil { + timeout = parsedTimeout + } + } + time.Sleep(time.Duration(timeout) * time.Second) + return nil +} diff --git a/pkg/plugins/email/email_test.go b/pkg/plugins/email/email_test.go new file mode 100644 index 0000000..0480d42 --- /dev/null +++ b/pkg/plugins/email/email_test.go @@ -0,0 +1,31 @@ +package email + +import ( + "testing" +) + +func TestEmail_Run(t *testing.T) { + e := &Email{} + + testCases := []struct { + name string + parameters map[string]string + }{ + {"Valid parameters", map[string]string{"key": "value"}}, + {"Empty parameters", map[string]string{}}, + {"Multiple parameters", map[string]string{"key1": "value1", "key2": "value2"}}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + err := e.Run(tc.parameters) + + // Test for no error + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + + }) + } +} diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go new file mode 100644 index 0000000..42d4198 --- /dev/null +++ b/pkg/plugins/plugins.go @@ -0,0 +1,24 @@ +package plugins + +import ( + "fmt" + "task/pkg/plugins/email" + "task/pkg/plugins/query" +) + +// Plugin interface defines the Run method for plugins +type Plugin interface { + Run(parameters map[string]string) error +} + +// NewPlugin returns a Plugin interface based on the provided type +func NewPlugin(pluginType string) (Plugin, error) { + switch pluginType { + case email.PLUGIN_NAME: + return &email.Email{}, nil // Assuming Email is a struct that implements Plugin + case query.PLUGIN_NAME: + return &query.Query{}, nil // Assuming Query is a struct that implements Plugin + default: + return nil, fmt.Errorf("unknown plugin type: %s", pluginType) + } +} diff --git a/pkg/plugins/plugins_test.go b/pkg/plugins/plugins_test.go new file mode 100644 index 0000000..a43bc2e --- /dev/null +++ b/pkg/plugins/plugins_test.go @@ -0,0 +1,55 @@ +package plugins + +import ( + "task/pkg/plugins/email" + "task/pkg/plugins/query" + "testing" +) + +func TestNewPlugin(t *testing.T) { + tests := []struct { + name string + pluginType string + want Plugin + wantErr bool + }{ + { + name: "SEND_EMAIL plugin", + pluginType: email.PLUGIN_NAME, + want: &email.Email{}, + wantErr: false, + }, + { + name: "RUN_QUERY plugin", + pluginType: query.PLUGIN_NAME, + want: &query.Query{}, + wantErr: false, + }, + { + name: "Unknown plugin type", + pluginType: "UNKNOWN", + want: nil, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewPlugin(tt.pluginType) + if (err != nil) != tt.wantErr { + t.Errorf("NewPlugin() error = %v, wantErr %v", err, tt.wantErr) + return + } + if tt.wantErr { + return + } + if got == nil { + t.Errorf("NewPlugin() returned nil, want %T", tt.want) + return + } + if _, ok := got.(Plugin); !ok { + t.Errorf("NewPlugin() returned %T, which does not implement Plugin interface", got) + } + }) + } +} diff --git a/pkg/plugins/query/query.go b/pkg/plugins/query/query.go new file mode 100644 index 0000000..398dfb6 --- /dev/null +++ b/pkg/plugins/query/query.go @@ -0,0 +1,33 @@ +package query + +import ( + "fmt" + "math/rand" + "os" + "strconv" + "time" +) + +var PLUGIN_NAME = "run_query" + +type Query struct { +} + +var seededRand *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano())) + +// run_query executes a query and fails 20% of the time +func (q *Query) Run(parameters map[string]string) error { + if seededRand.Float64() < 0.2 { // 20% chance to fail + return fmt.Errorf("query failed") + } + + // Get timeout from TASK_TIME_OUT env variable or use 10 seconds as default + timeout := 10 + if timeoutStr := os.Getenv("TASK_TIME_OUT"); timeoutStr != "" { + if parsedTimeout, err := strconv.Atoi(timeoutStr); err == nil { + timeout = parsedTimeout + } + } + time.Sleep(time.Duration(timeout) * time.Second) + return nil +} diff --git a/pkg/plugins/query/query_test.go b/pkg/plugins/query/query_test.go new file mode 100644 index 0000000..cdb29fc --- /dev/null +++ b/pkg/plugins/query/query_test.go @@ -0,0 +1,46 @@ +package query + +import ( + "testing" + "time" +) + +func TestRun(t *testing.T) { + q := &Query{} + + // Test case for successful execution + t.Run("Successful execution", func(t *testing.T) { + start := time.Now() + err := q.Run(map[string]string{"success": "true"}) + duration := time.Since(start) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + if duration < 3*time.Second { + t.Errorf("Expected execution time of at least 3 seconds, got %v", duration) + } + }) + + // Test case for failure + t.Run("Failure", func(t *testing.T) { + maxRetries := 10 + failureOccurred := false + + for i := 0; i < maxRetries; i++ { + err := q.Run(map[string]string{}) + if err != nil { + failureOccurred = true + if err.Error() != "query failed" { + t.Errorf("Expected 'query failed', got %v", err) + } + break + } + } + + if !failureOccurred { + t.Errorf("Expected at least one failure, but all attempts succeeded") + } + }) +} diff --git a/pkg/worker/cron.go b/pkg/worker/cron.go new file mode 100644 index 0000000..c145f51 --- /dev/null +++ b/pkg/worker/cron.go @@ -0,0 +1,124 @@ +package worker + +import ( + "context" + "database/sql" + "fmt" + "log/slog" + "os" + cloudv1 "task/pkg/gen/cloud/v1" + + "task/pkg/x" + "task/server/repository/model/task" + "time" + + "connectrpc.com/connect" + "github.com/riverqueue/river" + "gorm.io/driver/postgres" + "gorm.io/gorm" +) + +// ReconcileTaskWorkerArgs contains the arguments for the ReconcileTaskWorker. +type ReconcileTaskWorkerArgs struct { + Status int `json:"status"` + URL string +} + +// Kind returns the kind of the task argument. +func (ReconcileTaskWorkerArgs) Kind() string { return "reconcile_tasks" } + +// InsertOpts returns the insertion options for the task. +func (ReconcileTaskWorkerArgs) InsertOpts() river.InsertOpts { + return river.InsertOpts{MaxAttempts: 1} +} + +// ReconcileTaskWorker is the worker implementation for processing and reconciling tasks. +type ReconcileTaskWorker struct { + river.WorkerDefaults[ReconcileTaskWorkerArgs] + Logger *slog.Logger + db *gorm.DB +} + +// Work processes a single reconciliation job for tasks. +// It finds tasks that have been in a specific status for too long and updates them to QUEUED status. +func (w *ReconcileTaskWorker) Work(ctx context.Context, job *river.Job[ReconcileTaskWorkerArgs]) error { + w.Logger = slog.Default().With("worker", "ReconcileTaskWorker") + w.Logger.Info("Starting task reconciliation") + + sqlDB, err := sql.Open("pgx", job.Args.URL) + if err != nil { + return fmt.Errorf("failed to open database connection: %w", err) + } + defer sqlDB.Close() + + db, err := gorm.Open(postgres.New(postgres.Config{ + Conn: sqlDB, + }), &gorm.Config{}) + if err != nil { + return fmt.Errorf("failed to initialize GORM: %w", err) + } + + w.db = db + + runningTasks, err := w.fetchRunningTasks(ctx, job.Args.Status) + if err != nil { + return fmt.Errorf("failed to fetch running tasks: %w", err) + } + + w.Logger.Info("Found running tasks", "count", len(runningTasks)) + + updatedCount, err := w.updateAndQueueTasks(ctx, runningTasks) + if err != nil { + return fmt.Errorf("failed to update and queue tasks: %w", err) + } + + w.Logger.Info("Finished processing tasks", "updated_count", updatedCount) + return nil +} + +func (w *ReconcileTaskWorker) fetchRunningTasks(ctx context.Context, status int) ([]task.Task, error) { + var runningTasks []task.Task + twentyMinutesAgo := time.Now().Add(-time.Duration(x.CRON_TIME) * time.Minute) + + err := w.db.WithContext(ctx). + Where("status = ? AND created_at <= ?", status, twentyMinutesAgo). + Find(&runningTasks).Error + if err != nil { + return nil, fmt.Errorf("failed to query running tasks: %w", err) + } + + return runningTasks, nil +} + +func (w *ReconcileTaskWorker) updateAndQueueTasks(ctx context.Context, tasks []task.Task) (int, error) { + updatedCount := 0 + for _, t := range tasks { + if err := w.updateTaskStatus(ctx, t); err != nil { + w.Logger.Error("Failed to update task status", "task_id", t.ID, "error", err) + continue + } + updatedCount++ + } + return updatedCount, nil +} + +func (w *ReconcileTaskWorker) updateTaskStatus(ctx context.Context, t task.Task) error { + cloud, err := x.CreateClient(os.Getenv("SERVER_ENDPOINT")) + if err != nil { + return fmt.Errorf("failed to create client: %w", err) + } + + req := &cloudv1.UpdateTaskStatusRequest{ + Id: int32(t.ID), + Status: cloudv1.TaskStatusEnum_QUEUED, + Message: "Task has been queued again", + } + + _, err = cloud.UpdateTaskStatus(ctx, connect.NewRequest(req)) + if err != nil { + return fmt.Errorf("failed to update task status: %w", err) + } + + w.Logger.Info("Updated task status to QUEUED", "task_id", t.ID) + return nil +} diff --git a/pkg/worker/error.go b/pkg/worker/error.go new file mode 100644 index 0000000..936ec3a --- /dev/null +++ b/pkg/worker/error.go @@ -0,0 +1,24 @@ +package worker + +import ( + "context" + "fmt" + + "github.com/riverqueue/river" + "github.com/riverqueue/river/rivertype" +) + +type CustomErrorHandler struct{} + +func (*CustomErrorHandler) HandleError(ctx context.Context, job *rivertype.JobRow, err error) *river.ErrorHandlerResult { + fmt.Printf("Job errored with: %s\n", err) + return nil +} + +func (*CustomErrorHandler) HandlePanic(ctx context.Context, job *rivertype.JobRow, panicVal any, trace string) *river.ErrorHandlerResult { + fmt.Printf("Job panicked with: %v\n", panicVal) + fmt.Printf("Job panicked with: %v\n", trace) + + // Either function can also set the job to be immediately cancelled. + return &river.ErrorHandlerResult{SetCancelled: true} +} diff --git a/pkg/worker/worker.go b/pkg/worker/worker.go new file mode 100644 index 0000000..2e89dd5 --- /dev/null +++ b/pkg/worker/worker.go @@ -0,0 +1,133 @@ +package worker + +import ( + "context" + "encoding/json" + "fmt" + "log/slog" + "os" + "strconv" + v1 "task/pkg/gen/cloud/v1" + "task/pkg/gen/cloud/v1/cloudv1connect" + "task/pkg/plugins" + "task/pkg/x" + "task/server/repository/model/task" + "time" + + "connectrpc.com/connect" + "github.com/riverqueue/river" +) + +var cloudClient cloudv1connect.TaskManagementServiceClient + +// TaskArgument represents the argument structure for a task job. +type TaskArgument struct { + Task task.Task `json:"task"` +} + +// Kind returns the kind of the task argument. +func (TaskArgument) Kind() string { return "email_send" } + +// InsertOpts returns the insertion options for the task. +func (TaskArgument) InsertOpts() river.InsertOpts { + return river.InsertOpts{MaxAttempts: 5} +} + +// TaskWorker is the worker implementation for processing tasks. +type TaskWorker struct { + river.WorkerDefaults[TaskArgument] +} + +// Work processes a single task job. +func (w *TaskWorker) Work(ctx context.Context, job *river.Job[TaskArgument]) error { + logger := slog.With("task_id", job.Args.Task.ID, "attempt", job.Attempt) + logger.Info("Starting task processing") + + startTime := time.Now() + defer func() { + duration := time.Since(startTime) + logger.Info("Task processing completed", "duration", duration, "task_type", job.Args.Task.Type) + }() + + if err := updateTaskStatus(ctx, int64(job.Args.Task.ID), v1.TaskStatusEnum_RUNNING, fmt.Sprintf("Task started (Attempt %d)", job.Attempt)); err != nil { + logger.Error("Failed to update task status to RUNNING", "error", err) + return fmt.Errorf("failed to update task status to RUNNING: %w", err) + } + + defer func() { + if r := recover(); r != nil { + logger.Error("Task panicked", "panic", r) + if err := updateTaskStatus(ctx, int64(job.Args.Task.ID), v1.TaskStatusEnum_FAILED, fmt.Sprintf("Task panicked (Attempt %d): %v", job.Attempt, r)); err != nil { + logger.Error("Failed to update task status after panic", "error", err) + } + } + }() + + plugin, err := plugins.NewPlugin(job.Args.Task.Type) + if err != nil { + return w.handleError(ctx, job, logger, "Failed to create plugin", err) + } + + var payloadMap map[string]string + if err := json.Unmarshal([]byte(job.Args.Task.Payload), &payloadMap); err != nil { + return w.handleError(ctx, job, logger, "Failed to unmarshal payload", err) + } + + if err := plugin.Run(payloadMap); err != nil { + return w.handleError(ctx, job, logger, "Error running task", err) + } + + logger.Info("Task completed successfully") + if err := updateTaskStatus(ctx, int64(job.Args.Task.ID), v1.TaskStatusEnum_SUCCEEDED, fmt.Sprintf("Task completed successfully (Attempt %d)", job.Attempt)); err != nil { + logger.Error("Failed to update task status to SUCCEEDED", "error", err) + return fmt.Errorf("failed to update task status to SUCCEEDED: %w", err) + } + + return nil +} + +// handleError is a helper function to handle errors during task processing. +func (w *TaskWorker) handleError(ctx context.Context, job *river.Job[TaskArgument], logger *slog.Logger, message string, err error) error { + logger.Error(message, "error", err) + errorMsg := fmt.Sprintf("%s (Attempt %d): %v", message, job.Attempt, err) + if updateErr := updateTaskStatus(ctx, int64(job.Args.Task.ID), v1.TaskStatusEnum_FAILED, errorMsg); updateErr != nil { + logger.Error("Failed to update task status to FAILED", "error", updateErr) + } + return fmt.Errorf("%s for task %d (Attempt %d): %w", message, job.Args.Task.ID, job.Attempt, err) +} + +// NextRetry determines the time for the next retry attempt. +func (w *TaskWorker) NextRetry(job *river.Job[TaskArgument]) time.Time { + return time.Now().Add(2 * time.Second) +} + +// Timeout sets the maximum duration for a task to complete. +func (w *TaskWorker) Timeout(job *river.Job[TaskArgument]) time.Duration { + timeout := 10 + if timeoutStr := os.Getenv("TASK_TIME_OUT"); timeoutStr != "" { + if parsedTimeout, err := strconv.Atoi(timeoutStr); err == nil { + timeout = parsedTimeout + } + } + + return (time.Duration(timeout) + 5) * time.Second +} + +// updateTaskStatus updates the status of a task using the Task Management Service. +func updateTaskStatus(ctx context.Context, taskID int64, status v1.TaskStatusEnum, message string) error { + client, err := x.CreateClient(os.Getenv("SERVER_ENDPOINT")) + if err != nil { + return fmt.Errorf("failed to create client: %w", err) + } + + _, err = client.UpdateTaskStatus(ctx, connect.NewRequest(&v1.UpdateTaskStatusRequest{ + Id: int32(taskID), + Status: status, + Message: message, + })) + if err != nil { + return fmt.Errorf("failed to update task %d status: %w", taskID, err) + } + + return nil +} diff --git a/pkg/x/x.go b/pkg/x/x.go new file mode 100644 index 0000000..608a70e --- /dev/null +++ b/pkg/x/x.go @@ -0,0 +1,222 @@ +package x + +import ( + "encoding/json" + "fmt" + "log" + "log/slog" + "net/http" + "os" + "time" + + "task/pkg/config" + cloudv1 "task/pkg/gen/cloud/v1" + "task/pkg/gen/cloud/v1/cloudv1connect" + + "connectrpc.com/connect" + "connectrpc.com/otelconnect" + "github.com/joho/godotenv" + "github.com/kelseyhightower/envconfig" + "github.com/olekukonko/tablewriter" + "gopkg.in/yaml.v2" +) + +var CRON_TIME = 30 + +// loadEnv loads environment variables from .env file +func LoadEnv() error { + if err := godotenv.Load(); err != nil { + // Instead of returning an error, we'll just log a message + fmt.Println("No .env file found, proceeding with default values") + } + return nil +} + +// loadConfig processes environment variables into a Config struct +func LoadConfig() (config.Config, error) { + var env config.Config + if err := envconfig.Process("", &env); err != nil { + return env, fmt.Errorf("error loading environment variables: %w", err) + } + return env, nil +} + +// Example function to convert a map[string]string to a JSON string +func ConvertMapToJson(parameters map[string]string) (string, error) { + // Marshal the map into a JSON byte array + jsonBytes, err := json.Marshal(parameters) + if err != nil { + return "", fmt.Errorf("error converting map to JSON: %v", err) + } + + // Convert the byte array to a string and return + return string(jsonBytes), nil +} + +// ConvertJsonToMap converts a JSON string into a map[string]string. +func ConvertJsonToMap(jsonString string) (map[string]string, error) { + var result map[string]string + + // Unmarshal the JSON string into the map + if err := json.Unmarshal([]byte(jsonString), &result); err != nil { + return nil, fmt.Errorf("error converting JSON to map: %v", err) + } + + return result, nil +} + +// GetStatusString converts a status number to its corresponding string representation. +func GetStatusString(status int) string { + switch status { + case 0: + return "QUEUED" + case 1: + return "RUNNING" + case 2: + return "FAILED" + case 3: + return "SUCCEEDED" + default: + return "UNKNOWN" + } +} + +// GetStatusInt converts a status string to its corresponding integer value. +func GetStatusInt(status string) cloudv1.TaskStatusEnum { + switch status { + case "QUEUED": + return cloudv1.TaskStatusEnum_QUEUED + case "RUNNING": + return cloudv1.TaskStatusEnum_RUNNING + case "FAILED": + return cloudv1.TaskStatusEnum_FAILED + case "SUCCEEDED": + return cloudv1.TaskStatusEnum_SUCCEEDED + default: + return cloudv1.TaskStatusEnum_ALL // Indicating an unknown status + } +} + +// CreateClient creates a new TaskManagementServiceClient with an OpenTelemetry interceptor +func CreateClient(address string) (cloudv1connect.TaskManagementServiceClient, error) { + interceptor, err := otelconnect.NewInterceptor() + if err != nil { + return nil, fmt.Errorf("error creating interceptor: %w", err) + } + + slog.Info("Creating TaskManagementServiceClient", "serverURL", address) + return cloudv1connect.NewTaskManagementServiceClient( + http.DefaultClient, + address, + connect.WithInterceptors(interceptor), + ), nil +} + +// printTaskTable prints a single task in a table format +func PrintTaskTable(table *tablewriter.Table, task *cloudv1.Task) { + table.SetHeader([]string{"Field", "Value"}) + table.Append([]string{"ID", fmt.Sprintf("%d", task.Id)}) + table.Append([]string{"Name", task.Name}) + table.Append([]string{"Type", task.Type}) + table.Append([]string{"Status", task.Status.String()}) + table.Append([]string{"Description", task.Description}) + table.Render() +} + +// printTaskListTable prints a list of tasks in a table format +func PrintTaskListTable(table *tablewriter.Table, tasks *cloudv1.TaskList) { + table.SetHeader([]string{"ID", "Name", "Type", "Status", "Description"}) + for _, task := range tasks.Tasks { + table.Append([]string{ + fmt.Sprintf("%d", task.Id), + task.Name, + task.Type, + task.Status.String(), + truncateMessage(task.Description), + }) + } + table.Render() +} + +// printJSON prints data in JSON format +func PrintJSON(data interface{}) error { + jsonData, err := json.MarshalIndent(data, "", " ") + if err != nil { + fmt.Printf("Error marshaling to JSON: %v\n", err) + return err + } + fmt.Println(string(jsonData)) + return nil +} + +// printYAML prints data in YAML format +func PrintYAML(data interface{}) error { + yamlData, err := yaml.Marshal(data) + if err != nil { + fmt.Printf("Error marshaling to YAML: %v\n", err) + return err + } + fmt.Println(string(yamlData)) + return nil +} + +// printTaskHistoryTable prints task history in a table format +func PrintTaskHistoryTable(table *tablewriter.Table, history *cloudv1.GetTaskHistoryResponse) { + table.SetAutoWrapText(false) + table.SetAutoFormatHeaders(true) + table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) + table.SetAlignment(tablewriter.ALIGN_LEFT) + table.SetCenterSeparator("") + table.SetColumnSeparator("") + table.SetRowSeparator("") + table.SetHeaderLine(false) + table.SetBorder(false) + table.SetTablePadding("\t") + table.SetNoWhiteSpace(true) + + table.SetHeader([]string{"ID", "Created At", "Message", "Status"}) + for _, entry := range history.History { + createdAt, _ := time.Parse(time.RFC3339, entry.CreatedAt) + table.Append([]string{ + fmt.Sprintf("%d", entry.Id), + createdAt.Format(time.RFC3339), + truncateMessage(entry.Details), + entry.Status.String(), + }) + } + table.Render() +} + +// Helper function to truncate message to 30 characters +func truncateMessage(message string) string { + if len(message) > 30 { + return message[:27] + "..." + } + return message +} + +// printTable prints data in table format using github.com/olekukonko/tablewriter +func PrintTable(data interface{}) { + table := tablewriter.NewWriter(os.Stdout) + table.SetAutoWrapText(false) + table.SetAutoFormatHeaders(true) + table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) + table.SetAlignment(tablewriter.ALIGN_LEFT) + table.SetCenterSeparator("") + table.SetColumnSeparator("") + table.SetRowSeparator("") + table.SetHeaderLine(false) + table.SetBorder(false) + table.SetTablePadding("\t") + table.SetNoWhiteSpace(true) + + switch v := data.(type) { + case *cloudv1.Task: + PrintTaskTable(table, v) + case *cloudv1.TaskList: + PrintTaskListTable(table, v) + default: + log.Println("Unsupported data type for table format") + fmt.Println("Unsupported data type for table format") + } +} diff --git a/pkg/x/x_test.go b/pkg/x/x_test.go new file mode 100644 index 0000000..09589ac --- /dev/null +++ b/pkg/x/x_test.go @@ -0,0 +1,145 @@ +package x + +import ( + "os" + "reflect" + "testing" +) + +func TestLoadEnv(t *testing.T) { + // Create a temporary .env file for testing + err := os.WriteFile(".env", []byte("TEST_VAR=test_value"), 0644) + if err != nil { + t.Fatalf("Failed to create test .env file: %v", err) + } + defer os.Remove(".env") + + err = LoadEnv() + if err != nil { + t.Errorf("LoadEnv() returned an error: %v", err) + } + + // Check if the environment variable was loaded + if os.Getenv("TEST_VAR") != "test_value" { + t.Errorf("LoadEnv() did not load the environment variable correctly") + } +} + +func TestLoadConfig(t *testing.T) { + // Set test environment variables + os.Setenv("SERVER_PORT", "8080") + os.Setenv("DB_HOST", "localhost") + os.Setenv("DB_PORT", "5432") + os.Setenv("DB_USER", "testuser") + os.Setenv("DB_PASSWORD", "testpass") + os.Setenv("DB_NAME", "testdb") + defer func() { + os.Unsetenv("SERVER_PORT") + os.Unsetenv("DB_HOST") + os.Unsetenv("DB_PORT") + os.Unsetenv("DB_USER") + os.Unsetenv("DB_PASSWORD") + os.Unsetenv("DB_NAME") + }() + + cfg, err := LoadConfig() + if err != nil { + t.Fatalf("LoadConfig() returned an error: %v", err) + } + + // Check if the config was loaded correctly + if cfg.ServerPort != "8080" { + t.Errorf("LoadConfig() ServerPort = %s, want %s", cfg.ServerPort, "8080") + } + if cfg.Database.Host != "localhost" { + t.Errorf("LoadConfig() Database.Host = %s, want %s", cfg.Database.Host, "localhost") + } + if cfg.Database.Port != "5432" { + t.Errorf("LoadConfig() Database.Port = %s, want %s", cfg.Database.Port, "5432") + } + + if cfg.Database.Password != "testpass" { + t.Errorf("LoadConfig() Database.Password = %s, want %s", cfg.Database.Password, "testpass") + } + +} + +func TestConvertMapToJson(t *testing.T) { + input := map[string]string{"key1": "value1", "key2": "value2"} + expected := `{"key1":"value1","key2":"value2"}` + + result, err := ConvertMapToJson(input) + if err != nil { + t.Errorf("ConvertMapToJson() returned an error: %v", err) + } + if result != expected { + t.Errorf("ConvertMapToJson() = %v, want %v", result, expected) + } +} + +func TestConvertJsonToMap(t *testing.T) { + input := `{"key1":"value1","key2":"value2"}` + expected := map[string]string{"key1": "value1", "key2": "value2"} + + result, err := ConvertJsonToMap(input) + if err != nil { + t.Errorf("ConvertJsonToMap() returned an error: %v", err) + } + if !reflect.DeepEqual(result, expected) { + t.Errorf("ConvertJsonToMap() = %v, want %v", result, expected) + } +} + +func TestGetStatusString(t *testing.T) { + tests := []struct { + name string + status int + expected string + }{ + {"Queued", 0, "QUEUED"}, + {"Running", 1, "RUNNING"}, + {"Failed", 2, "FAILED"}, + {"Succeeded", 3, "SUCCEEDED"}, + {"Unknown", 4, "UNKNOWN"}, + {"Negative", -1, "UNKNOWN"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := GetStatusString(tt.status) + if result != tt.expected { + t.Errorf("GetStatusString(%d) = %s, want %s", tt.status, result, tt.expected) + } + }) + } +} + +func TestCreateClient(t *testing.T) { + // Test with default server URL + t.Run("Default Server URL", func(t *testing.T) { + os.Unsetenv("SERVER_ENDPOINT") + client, err := CreateClient("http://task:8080") + if err != nil { + t.Fatalf("CreateClient() returned an error: %v", err) + } + if client == nil { + t.Error("CreateClient() returned nil client") + } + }) + + // Test with custom server URL + t.Run("Custom Server URL", func(t *testing.T) { + os.Setenv("SERVER_ENDPOINT", "http://testserver:9090") + defer os.Unsetenv("SERVER_ENDPOINT") + + client, err := CreateClient("http://testserver:9090") + if err != nil { + t.Fatalf("CreateClient() returned an error: %v", err) + } + if client == nil { + t.Error("CreateClient() returned nil client") + } + // Note: We can't easily check the actual URL used by the client, + // but we can verify that a client was created without errors. + }) +} diff --git a/server/repository/factory.go b/server/repository/factory.go new file mode 100644 index 0000000..ecb1aae --- /dev/null +++ b/server/repository/factory.go @@ -0,0 +1,145 @@ +package repositories + +import ( + "context" + "database/sql" + "fmt" + "log/slog" + "os" + "time" + + cloudv1 "task/pkg/gen/cloud/v1" + "task/pkg/worker" + "task/pkg/x" + interfaces "task/server/repository/interface" + tasks "task/server/repository/model/task" + + "github.com/riverqueue/river" + "github.com/riverqueue/river/riverdriver/riverdatabasesql" + "github.com/riverqueue/river/rivermigrate" + "gorm.io/driver/postgres" + "gorm.io/gorm" +) + +func GetRepository(url string, workerCount int, maxConns int) (interfaces.TaskManagmentInterface, error) { + // Open database connection + + sqlDB, err := sql.Open("pgx", url) + if err != nil { + return nil, err + } + + // Set the maximum number of open connections + sqlDB.SetMaxOpenConns(maxConns) + // Set the maximum number of open connections + sqlDB.SetMaxOpenConns(maxConns) + + // Set the maximum number of idle connections + sqlDB.SetMaxIdleConns(maxConns / 2) + + // Set the maximum lifetime of a connection + sqlDB.SetConnMaxLifetime(time.Hour) + + db, err := gorm.Open(postgres.New(postgres.Config{ + Conn: sqlDB, + }), &gorm.Config{}) + if err != nil { + return nil, err + } + + migrator, err := rivermigrate.New(riverdatabasesql.New(sqlDB), nil) + if err != nil { + return nil, fmt.Errorf("failed to create river migrator: %w", err) + } + + _, err = migrator.Migrate(context.Background(), rivermigrate.DirectionUp, &rivermigrate.MigrateOpts{}) + if err != nil { + panic(err) + } + + // Set up River workers and client + workers := river.NewWorkers() + if err := river.AddWorkerSafely(workers, &worker.TaskWorker{}); err != nil { + return nil, fmt.Errorf("failed to add TaskWorker: %w", err) + } + + if err := river.AddWorkerSafely(workers, &worker.ReconcileTaskWorker{}); err != nil { + return nil, fmt.Errorf("failed to add TaskWorker: %w", err) + } + + // TODO: Add comprehensive documentation + // We added periodic reconciliation jobs to handle stuck tasks. These jobs will: + // 1. Get a list of all stuck tasks + // 2. Change their status to "queued" + // 3. Enqueue them for processing + // Currently, we're making direct DB changes, but ideally, the server should + // implement an API to handle this logic. In the future, these scheduled jobs + // should just call the API instead of modifying the database directly. + + var reconcileTasks = []*river.PeriodicJob{ + river.NewPeriodicJob( + river.PeriodicInterval(time.Duration(x.CRON_TIME)*time.Second), + func() (river.JobArgs, *river.InsertOpts) { + return worker.ReconcileTaskWorkerArgs{ + + Status: int(cloudv1.TaskStatusEnum_RUNNING), + URL: url, + }, nil + }, + &river.PeriodicJobOpts{RunOnStart: true}, + ), + river.NewPeriodicJob( + river.PeriodicInterval(time.Duration(x.CRON_TIME)*time.Second), + func() (river.JobArgs, *river.InsertOpts) { + return worker.ReconcileTaskWorkerArgs{ + Status: int(cloudv1.TaskStatusEnum_QUEUED), + URL: url, + }, nil + }, + &river.PeriodicJobOpts{RunOnStart: true}, + ), + } + + riverClient, err := river.NewClient(riverdatabasesql.New(sqlDB), &river.Config{ + Queues: map[string]river.QueueConfig{ + river.QueueDefault: {MaxWorkers: workerCount}, + }, + Workers: workers, + PeriodicJobs: reconcileTasks, + ErrorHandler: &worker.CustomErrorHandler{}, + Logger: slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})), + }) + if err != nil { + return nil, fmt.Errorf("failed to create River client: %w", err) + } + + // Start River client + if err := riverClient.Start(context.Background()); err != nil { + return nil, fmt.Errorf("failed to start River client: %w", err) + } + + // Perform database migrations + if err = db.AutoMigrate(&tasks.Task{}, &tasks.TaskHistory{}); err != nil { + return nil, fmt.Errorf("failed to run auto migrations: %w", err) + } + + // Create necessary indexes + indexes := []struct { + name string + sql string + }{ + {"idx_task_id_created_at", "CREATE INDEX IF NOT EXISTS idx_task_id_created_at ON task_histories (task_id, created_at DESC)"}, + {"idx_type_status", "CREATE INDEX IF NOT EXISTS idx_type_status ON tasks (type, status)"}, + {"idx_created_at", "CREATE INDEX IF NOT EXISTS idx_created_at ON tasks (created_at)"}, + {"idx_status_created_at", "CREATE INDEX IF NOT EXISTS idx_status_created_at ON tasks (status, created_at)"}, + } + + for _, idx := range indexes { + if err := db.Exec(idx.sql).Error; err != nil { + return nil, fmt.Errorf("failed to create index %s: %w", idx.name, err) + } + slog.Info("Created index", "name", idx.name) + } + + return NewPostgresRepo(db, riverClient), nil +} diff --git a/server/repository/gormimpl/history.go b/server/repository/gormimpl/history.go new file mode 100644 index 0000000..ad38510 --- /dev/null +++ b/server/repository/gormimpl/history.go @@ -0,0 +1,78 @@ +package gormimpl + +import ( + "context" + "database/sql" + "fmt" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "github.com/riverqueue/river" + "gorm.io/gorm" + + interfaces "task/server/repository/interface" + models "task/server/repository/model/task" +) + +var ( + taskHistoryOperations = promauto.NewCounterVec( + prometheus.CounterOpts{ + Name: "task_history_repository_operations_total", + Help: "The total number of task history repository operations", + }, + []string{"operation", "status"}, + ) +) + +// TaskHistoryRepo handles database operations for task history entries. +type TaskHistoryRepo struct { + db *gorm.DB + riverClient *river.Client[*sql.Tx] +} + +// CreateTaskHistory creates a new history entry for a task. +// It returns the created TaskHistory object and any error encountered. +func (s *TaskHistoryRepo) CreateTaskHistory(ctx context.Context, history models.TaskHistory) (models.TaskHistory, error) { + if err := s.db.Create(&history).Error; err != nil { + taskHistoryOperations.WithLabelValues("create", "error").Inc() + return models.TaskHistory{}, fmt.Errorf("failed to create task history: %w", err) + } + taskHistoryOperations.WithLabelValues("create", "success").Inc() + return history, nil +} + +// GetTaskHistory retrieves all history entries for a task by its ID. +// It returns a slice of TaskHistory objects and any error encountered. +func (s *TaskHistoryRepo) GetTaskHistory(ctx context.Context, taskID uint) ([]models.TaskHistory, error) { + var histories []models.TaskHistory + if err := s.db.Where("task_id = ?", taskID).Find(&histories).Error; err != nil { + taskHistoryOperations.WithLabelValues("get", "error").Inc() + return nil, fmt.Errorf("failed to retrieve task history by task ID: %w", err) + } + taskHistoryOperations.WithLabelValues("get", "success").Inc() + return histories, nil +} + +// ListTaskHistories retrieves all history entries for a given task, sorted by ID in ascending order. +// It returns a slice of TaskHistory objects and any error encountered. +func (s *TaskHistoryRepo) ListTaskHistories(ctx context.Context, taskID uint) ([]models.TaskHistory, error) { + var histories []models.TaskHistory + + // Added Order clause to sort by ID in descending order (latest first) + if err := s.db.Where("task_id = ?", taskID).Order("id ASC").Find(&histories).Error; err != nil { + taskHistoryOperations.WithLabelValues("list", "error").Inc() + return nil, fmt.Errorf("failed to retrieve task histories: %w", err) + } + + taskHistoryOperations.WithLabelValues("list", "success").Inc() + return histories, nil +} + +// NewTaskHistoryRepo creates and returns a new instance of TaskHistoryRepo. +// It takes a GORM database connection and a River client as parameters. +func NewTaskHistoryRepo(db *gorm.DB, riverClient *river.Client[*sql.Tx]) interfaces.TaskHistoryRepo { + return &TaskHistoryRepo{ + db: db, + riverClient: riverClient, + } +} diff --git a/server/repository/gormimpl/history_test.go b/server/repository/gormimpl/history_test.go new file mode 100644 index 0000000..1c9c659 --- /dev/null +++ b/server/repository/gormimpl/history_test.go @@ -0,0 +1,39 @@ +package gormimpl + +import ( + "context" + "testing" + + "task/server/repository/mocks" + "task/server/repository/model/task" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestCreateTaskHistory(t *testing.T) { + mockRepo := mocks.NewTaskHistoryRepo(t) // {{ edit_1 }} + history := task.TaskHistory{TaskID: 1, Status: 3} + + mockRepo.EXPECT().CreateTaskHistory(mock.Anything, history).Return(history, nil) // {{ edit_2 }} + + result, err := mockRepo.CreateTaskHistory(context.Background(), history) + + assert.NoError(t, err) + assert.Equal(t, history, result) + mockRepo.AssertExpectations(t) +} + +func TestGetTaskHistory(t *testing.T) { + mockRepo := mocks.NewTaskHistoryRepo(t) // {{ edit_3 }} + histories := []task.TaskHistory{{TaskID: 1, Status: 3}} + + mockRepo.EXPECT().GetTaskHistory(mock.Anything, uint(1)).Return(histories, nil) // {{ edit_4 }} + + result, err := mockRepo.GetTaskHistory(context.Background(), 1) + + assert.NoError(t, err) + assert.Equal(t, histories, result) + assert.Len(t, result, len(histories)) + mockRepo.AssertExpectations(t) +} diff --git a/server/repository/gormimpl/task.go b/server/repository/gormimpl/task.go new file mode 100644 index 0000000..c5164f2 --- /dev/null +++ b/server/repository/gormimpl/task.go @@ -0,0 +1,185 @@ +package gormimpl + +import ( + "context" + "database/sql" + "fmt" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "github.com/riverqueue/river" + "gorm.io/gorm" + + cloudv1 "task/pkg/gen/cloud/v1" + "task/pkg/worker" + interfaces "task/server/repository/interface" + models "task/server/repository/model/task" +) + +var ( + taskOperations = promauto.NewCounterVec( + prometheus.CounterOpts{ + Name: "task_repository_operations_total", + Help: "The total number of task repository operations", + }, + []string{"operation", "status"}, + ) + taskLatency = promauto.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "task_repository_operation_duration_seconds", + Help: "Duration of task repository operations in seconds", + Buckets: prometheus.DefBuckets, + }, + []string{"operation"}, + ) +) + +// TaskRepo implements the TaskRepo interface using GORM for database operations +// and River for task queue management. +type TaskRepo struct { + db *gorm.DB + riverClient *river.Client[*sql.Tx] +} + +// CreateTask creates a new task in the database and enqueues it for processing. +// It returns the created task with its assigned ID or an error if the operation fails. +func (s *TaskRepo) CreateTask(ctx context.Context, task models.Task) (models.Task, error) { + timer := prometheus.NewTimer(taskLatency.WithLabelValues("create")) + defer timer.ObserveDuration() + + result := s.db.Create(&task) + if result.Error != nil { + taskOperations.WithLabelValues("create", "error").Inc() + return models.Task{}, fmt.Errorf("failed to create task: %w", result.Error) + } + + if task.ID == 0 { + taskOperations.WithLabelValues("create", "error").Inc() + return models.Task{}, fmt.Errorf("failed to get task ID after creation") + } + _, err := s.riverClient.Insert(context.Background(), worker.TaskArgument{ + Task: task, + }, &river.InsertOpts{ + MaxAttempts: 5, + }) + if err != nil { + taskOperations.WithLabelValues("create", "error").Inc() + return models.Task{}, fmt.Errorf("failed to enqueue task: %w", err) + } + + taskOperations.WithLabelValues("create", "success").Inc() + return task, nil +} + +// GetTaskByID retrieves a task from the database by its ID. +// It returns a pointer to the task if found, or an error if the task doesn't exist or if the operation fails. +func (s *TaskRepo) GetTaskByID(ctx context.Context, taskID uint) (*models.Task, error) { + timer := prometheus.NewTimer(taskLatency.WithLabelValues("get")) + defer timer.ObserveDuration() + + var task models.Task + if err := s.db.First(&task, taskID).Error; err != nil { + taskOperations.WithLabelValues("get", "error").Inc() + return nil, fmt.Errorf("failed to retrieve task by ID: %w", err) + } + taskOperations.WithLabelValues("get", "success").Inc() + return &task, nil +} + +// UpdateTaskStatus updates the status of a task identified by its ID. +// It returns an error if the update operation fails. +func (s *TaskRepo) UpdateTaskStatus(ctx context.Context, taskID uint, status int) error { + timer := prometheus.NewTimer(taskLatency.WithLabelValues("update_status")) + defer timer.ObserveDuration() + + if err := s.db.Model(&models.Task{}).Where("id = ?", taskID).Update("status", status).Error; err != nil { + taskOperations.WithLabelValues("update_status", "error").Inc() + return fmt.Errorf("failed to update task status: %w", err) + } + if status == int(cloudv1.TaskStatusEnum_QUEUED) { + task, err := s.GetTaskByID(ctx, taskID) + if err != nil { + return fmt.Errorf("failed to get task by ID: %w", err) + } + _, err = s.riverClient.Insert(ctx, worker.TaskArgument{ + Task: *task, + }, &river.InsertOpts{ + MaxAttempts: 5, + }) + if err != nil { + taskOperations.WithLabelValues("update_status", "error").Inc() + return fmt.Errorf("failed to enqueue task: %w", err) + } + } + + taskOperations.WithLabelValues("update_status", "success").Inc() + return nil +} + +// ListTasks retrieves a paginated list of tasks from the database, filtered by status and type. +// The 'limit' parameter specifies the maximum number of tasks to return, +// 'offset' determines the starting point for pagination, +// 'status' allows filtering by task status, and 'taskType' allows filtering by task type. +// It returns a slice of tasks and an error if the operation fails. +func (s *TaskRepo) ListTasks(ctx context.Context, limit, offset int, status int, taskType string) ([]models.Task, error) { + timer := prometheus.NewTimer(taskLatency.WithLabelValues("list")) + defer timer.ObserveDuration() + + var tasks []models.Task + query := s.db.Limit(limit).Offset(offset) + + // Apply filters if they are provided + if status != 5 { + query = query.Where("status = ?", status) + } + if taskType != "" { + query = query.Where("type = ?", taskType) + } + + // Execute the query + if err := query.Find(&tasks).Error; err != nil { + taskOperations.WithLabelValues("list", "error").Inc() + return nil, fmt.Errorf("failed to retrieve tasks: %w", err) + } + + taskOperations.WithLabelValues("list", "success").Inc() + return tasks, nil +} + +// GetTaskStatusCounts retrieves the count of tasks for each status. +// It returns a map where the key is the status code and the value is the count of tasks with that status. +// An error is returned if the operation fails. +func (s *TaskRepo) GetTaskStatusCounts(ctx context.Context) (map[int]int64, error) { + timer := prometheus.NewTimer(taskLatency.WithLabelValues("status_counts")) + defer timer.ObserveDuration() + + var results []struct { + Status int + Count int64 + } + + if err := s.db.Model(&models.Task{}). + Select("status, count(*) as count"). + Group("status"). + Find(&results).Error; err != nil { + taskOperations.WithLabelValues("status_counts", "error").Inc() + return nil, fmt.Errorf("failed to retrieve task status counts: %w", err) + } + + counts := make(map[int]int64) + for _, result := range results { + counts[result.Status] = result.Count + } + + taskOperations.WithLabelValues("status_counts", "success").Inc() + return counts, nil +} + +// NewTaskRepo creates and returns a new instance of TaskRepo. +// It requires a GORM database connection and a River client for task queue management. +func NewTaskRepo(db *gorm.DB, riverClient *river.Client[*sql.Tx]) interfaces.TaskRepo { + return &TaskRepo{ + db: db, + riverClient: riverClient, + } +} diff --git a/server/repository/gormimpl/task_test.go b/server/repository/gormimpl/task_test.go new file mode 100644 index 0000000..b3ac051 --- /dev/null +++ b/server/repository/gormimpl/task_test.go @@ -0,0 +1,57 @@ +package gormimpl + +import ( + "context" + "testing" + + "task/server/repository/mocks" + "task/server/repository/model/task" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestCreateTask(t *testing.T) { + mockRepo := mocks.NewTaskRepo(t) + + newTask := task.Task{Name: "Test Task", Status: 2} + mockRepo.EXPECT().CreateTask(mock.Anything, newTask).Return(newTask, nil) + + createdTask, err := mockRepo.CreateTask(context.Background(), newTask) + + assert.NoError(t, err) + assert.Equal(t, newTask.Name, createdTask.Name) +} + +func TestGetTaskByID(t *testing.T) { + mockRepo := mocks.NewTaskRepo(t) + + taskToCreate := task.Task{Name: "Test Task", Status: 0} + mockRepo.EXPECT().CreateTask(mock.Anything, taskToCreate).Return(taskToCreate, nil) + mockRepo.EXPECT().GetTaskByID(mock.Anything, uint(1)).Return(&taskToCreate, nil) + + mockRepo.CreateTask(context.Background(), taskToCreate) + + retrievedTask, err := mockRepo.GetTaskByID(context.Background(), 1) + + assert.NoError(t, err) + assert.Equal(t, taskToCreate.Name, retrievedTask.Name) +} + +func TestUpdateTaskStatus(t *testing.T) { + mockRepo := mocks.NewTaskRepo(t) + + taskToCreate := task.Task{Name: "Test Task", Status: 1} + mockRepo.EXPECT().CreateTask(mock.Anything, taskToCreate).Return(taskToCreate, nil) + mockRepo.EXPECT().UpdateTaskStatus(mock.Anything, uint(1), 3).Return(nil) + mockRepo.EXPECT().GetTaskByID(mock.Anything, uint(1)).Return(&task.Task{Status: 3}, nil) + + mockRepo.CreateTask(context.Background(), taskToCreate) + + err := mockRepo.UpdateTaskStatus(context.Background(), 1, 3) + + assert.NoError(t, err) + + updatedTask, _ := mockRepo.GetTaskByID(context.Background(), 1) + assert.Equal(t, 3, updatedTask.Status) +} diff --git a/server/repository/interface/history.go b/server/repository/interface/history.go new file mode 100644 index 0000000..9197fce --- /dev/null +++ b/server/repository/interface/history.go @@ -0,0 +1,25 @@ +package interfaces + +import ( + "context" + + model "task/server/repository/model/task" +) + +// TaskHistoryRepo defines the interface for the task history repository. +// It handles operations related to task history management. +// +//go:generate mockery --output=../mocks --case=underscore --all --with-expecter +type TaskHistoryRepo interface { + // CreateTaskHistory creates a history entry for a task. + // It takes a context.Context parameter for handling request-scoped values and deadlines. + CreateTaskHistory(ctx context.Context, history model.TaskHistory) (model.TaskHistory, error) + + // GetTaskHistory retrieves the history of a task by its ID. + // Returns a slice of task history entries, or an error if none found. + GetTaskHistory(ctx context.Context, taskID uint) ([]model.TaskHistory, error) + + // ListTaskHistories lists all history entries for a given task, with pagination support. + // Returns a slice of task history entries, along with a pagination token (if any) for subsequent queries. + ListTaskHistories(ctx context.Context, taskID uint) ([]model.TaskHistory, error) +} diff --git a/server/repository/interface/repo.go b/server/repository/interface/repo.go new file mode 100644 index 0000000..f4e5c35 --- /dev/null +++ b/server/repository/interface/repo.go @@ -0,0 +1,7 @@ +package interfaces + +//go:generate mockery --output=../mocks --case=underscore --all --with-expecter +type TaskManagmentInterface interface { + TaskRepo() TaskRepo + TaskHistoryRepo() TaskHistoryRepo +} diff --git a/server/repository/interface/task.go b/server/repository/interface/task.go new file mode 100644 index 0000000..0d614b4 --- /dev/null +++ b/server/repository/interface/task.go @@ -0,0 +1,39 @@ +package interfaces + +import ( + "context" + + model "task/server/repository/model/task" +) + +// TaskRepo defines the interface for the task repository. +// It handles operations related to task management, including task creation, status update, and history retrieval. +// +//go:generate mockery --output=../mocks --case=underscore --all --with-expecter +type TaskRepo interface { + // CreateTask creates a new task with the provided information. + // It takes a context.Context parameter for handling request-scoped values and deadlines. + CreateTask(ctx context.Context, task model.Task) (model.Task, error) + + // GetTaskByID retrieves a task by its ID. + // It returns the task if found, or an error otherwise. + GetTaskByID(ctx context.Context, taskID uint) (*model.Task, error) + + // UpdateTaskStatus updates the status of a task. + // It requires the task ID and the new status to be set. + UpdateTaskStatus(ctx context.Context, taskID uint, status int) error + + // ListTasks retrieves a list of tasks based on the provided criteria. + // It takes a context.Context parameter for handling request-scoped values and deadlines. + // The limit and offset parameters are used for pagination. + // The status parameter filters tasks by their status (use -1 for all statuses). + // The taskType parameter filters tasks by their type (use an empty string for all types). + // It returns a slice of tasks and an error if any occurs during the operation. + ListTasks(ctx context.Context, limit, offset int, status int, taskType string) ([]model.Task, error) + + // GetTaskStatusCounts retrieves the count of tasks for each status. + // It takes a context.Context parameter for handling request-scoped values and deadlines. + // It returns a map where the key is the status code and the value is the count of tasks with that status. + // An error is returned if any occurs during the operation. + GetTaskStatusCounts(ctx context.Context) (map[int]int64, error) +} diff --git a/server/repository/mocks/task_history_repo.go b/server/repository/mocks/task_history_repo.go new file mode 100644 index 0000000..88088fb --- /dev/null +++ b/server/repository/mocks/task_history_repo.go @@ -0,0 +1,213 @@ +// Code generated by mockery v2.46.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + task "task/server/repository/model/task" +) + +// TaskHistoryRepo is an autogenerated mock type for the TaskHistoryRepo type +type TaskHistoryRepo struct { + mock.Mock +} + +type TaskHistoryRepo_Expecter struct { + mock *mock.Mock +} + +func (_m *TaskHistoryRepo) EXPECT() *TaskHistoryRepo_Expecter { + return &TaskHistoryRepo_Expecter{mock: &_m.Mock} +} + +// CreateTaskHistory provides a mock function with given fields: ctx, history +func (_m *TaskHistoryRepo) CreateTaskHistory(ctx context.Context, history task.TaskHistory) (task.TaskHistory, error) { + ret := _m.Called(ctx, history) + + if len(ret) == 0 { + panic("no return value specified for CreateTaskHistory") + } + + var r0 task.TaskHistory + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, task.TaskHistory) (task.TaskHistory, error)); ok { + return rf(ctx, history) + } + if rf, ok := ret.Get(0).(func(context.Context, task.TaskHistory) task.TaskHistory); ok { + r0 = rf(ctx, history) + } else { + r0 = ret.Get(0).(task.TaskHistory) + } + + if rf, ok := ret.Get(1).(func(context.Context, task.TaskHistory) error); ok { + r1 = rf(ctx, history) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskHistoryRepo_CreateTaskHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateTaskHistory' +type TaskHistoryRepo_CreateTaskHistory_Call struct { + *mock.Call +} + +// CreateTaskHistory is a helper method to define mock.On call +// - ctx context.Context +// - history task.TaskHistory +func (_e *TaskHistoryRepo_Expecter) CreateTaskHistory(ctx interface{}, history interface{}) *TaskHistoryRepo_CreateTaskHistory_Call { + return &TaskHistoryRepo_CreateTaskHistory_Call{Call: _e.mock.On("CreateTaskHistory", ctx, history)} +} + +func (_c *TaskHistoryRepo_CreateTaskHistory_Call) Run(run func(ctx context.Context, history task.TaskHistory)) *TaskHistoryRepo_CreateTaskHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(task.TaskHistory)) + }) + return _c +} + +func (_c *TaskHistoryRepo_CreateTaskHistory_Call) Return(_a0 task.TaskHistory, _a1 error) *TaskHistoryRepo_CreateTaskHistory_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskHistoryRepo_CreateTaskHistory_Call) RunAndReturn(run func(context.Context, task.TaskHistory) (task.TaskHistory, error)) *TaskHistoryRepo_CreateTaskHistory_Call { + _c.Call.Return(run) + return _c +} + +// GetTaskHistory provides a mock function with given fields: ctx, taskID +func (_m *TaskHistoryRepo) GetTaskHistory(ctx context.Context, taskID uint) ([]task.TaskHistory, error) { + ret := _m.Called(ctx, taskID) + + if len(ret) == 0 { + panic("no return value specified for GetTaskHistory") + } + + var r0 []task.TaskHistory + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint) ([]task.TaskHistory, error)); ok { + return rf(ctx, taskID) + } + if rf, ok := ret.Get(0).(func(context.Context, uint) []task.TaskHistory); ok { + r0 = rf(ctx, taskID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]task.TaskHistory) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint) error); ok { + r1 = rf(ctx, taskID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskHistoryRepo_GetTaskHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTaskHistory' +type TaskHistoryRepo_GetTaskHistory_Call struct { + *mock.Call +} + +// GetTaskHistory is a helper method to define mock.On call +// - ctx context.Context +// - taskID uint +func (_e *TaskHistoryRepo_Expecter) GetTaskHistory(ctx interface{}, taskID interface{}) *TaskHistoryRepo_GetTaskHistory_Call { + return &TaskHistoryRepo_GetTaskHistory_Call{Call: _e.mock.On("GetTaskHistory", ctx, taskID)} +} + +func (_c *TaskHistoryRepo_GetTaskHistory_Call) Run(run func(ctx context.Context, taskID uint)) *TaskHistoryRepo_GetTaskHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint)) + }) + return _c +} + +func (_c *TaskHistoryRepo_GetTaskHistory_Call) Return(_a0 []task.TaskHistory, _a1 error) *TaskHistoryRepo_GetTaskHistory_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskHistoryRepo_GetTaskHistory_Call) RunAndReturn(run func(context.Context, uint) ([]task.TaskHistory, error)) *TaskHistoryRepo_GetTaskHistory_Call { + _c.Call.Return(run) + return _c +} + +// ListTaskHistories provides a mock function with given fields: ctx, taskID +func (_m *TaskHistoryRepo) ListTaskHistories(ctx context.Context, taskID uint) ([]task.TaskHistory, error) { + ret := _m.Called(ctx, taskID) + + if len(ret) == 0 { + panic("no return value specified for ListTaskHistories") + } + + var r0 []task.TaskHistory + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint) ([]task.TaskHistory, error)); ok { + return rf(ctx, taskID) + } + if rf, ok := ret.Get(0).(func(context.Context, uint) []task.TaskHistory); ok { + r0 = rf(ctx, taskID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]task.TaskHistory) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint) error); ok { + r1 = rf(ctx, taskID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskHistoryRepo_ListTaskHistories_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListTaskHistories' +type TaskHistoryRepo_ListTaskHistories_Call struct { + *mock.Call +} + +// ListTaskHistories is a helper method to define mock.On call +// - ctx context.Context +// - taskID uint +func (_e *TaskHistoryRepo_Expecter) ListTaskHistories(ctx interface{}, taskID interface{}) *TaskHistoryRepo_ListTaskHistories_Call { + return &TaskHistoryRepo_ListTaskHistories_Call{Call: _e.mock.On("ListTaskHistories", ctx, taskID)} +} + +func (_c *TaskHistoryRepo_ListTaskHistories_Call) Run(run func(ctx context.Context, taskID uint)) *TaskHistoryRepo_ListTaskHistories_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint)) + }) + return _c +} + +func (_c *TaskHistoryRepo_ListTaskHistories_Call) Return(_a0 []task.TaskHistory, _a1 error) *TaskHistoryRepo_ListTaskHistories_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskHistoryRepo_ListTaskHistories_Call) RunAndReturn(run func(context.Context, uint) ([]task.TaskHistory, error)) *TaskHistoryRepo_ListTaskHistories_Call { + _c.Call.Return(run) + return _c +} + +// NewTaskHistoryRepo creates a new instance of TaskHistoryRepo. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewTaskHistoryRepo(t interface { + mock.TestingT + Cleanup(func()) +}) *TaskHistoryRepo { + mock := &TaskHistoryRepo{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/server/repository/mocks/task_managment_interface.go b/server/repository/mocks/task_managment_interface.go new file mode 100644 index 0000000..ad78aee --- /dev/null +++ b/server/repository/mocks/task_managment_interface.go @@ -0,0 +1,130 @@ +// Code generated by mockery v2.46.0. DO NOT EDIT. + +package mocks + +import ( + interfaces "task/server/repository/interface" + + mock "github.com/stretchr/testify/mock" +) + +// TaskManagmentInterface is an autogenerated mock type for the TaskManagmentInterface type +type TaskManagmentInterface struct { + mock.Mock +} + +type TaskManagmentInterface_Expecter struct { + mock *mock.Mock +} + +func (_m *TaskManagmentInterface) EXPECT() *TaskManagmentInterface_Expecter { + return &TaskManagmentInterface_Expecter{mock: &_m.Mock} +} + +// TaskHistoryRepo provides a mock function with given fields: +func (_m *TaskManagmentInterface) TaskHistoryRepo() interfaces.TaskHistoryRepo { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for TaskHistoryRepo") + } + + var r0 interfaces.TaskHistoryRepo + if rf, ok := ret.Get(0).(func() interfaces.TaskHistoryRepo); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(interfaces.TaskHistoryRepo) + } + } + + return r0 +} + +// TaskManagmentInterface_TaskHistoryRepo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TaskHistoryRepo' +type TaskManagmentInterface_TaskHistoryRepo_Call struct { + *mock.Call +} + +// TaskHistoryRepo is a helper method to define mock.On call +func (_e *TaskManagmentInterface_Expecter) TaskHistoryRepo() *TaskManagmentInterface_TaskHistoryRepo_Call { + return &TaskManagmentInterface_TaskHistoryRepo_Call{Call: _e.mock.On("TaskHistoryRepo")} +} + +func (_c *TaskManagmentInterface_TaskHistoryRepo_Call) Run(run func()) *TaskManagmentInterface_TaskHistoryRepo_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TaskManagmentInterface_TaskHistoryRepo_Call) Return(_a0 interfaces.TaskHistoryRepo) *TaskManagmentInterface_TaskHistoryRepo_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TaskManagmentInterface_TaskHistoryRepo_Call) RunAndReturn(run func() interfaces.TaskHistoryRepo) *TaskManagmentInterface_TaskHistoryRepo_Call { + _c.Call.Return(run) + return _c +} + +// TaskRepo provides a mock function with given fields: +func (_m *TaskManagmentInterface) TaskRepo() interfaces.TaskRepo { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for TaskRepo") + } + + var r0 interfaces.TaskRepo + if rf, ok := ret.Get(0).(func() interfaces.TaskRepo); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(interfaces.TaskRepo) + } + } + + return r0 +} + +// TaskManagmentInterface_TaskRepo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TaskRepo' +type TaskManagmentInterface_TaskRepo_Call struct { + *mock.Call +} + +// TaskRepo is a helper method to define mock.On call +func (_e *TaskManagmentInterface_Expecter) TaskRepo() *TaskManagmentInterface_TaskRepo_Call { + return &TaskManagmentInterface_TaskRepo_Call{Call: _e.mock.On("TaskRepo")} +} + +func (_c *TaskManagmentInterface_TaskRepo_Call) Run(run func()) *TaskManagmentInterface_TaskRepo_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TaskManagmentInterface_TaskRepo_Call) Return(_a0 interfaces.TaskRepo) *TaskManagmentInterface_TaskRepo_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TaskManagmentInterface_TaskRepo_Call) RunAndReturn(run func() interfaces.TaskRepo) *TaskManagmentInterface_TaskRepo_Call { + _c.Call.Return(run) + return _c +} + +// NewTaskManagmentInterface creates a new instance of TaskManagmentInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewTaskManagmentInterface(t interface { + mock.TestingT + Cleanup(func()) +}) *TaskManagmentInterface { + mock := &TaskManagmentInterface{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/server/repository/mocks/task_repo.go b/server/repository/mocks/task_repo.go new file mode 100644 index 0000000..5ee0f5a --- /dev/null +++ b/server/repository/mocks/task_repo.go @@ -0,0 +1,322 @@ +// Code generated by mockery v2.46.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + task "task/server/repository/model/task" +) + +// TaskRepo is an autogenerated mock type for the TaskRepo type +type TaskRepo struct { + mock.Mock +} + +type TaskRepo_Expecter struct { + mock *mock.Mock +} + +func (_m *TaskRepo) EXPECT() *TaskRepo_Expecter { + return &TaskRepo_Expecter{mock: &_m.Mock} +} + +// CreateTask provides a mock function with given fields: ctx, _a1 +func (_m *TaskRepo) CreateTask(ctx context.Context, _a1 task.Task) (task.Task, error) { + ret := _m.Called(ctx, _a1) + + if len(ret) == 0 { + panic("no return value specified for CreateTask") + } + + var r0 task.Task + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, task.Task) (task.Task, error)); ok { + return rf(ctx, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, task.Task) task.Task); ok { + r0 = rf(ctx, _a1) + } else { + r0 = ret.Get(0).(task.Task) + } + + if rf, ok := ret.Get(1).(func(context.Context, task.Task) error); ok { + r1 = rf(ctx, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskRepo_CreateTask_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateTask' +type TaskRepo_CreateTask_Call struct { + *mock.Call +} + +// CreateTask is a helper method to define mock.On call +// - ctx context.Context +// - _a1 task.Task +func (_e *TaskRepo_Expecter) CreateTask(ctx interface{}, _a1 interface{}) *TaskRepo_CreateTask_Call { + return &TaskRepo_CreateTask_Call{Call: _e.mock.On("CreateTask", ctx, _a1)} +} + +func (_c *TaskRepo_CreateTask_Call) Run(run func(ctx context.Context, _a1 task.Task)) *TaskRepo_CreateTask_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(task.Task)) + }) + return _c +} + +func (_c *TaskRepo_CreateTask_Call) Return(_a0 task.Task, _a1 error) *TaskRepo_CreateTask_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskRepo_CreateTask_Call) RunAndReturn(run func(context.Context, task.Task) (task.Task, error)) *TaskRepo_CreateTask_Call { + _c.Call.Return(run) + return _c +} + +// GetTaskByID provides a mock function with given fields: ctx, taskID +func (_m *TaskRepo) GetTaskByID(ctx context.Context, taskID uint) (*task.Task, error) { + ret := _m.Called(ctx, taskID) + + if len(ret) == 0 { + panic("no return value specified for GetTaskByID") + } + + var r0 *task.Task + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint) (*task.Task, error)); ok { + return rf(ctx, taskID) + } + if rf, ok := ret.Get(0).(func(context.Context, uint) *task.Task); ok { + r0 = rf(ctx, taskID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*task.Task) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint) error); ok { + r1 = rf(ctx, taskID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskRepo_GetTaskByID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTaskByID' +type TaskRepo_GetTaskByID_Call struct { + *mock.Call +} + +// GetTaskByID is a helper method to define mock.On call +// - ctx context.Context +// - taskID uint +func (_e *TaskRepo_Expecter) GetTaskByID(ctx interface{}, taskID interface{}) *TaskRepo_GetTaskByID_Call { + return &TaskRepo_GetTaskByID_Call{Call: _e.mock.On("GetTaskByID", ctx, taskID)} +} + +func (_c *TaskRepo_GetTaskByID_Call) Run(run func(ctx context.Context, taskID uint)) *TaskRepo_GetTaskByID_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint)) + }) + return _c +} + +func (_c *TaskRepo_GetTaskByID_Call) Return(_a0 *task.Task, _a1 error) *TaskRepo_GetTaskByID_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskRepo_GetTaskByID_Call) RunAndReturn(run func(context.Context, uint) (*task.Task, error)) *TaskRepo_GetTaskByID_Call { + _c.Call.Return(run) + return _c +} + +// GetTaskStatusCounts provides a mock function with given fields: ctx +func (_m *TaskRepo) GetTaskStatusCounts(ctx context.Context) (map[int]int64, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetTaskStatusCounts") + } + + var r0 map[int]int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (map[int]int64, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) map[int]int64); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[int]int64) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskRepo_GetTaskStatusCounts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTaskStatusCounts' +type TaskRepo_GetTaskStatusCounts_Call struct { + *mock.Call +} + +// GetTaskStatusCounts is a helper method to define mock.On call +// - ctx context.Context +func (_e *TaskRepo_Expecter) GetTaskStatusCounts(ctx interface{}) *TaskRepo_GetTaskStatusCounts_Call { + return &TaskRepo_GetTaskStatusCounts_Call{Call: _e.mock.On("GetTaskStatusCounts", ctx)} +} + +func (_c *TaskRepo_GetTaskStatusCounts_Call) Run(run func(ctx context.Context)) *TaskRepo_GetTaskStatusCounts_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *TaskRepo_GetTaskStatusCounts_Call) Return(_a0 map[int]int64, _a1 error) *TaskRepo_GetTaskStatusCounts_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskRepo_GetTaskStatusCounts_Call) RunAndReturn(run func(context.Context) (map[int]int64, error)) *TaskRepo_GetTaskStatusCounts_Call { + _c.Call.Return(run) + return _c +} + +// ListTasks provides a mock function with given fields: ctx, limit, offset, status, taskType +func (_m *TaskRepo) ListTasks(ctx context.Context, limit int, offset int, status int, taskType string) ([]task.Task, error) { + ret := _m.Called(ctx, limit, offset, status, taskType) + + if len(ret) == 0 { + panic("no return value specified for ListTasks") + } + + var r0 []task.Task + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int, int, int, string) ([]task.Task, error)); ok { + return rf(ctx, limit, offset, status, taskType) + } + if rf, ok := ret.Get(0).(func(context.Context, int, int, int, string) []task.Task); ok { + r0 = rf(ctx, limit, offset, status, taskType) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]task.Task) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int, int, int, string) error); ok { + r1 = rf(ctx, limit, offset, status, taskType) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskRepo_ListTasks_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListTasks' +type TaskRepo_ListTasks_Call struct { + *mock.Call +} + +// ListTasks is a helper method to define mock.On call +// - ctx context.Context +// - limit int +// - offset int +// - status int +// - taskType string +func (_e *TaskRepo_Expecter) ListTasks(ctx interface{}, limit interface{}, offset interface{}, status interface{}, taskType interface{}) *TaskRepo_ListTasks_Call { + return &TaskRepo_ListTasks_Call{Call: _e.mock.On("ListTasks", ctx, limit, offset, status, taskType)} +} + +func (_c *TaskRepo_ListTasks_Call) Run(run func(ctx context.Context, limit int, offset int, status int, taskType string)) *TaskRepo_ListTasks_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int), args[2].(int), args[3].(int), args[4].(string)) + }) + return _c +} + +func (_c *TaskRepo_ListTasks_Call) Return(_a0 []task.Task, _a1 error) *TaskRepo_ListTasks_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskRepo_ListTasks_Call) RunAndReturn(run func(context.Context, int, int, int, string) ([]task.Task, error)) *TaskRepo_ListTasks_Call { + _c.Call.Return(run) + return _c +} + +// UpdateTaskStatus provides a mock function with given fields: ctx, taskID, status +func (_m *TaskRepo) UpdateTaskStatus(ctx context.Context, taskID uint, status int) error { + ret := _m.Called(ctx, taskID, status) + + if len(ret) == 0 { + panic("no return value specified for UpdateTaskStatus") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint, int) error); ok { + r0 = rf(ctx, taskID, status) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// TaskRepo_UpdateTaskStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTaskStatus' +type TaskRepo_UpdateTaskStatus_Call struct { + *mock.Call +} + +// UpdateTaskStatus is a helper method to define mock.On call +// - ctx context.Context +// - taskID uint +// - status int +func (_e *TaskRepo_Expecter) UpdateTaskStatus(ctx interface{}, taskID interface{}, status interface{}) *TaskRepo_UpdateTaskStatus_Call { + return &TaskRepo_UpdateTaskStatus_Call{Call: _e.mock.On("UpdateTaskStatus", ctx, taskID, status)} +} + +func (_c *TaskRepo_UpdateTaskStatus_Call) Run(run func(ctx context.Context, taskID uint, status int)) *TaskRepo_UpdateTaskStatus_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint), args[2].(int)) + }) + return _c +} + +func (_c *TaskRepo_UpdateTaskStatus_Call) Return(_a0 error) *TaskRepo_UpdateTaskStatus_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TaskRepo_UpdateTaskStatus_Call) RunAndReturn(run func(context.Context, uint, int) error) *TaskRepo_UpdateTaskStatus_Call { + _c.Call.Return(run) + return _c +} + +// NewTaskRepo creates a new instance of TaskRepo. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewTaskRepo(t interface { + mock.TestingT + Cleanup(func()) +}) *TaskRepo { + mock := &TaskRepo{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/server/repository/model/task/history.go b/server/repository/model/task/history.go new file mode 100644 index 0000000..50ff0d7 --- /dev/null +++ b/server/repository/model/task/history.go @@ -0,0 +1,27 @@ +package task + +import ( + "time" + + "gorm.io/gorm" +) + +// TaskHistory represents the history of a task with status changes and additional details. +type TaskHistory struct { + gorm.Model + TaskID uint `json:"task_id" gorm:"not null"` // Foreign key for Task + Status int `json:"status" gorm:"type:int;not null"` // Refers to the custom PostgreSQL enum + Details string `json:"details" gorm:"type:text"` + CreatedAt time.Time `json:"created_at" gorm:"not null"` +} + +// TableName returns the custom table name for the TaskHistory model. +func (*TaskHistory) TableName() string { + return "task_histories" +} + +// BeforeCreate sets the CreatedAt field to the current time before creating a new TaskHistory record. +func (th *TaskHistory) BeforeCreate(tx *gorm.DB) (err error) { + th.CreatedAt = time.Now() + return nil +} diff --git a/server/repository/model/task/task.go b/server/repository/model/task/task.go new file mode 100644 index 0000000..5c2c0a3 --- /dev/null +++ b/server/repository/model/task/task.go @@ -0,0 +1,51 @@ +package task + +import ( + "encoding/json" + "errors" + "time" + + "gorm.io/gorm" +) + +// Task represents a task with its attributes. +type Task struct { + gorm.Model + Name string `json:"name" gorm:"type:varchar(255);not null"` + Description string `json:"description" gorm:"type:text;not null"` + Type string `json:"type" gorm:"type:varchar(255);not null"` // Refers to the custom PostgreSQL enum + Status int `json:"status" gorm:"type:int;not null"` // Refers to the custom PostgreSQL enum + Payload string `json:"payload" gorm:"type:jsonb;not null"` // Storing JSON as a string in PostgreSQL + Retries int `json:"retries" gorm:"default:0;check:retries >= 0 AND retries <= 10"` + Priority int `json:"priority" gorm:"default:0;check:priority >= 0"` + CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime; not null"` +} + +// TableName returns the custom table name for the Task model. +func (*Task) TableName() string { + return "tasks" +} + +// BeforeCreate ensures that the TaskType and TaskStatusEnum are valid before the task is created. +func (t *Task) BeforeCreate(tx *gorm.DB) (err error) { + // Set CreatedAt to current time + t.CreatedAt = time.Now() + + // Ensure task type is valid + if t.Type != "send_email" && t.Type != "run_query" { + return errors.New("invalid task type") + } + + // Ensure task status is valid + if t.Status > 3 { + return errors.New("invalid task status") + } + + // Ensure payload is valid JSON + var js json.RawMessage + if err := json.Unmarshal([]byte(t.Payload), &js); err != nil { + return errors.New("invalid JSON payload") + } + + return nil +} diff --git a/server/repository/postgres.go b/server/repository/postgres.go new file mode 100644 index 0000000..7c3653d --- /dev/null +++ b/server/repository/postgres.go @@ -0,0 +1,32 @@ +package repositories + +import ( + "database/sql" + "fmt" + gormimpl "task/server/repository/gormimpl" + interfaces "task/server/repository/interface" + + "github.com/riverqueue/river" + "gorm.io/gorm" +) + +type Postgres struct { + task interfaces.TaskRepo + history interfaces.TaskHistoryRepo +} + +func (r Postgres) TaskRepo() interfaces.TaskRepo { + fmt.Println(r.task) + return r.task +} + +func (r Postgres) TaskHistoryRepo() interfaces.TaskHistoryRepo { + return r.history +} + +func NewPostgresRepo(db *gorm.DB, riverClient *river.Client[*sql.Tx]) interfaces.TaskManagmentInterface { + return &Postgres{ + task: gormimpl.NewTaskRepo(db, riverClient), + history: gormimpl.NewTaskHistoryRepo(db, riverClient), + } +} diff --git a/server/root/main.go b/server/root/main.go new file mode 100644 index 0000000..d26de24 --- /dev/null +++ b/server/root/main.go @@ -0,0 +1,213 @@ +package main + +import ( + "context" + "errors" + "fmt" + "log/slog" + "net/http" + "os" + "os/signal" + "syscall" + "time" + + "connectrpc.com/connect" + "connectrpc.com/grpchealth" + "connectrpc.com/grpcreflect" + "connectrpc.com/otelconnect" + "github.com/rs/cors" + "go.akshayshah.org/connectauth" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + + cloudv1connect "task/pkg/gen/cloud/v1/cloudv1connect" + "task/pkg/x" // Import the x package for env and config + repository "task/server/repository" // Import repository package + interfaces "task/server/repository/interface" // Import repository package + "task/server/route" // Import route package + + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +const ( + CompressMinByte = 1024 // Minimum byte size for compression +) + +// AuthCtx holds user authentication information +type AuthCtx struct { + Username string +} + +// newCORS initializes CORS settings for the server +// It allows all origins and methods, and exposes necessary headers for gRPC-Web +func newCORS() *cors.Cors { + return cors.New(cors.Options{ + AllowedMethods: []string{ + http.MethodHead, + http.MethodGet, + http.MethodPost, + http.MethodPut, + http.MethodPatch, + http.MethodDelete, + }, + AllowOriginFunc: func(origin string) bool { + return true // Allow all origins + }, + AllowedHeaders: []string{"*"}, + ExposedHeaders: []string{ + "Accept", + "Accept-Encoding", + "Accept-Post", + "Connect-Accept-Encoding", + "Connect-Content-Encoding", + "Content-Encoding", + "Grpc-Accept-Encoding", + "Grpc-Encoding", + "Grpc-Message", + "Grpc-Status", + "Grpc-Status-Details-Bin", + }, + }) +} + +// main is the entry point of the application. +// It sets up logging and runs the main application logic. +func main() { + // Initialize structured logging with JSON format + logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ + Level: slog.LevelInfo, + })) + slog.SetDefault(logger) + + if err := run(); err != nil { + slog.Error("Application failed", "error", err) + os.Exit(1) + } +} + +// run encapsulates the main application logic +// It loads configuration, sets up the server, and handles graceful shutdown +func run() error { + // Load environment variables + if err := x.LoadEnv(); err != nil { + return fmt.Errorf("failed to load environment variables: %w", err) + } + + env, err := x.LoadConfig() + if err != nil { + return fmt.Errorf("failed to load configuration: %w", err) + } + slog.Info("Application started", "config", env) + + // Set up a channel to handle exit signals + exitChan := make(chan os.Signal, 1) + signal.Notify(exitChan, syscall.SIGINT, syscall.SIGTERM) + + // Create the repository with DB configuration + repo, err := repository.GetRepository(env.Database.ToDbConnectionUri(), env.WorkerCount, env.Database.PoolMaxConns) + if err != nil { + return fmt.Errorf("failed to initialize database repository: %w", err) + } + + slog.Info("Database repository initialized", "workerCount", env.WorkerCount) + + // Set up gRPC middleware + middleware := connectauth.NewMiddleware(GrpcMiddleware) + + // Set up HTTP server + mux := http.NewServeMux() + if err := setupHandlers(mux, repo, middleware); err != nil { + return fmt.Errorf("failed to set up handlers: %w", err) + } + + // Add Prometheus metrics endpoint + mux.Handle("/metrics", promhttp.Handler()) + + // Initialize HTTP server + srv := &http.Server{ + Addr: fmt.Sprintf("0.0.0.0:%v", env.ServerPort), + Handler: h2c.NewHandler( + newCORS().Handler(mux), + &http2.Server{}, + ), + ReadHeaderTimeout: time.Second, + ReadTimeout: 5 * time.Minute, + WriteTimeout: 5 * time.Minute, + MaxHeaderBytes: 8 * 1024, // 8KiB + } + + // Start the server in a goroutine + serverErrChan := make(chan error, 1) + go func() { + slog.Info("HTTP server starting", "address", srv.Addr) + if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { + serverErrChan <- fmt.Errorf("HTTP server failed: %w", err) + } + }() + + // Wait for exit signal or server error + select { + case <-exitChan: + slog.Info("Shutdown signal received, shutting down server...") + case err := <-serverErrChan: + return err + } + + // Graceful shutdown + if err := shutdownServer(srv); err != nil { + return fmt.Errorf("HTTP server shutdown failed: %w", err) + } + slog.Info("HTTP server shut down gracefully") + return nil +} + +// setupHandlers configures the HTTP handlers for the server +// It sets up the gRPC service, health check, and reflection handlers +func setupHandlers(mux *http.ServeMux, repo interfaces.TaskManagmentInterface, middleware *connectauth.Middleware) error { + otelInterceptor, err := otelconnect.NewInterceptor() + if err != nil { + return fmt.Errorf("failed to create interceptor: %w", err) + } + + pattern, handler := cloudv1connect.NewTaskManagementServiceHandler( + route.NewTaskServer(repo), + connect.WithInterceptors(otelInterceptor), + connect.WithCompressMinBytes(CompressMinByte), + ) + mux.Handle(pattern, middleware.Wrap(handler)) + + // Health check and reflection handlers + mux.Handle(grpchealth.NewHandler( + grpchealth.NewStaticChecker(cloudv1connect.TaskManagementServiceName), + )) + mux.Handle(grpcreflect.NewHandlerV1( + grpcreflect.NewStaticReflector(cloudv1connect.TaskManagementServiceName), + )) + mux.Handle(grpcreflect.NewHandlerV1Alpha( + grpcreflect.NewStaticReflector(cloudv1connect.TaskManagementServiceName), + )) + + slog.Info("Handlers set up successfully", "serviceName", cloudv1connect.TaskManagementServiceName) + return nil +} + +// shutdownServer gracefully shuts down the HTTP server +// It waits for ongoing requests to complete before shutting down +func shutdownServer(srv *http.Server) error { + slog.Info("Initiating graceful shutdown") + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + if err := srv.Shutdown(ctx); err != nil { + return fmt.Errorf("HTTP server shutdown failed: %w", err) + } + slog.Info("Server shutdown completed") + return nil +} + +// GrpcMiddleware is the gRPC middleware used for authentication. +// Currently, it uses a placeholder authentication mechanism. +func GrpcMiddleware(ctx context.Context, req *connectauth.Request) (any, error) { + // TODO: Implement proper authentication logic + slog.Warn("Using placeholder authentication", "username", "tqindia") + return AuthCtx{Username: "tqindia"}, nil +} diff --git a/server/route/mocks/task_management_handler.go b/server/route/mocks/task_management_handler.go new file mode 100644 index 0000000..772c2f9 --- /dev/null +++ b/server/route/mocks/task_management_handler.go @@ -0,0 +1,334 @@ +// Code generated by mockery v2.46.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + cloudv1 "task/pkg/gen/cloud/v1" + + emptypb "google.golang.org/protobuf/types/known/emptypb" + + mock "github.com/stretchr/testify/mock" +) + +// TaskManagementHandler is an autogenerated mock type for the TaskManagementHandler type +type TaskManagementHandler struct { + mock.Mock +} + +type TaskManagementHandler_Expecter struct { + mock *mock.Mock +} + +func (_m *TaskManagementHandler) EXPECT() *TaskManagementHandler_Expecter { + return &TaskManagementHandler_Expecter{mock: &_m.Mock} +} + +// CreateTask provides a mock function with given fields: ctx, req +func (_m *TaskManagementHandler) CreateTask(ctx context.Context, req *cloudv1.CreateTaskRequest) (*cloudv1.CreateTaskResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for CreateTask") + } + + var r0 *cloudv1.CreateTaskResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudv1.CreateTaskRequest) (*cloudv1.CreateTaskResponse, error)); ok { + return rf(ctx, req) + } + if rf, ok := ret.Get(0).(func(context.Context, *cloudv1.CreateTaskRequest) *cloudv1.CreateTaskResponse); ok { + r0 = rf(ctx, req) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudv1.CreateTaskResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *cloudv1.CreateTaskRequest) error); ok { + r1 = rf(ctx, req) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskManagementHandler_CreateTask_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateTask' +type TaskManagementHandler_CreateTask_Call struct { + *mock.Call +} + +// CreateTask is a helper method to define mock.On call +// - ctx context.Context +// - req *cloudv1.CreateTaskRequest +func (_e *TaskManagementHandler_Expecter) CreateTask(ctx interface{}, req interface{}) *TaskManagementHandler_CreateTask_Call { + return &TaskManagementHandler_CreateTask_Call{Call: _e.mock.On("CreateTask", ctx, req)} +} + +func (_c *TaskManagementHandler_CreateTask_Call) Run(run func(ctx context.Context, req *cloudv1.CreateTaskRequest)) *TaskManagementHandler_CreateTask_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*cloudv1.CreateTaskRequest)) + }) + return _c +} + +func (_c *TaskManagementHandler_CreateTask_Call) Return(_a0 *cloudv1.CreateTaskResponse, _a1 error) *TaskManagementHandler_CreateTask_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskManagementHandler_CreateTask_Call) RunAndReturn(run func(context.Context, *cloudv1.CreateTaskRequest) (*cloudv1.CreateTaskResponse, error)) *TaskManagementHandler_CreateTask_Call { + _c.Call.Return(run) + return _c +} + +// GetTask provides a mock function with given fields: ctx, req +func (_m *TaskManagementHandler) GetTask(ctx context.Context, req *cloudv1.GetTaskRequest) (*cloudv1.Task, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for GetTask") + } + + var r0 *cloudv1.Task + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudv1.GetTaskRequest) (*cloudv1.Task, error)); ok { + return rf(ctx, req) + } + if rf, ok := ret.Get(0).(func(context.Context, *cloudv1.GetTaskRequest) *cloudv1.Task); ok { + r0 = rf(ctx, req) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudv1.Task) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *cloudv1.GetTaskRequest) error); ok { + r1 = rf(ctx, req) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskManagementHandler_GetTask_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTask' +type TaskManagementHandler_GetTask_Call struct { + *mock.Call +} + +// GetTask is a helper method to define mock.On call +// - ctx context.Context +// - req *cloudv1.GetTaskRequest +func (_e *TaskManagementHandler_Expecter) GetTask(ctx interface{}, req interface{}) *TaskManagementHandler_GetTask_Call { + return &TaskManagementHandler_GetTask_Call{Call: _e.mock.On("GetTask", ctx, req)} +} + +func (_c *TaskManagementHandler_GetTask_Call) Run(run func(ctx context.Context, req *cloudv1.GetTaskRequest)) *TaskManagementHandler_GetTask_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*cloudv1.GetTaskRequest)) + }) + return _c +} + +func (_c *TaskManagementHandler_GetTask_Call) Return(_a0 *cloudv1.Task, _a1 error) *TaskManagementHandler_GetTask_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskManagementHandler_GetTask_Call) RunAndReturn(run func(context.Context, *cloudv1.GetTaskRequest) (*cloudv1.Task, error)) *TaskManagementHandler_GetTask_Call { + _c.Call.Return(run) + return _c +} + +// GetTaskHistory provides a mock function with given fields: ctx, req +func (_m *TaskManagementHandler) GetTaskHistory(ctx context.Context, req *cloudv1.GetTaskHistoryRequest) (*cloudv1.GetTaskHistoryResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for GetTaskHistory") + } + + var r0 *cloudv1.GetTaskHistoryResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudv1.GetTaskHistoryRequest) (*cloudv1.GetTaskHistoryResponse, error)); ok { + return rf(ctx, req) + } + if rf, ok := ret.Get(0).(func(context.Context, *cloudv1.GetTaskHistoryRequest) *cloudv1.GetTaskHistoryResponse); ok { + r0 = rf(ctx, req) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudv1.GetTaskHistoryResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *cloudv1.GetTaskHistoryRequest) error); ok { + r1 = rf(ctx, req) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskManagementHandler_GetTaskHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTaskHistory' +type TaskManagementHandler_GetTaskHistory_Call struct { + *mock.Call +} + +// GetTaskHistory is a helper method to define mock.On call +// - ctx context.Context +// - req *cloudv1.GetTaskHistoryRequest +func (_e *TaskManagementHandler_Expecter) GetTaskHistory(ctx interface{}, req interface{}) *TaskManagementHandler_GetTaskHistory_Call { + return &TaskManagementHandler_GetTaskHistory_Call{Call: _e.mock.On("GetTaskHistory", ctx, req)} +} + +func (_c *TaskManagementHandler_GetTaskHistory_Call) Run(run func(ctx context.Context, req *cloudv1.GetTaskHistoryRequest)) *TaskManagementHandler_GetTaskHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*cloudv1.GetTaskHistoryRequest)) + }) + return _c +} + +func (_c *TaskManagementHandler_GetTaskHistory_Call) Return(_a0 *cloudv1.GetTaskHistoryResponse, _a1 error) *TaskManagementHandler_GetTaskHistory_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskManagementHandler_GetTaskHistory_Call) RunAndReturn(run func(context.Context, *cloudv1.GetTaskHistoryRequest) (*cloudv1.GetTaskHistoryResponse, error)) *TaskManagementHandler_GetTaskHistory_Call { + _c.Call.Return(run) + return _c +} + +// ListTasks provides a mock function with given fields: ctx, req +func (_m *TaskManagementHandler) ListTasks(ctx context.Context, req *cloudv1.TaskListRequest) (*cloudv1.TaskList, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for ListTasks") + } + + var r0 *cloudv1.TaskList + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudv1.TaskListRequest) (*cloudv1.TaskList, error)); ok { + return rf(ctx, req) + } + if rf, ok := ret.Get(0).(func(context.Context, *cloudv1.TaskListRequest) *cloudv1.TaskList); ok { + r0 = rf(ctx, req) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudv1.TaskList) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *cloudv1.TaskListRequest) error); ok { + r1 = rf(ctx, req) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskManagementHandler_ListTasks_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListTasks' +type TaskManagementHandler_ListTasks_Call struct { + *mock.Call +} + +// ListTasks is a helper method to define mock.On call +// - ctx context.Context +// - req *cloudv1.TaskListRequest +func (_e *TaskManagementHandler_Expecter) ListTasks(ctx interface{}, req interface{}) *TaskManagementHandler_ListTasks_Call { + return &TaskManagementHandler_ListTasks_Call{Call: _e.mock.On("ListTasks", ctx, req)} +} + +func (_c *TaskManagementHandler_ListTasks_Call) Run(run func(ctx context.Context, req *cloudv1.TaskListRequest)) *TaskManagementHandler_ListTasks_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*cloudv1.TaskListRequest)) + }) + return _c +} + +func (_c *TaskManagementHandler_ListTasks_Call) Return(_a0 *cloudv1.TaskList, _a1 error) *TaskManagementHandler_ListTasks_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskManagementHandler_ListTasks_Call) RunAndReturn(run func(context.Context, *cloudv1.TaskListRequest) (*cloudv1.TaskList, error)) *TaskManagementHandler_ListTasks_Call { + _c.Call.Return(run) + return _c +} + +// UpdateTaskStatus provides a mock function with given fields: ctx, req +func (_m *TaskManagementHandler) UpdateTaskStatus(ctx context.Context, req *cloudv1.UpdateTaskStatusRequest) (*emptypb.Empty, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for UpdateTaskStatus") + } + + var r0 *emptypb.Empty + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudv1.UpdateTaskStatusRequest) (*emptypb.Empty, error)); ok { + return rf(ctx, req) + } + if rf, ok := ret.Get(0).(func(context.Context, *cloudv1.UpdateTaskStatusRequest) *emptypb.Empty); ok { + r0 = rf(ctx, req) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*emptypb.Empty) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *cloudv1.UpdateTaskStatusRequest) error); ok { + r1 = rf(ctx, req) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TaskManagementHandler_UpdateTaskStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTaskStatus' +type TaskManagementHandler_UpdateTaskStatus_Call struct { + *mock.Call +} + +// UpdateTaskStatus is a helper method to define mock.On call +// - ctx context.Context +// - req *cloudv1.UpdateTaskStatusRequest +func (_e *TaskManagementHandler_Expecter) UpdateTaskStatus(ctx interface{}, req interface{}) *TaskManagementHandler_UpdateTaskStatus_Call { + return &TaskManagementHandler_UpdateTaskStatus_Call{Call: _e.mock.On("UpdateTaskStatus", ctx, req)} +} + +func (_c *TaskManagementHandler_UpdateTaskStatus_Call) Run(run func(ctx context.Context, req *cloudv1.UpdateTaskStatusRequest)) *TaskManagementHandler_UpdateTaskStatus_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*cloudv1.UpdateTaskStatusRequest)) + }) + return _c +} + +func (_c *TaskManagementHandler_UpdateTaskStatus_Call) Return(_a0 *emptypb.Empty, _a1 error) *TaskManagementHandler_UpdateTaskStatus_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TaskManagementHandler_UpdateTaskStatus_Call) RunAndReturn(run func(context.Context, *cloudv1.UpdateTaskStatusRequest) (*emptypb.Empty, error)) *TaskManagementHandler_UpdateTaskStatus_Call { + _c.Call.Return(run) + return _c +} + +// NewTaskManagementHandler creates a new instance of TaskManagementHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewTaskManagementHandler(t interface { + mock.TestingT + Cleanup(func()) +}) *TaskManagementHandler { + mock := &TaskManagementHandler{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/server/route/route.go b/server/route/route.go new file mode 100644 index 0000000..a74755f --- /dev/null +++ b/server/route/route.go @@ -0,0 +1,20 @@ +package route + +import ( + "context" + v1 "task/pkg/gen/cloud/v1" + + "google.golang.org/protobuf/types/known/emptypb" +) + +// TaskManagementHandler defines the methods for task management operations. +// + +//go:generate mockery --output=./mocks --case=underscore --all --with-expecter +type TaskManagementHandler interface { + CreateTask(ctx context.Context, req *v1.CreateTaskRequest) (*v1.CreateTaskResponse, error) + GetTask(ctx context.Context, req *v1.GetTaskRequest) (*v1.Task, error) + GetTaskHistory(ctx context.Context, req *v1.GetTaskHistoryRequest) (*v1.GetTaskHistoryResponse, error) + UpdateTaskStatus(ctx context.Context, req *v1.UpdateTaskStatusRequest) (*emptypb.Empty, error) + ListTasks(ctx context.Context, req *v1.TaskListRequest) (*v1.TaskList, error) // Updated to match the proto definition +} diff --git a/server/route/task.go b/server/route/task.go new file mode 100644 index 0000000..f4b0585 --- /dev/null +++ b/server/route/task.go @@ -0,0 +1,394 @@ +package route + +import ( + "context" + "fmt" + "log" + "os" + v1 "task/pkg/gen/cloud/v1" + "task/pkg/gen/cloud/v1/cloudv1connect" + "task/pkg/x" + interfaces "task/server/repository/interface" + "task/server/repository/model/task" + "time" + + "google.golang.org/protobuf/types/known/emptypb" + + connect "connectrpc.com/connect" + "github.com/avast/retry-go/v4" + protovalidate "github.com/bufbuild/protovalidate-go" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "google.golang.org/protobuf/reflect/protoreflect" +) + +const ( + logPrefix = "TaskServer: " + defaultTaskPriority = 0 + defaultTaskRetries = 0 +) + +// TaskServer represents the server handling task-related requests. +// It implements the cloudv1connect.TaskManagementServiceHandler interface. +type TaskServer struct { + taskRepo interfaces.TaskRepo + historyRepo interfaces.TaskHistoryRepo + logger *log.Logger + validator *protovalidate.Validator + metrics *taskMetrics +} + +type taskMetrics struct { + createTaskCounter prometheus.Counter + getTaskCounter prometheus.Counter + getTaskHistoryCounter prometheus.Counter + updateTaskStatusCounter prometheus.Counter + listTasksCounter prometheus.Counter + errorCounter *prometheus.CounterVec + taskDuration *prometheus.HistogramVec +} + +func newTaskMetrics() *taskMetrics { + return &taskMetrics{ + createTaskCounter: promauto.NewCounter(prometheus.CounterOpts{ + Name: "task_create_total", + Help: "The total number of create task requests", + }), + getTaskCounter: promauto.NewCounter(prometheus.CounterOpts{ + Name: "task_get_total", + Help: "The total number of get task requests", + }), + getTaskHistoryCounter: promauto.NewCounter(prometheus.CounterOpts{ + Name: "task_get_history_total", + Help: "The total number of get task history requests", + }), + updateTaskStatusCounter: promauto.NewCounter(prometheus.CounterOpts{ + Name: "task_update_status_total", + Help: "The total number of update task status requests", + }), + listTasksCounter: promauto.NewCounter(prometheus.CounterOpts{ + Name: "task_list_total", + Help: "The total number of list tasks requests", + }), + errorCounter: promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "task_errors_total", + Help: "The total number of errors across all task operations", + }, []string{"operation"}), + taskDuration: promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "task_duration_seconds", + Help: "The duration of task operations in seconds", + Buckets: prometheus.DefBuckets, + }, []string{"operation"}), + } +} + +// NewTaskServer creates and returns a new instance of TaskServer. +// It initializes the validator, sets up the logger, and configures metrics. +func NewTaskServer(repo interfaces.TaskManagmentInterface) cloudv1connect.TaskManagementServiceHandler { + validator, err := protovalidate.New() + if err != nil { + log.Fatalf("Failed to initialize validator: %v", err) + } + + server := &TaskServer{ + taskRepo: repo.TaskRepo(), + historyRepo: repo.TaskHistoryRepo(), + logger: log.New(os.Stdout, logPrefix, log.LstdFlags|log.Lshortfile), + validator: validator, + metrics: newTaskMetrics(), + } + + server.logger.Println("TaskServer initialized successfully") + return server +} + +// CreateTask creates a new task, logs the operation, and returns the created task's ID. +// It also attempts to log the task creation in the history. +func (s *TaskServer) CreateTask(ctx context.Context, req *connect.Request[v1.CreateTaskRequest]) (*connect.Response[v1.CreateTaskResponse], error) { + timer := prometheus.NewTimer(s.metrics.taskDuration.WithLabelValues("create_task")) + defer timer.ObserveDuration() + + s.metrics.createTaskCounter.Inc() + s.logger.Printf("Creating task: name=%s, type=%s", req.Msg.Name, req.Msg.GetType()) + + if err := s.validateRequest(req.Msg); err != nil { + s.logger.Printf("CreateTask validation failed: %v", err) + return nil, err + } + + newTask := s.prepareNewTask(req.Msg) + + createdTask, err := s.taskRepo.CreateTask(ctx, newTask) + if err != nil { + s.metrics.errorCounter.WithLabelValues("create_task").Inc() + return nil, s.logError(err, "Failed to create task in repository") + } + + // Attempt to log task creation history with retries + err = retry.Do( + func() error { + return s.logTaskCreationHistory(ctx, createdTask.ID) + }, + retry.Attempts(3), + retry.Delay(100*time.Millisecond), + retry.DelayType(retry.BackOffDelay), + retry.OnRetry(func(n uint, err error) { + s.logger.Printf("Retry %d: Failed to create task status history: %v", n, err) + }), + ) + + if err != nil { + s.logger.Printf("WARNING: Failed to create task status history after retries: %v", err) + // Consider whether to return an error here or continue + } + + s.logger.Printf("Task created successfully: id=%d", createdTask.ID) + return connect.NewResponse(&v1.CreateTaskResponse{Id: int32(createdTask.ID)}), nil +} + +// GetTask retrieves the status of a task. +func (s *TaskServer) GetTask(ctx context.Context, req *connect.Request[v1.GetTaskRequest]) (*connect.Response[v1.Task], error) { + timer := prometheus.NewTimer(s.metrics.taskDuration.WithLabelValues("get_task")) + defer timer.ObserveDuration() + + s.metrics.getTaskCounter.Inc() + s.logger.Printf("Retrieving task: id=%d", req.Msg.Id) + + if err := s.validateRequest(req.Msg); err != nil { + return nil, err + } + + taskResponse, err := s.taskRepo.GetTaskByID(ctx, uint(req.Msg.Id)) + if err != nil { + s.metrics.errorCounter.WithLabelValues("get_task").Inc() + return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("task not found: %w", err)) + } + + s.logger.Printf("Task retrieved successfully: id=%d", req.Msg.Id) + return connect.NewResponse(s.convertTaskToProto(taskResponse)), nil +} + +// GetTaskHistory retrieves the history of a task. +func (s *TaskServer) GetTaskHistory(ctx context.Context, req *connect.Request[v1.GetTaskHistoryRequest]) (*connect.Response[v1.GetTaskHistoryResponse], error) { + timer := prometheus.NewTimer(s.metrics.taskDuration.WithLabelValues("get_task_history")) + defer timer.ObserveDuration() + + s.metrics.getTaskHistoryCounter.Inc() + s.logger.Printf("Retrieving task history: id=%d", req.Msg.Id) + + if err := s.validateRequest(req.Msg); err != nil { + return nil, err + } + + history, err := s.historyRepo.ListTaskHistories(ctx, uint(req.Msg.Id)) + if err != nil { + s.metrics.errorCounter.WithLabelValues("get_task_history").Inc() + return nil, s.logError(err, "Failed to retrieve task history: id=%d", req.Msg.Id) + } + + protoHistory := s.convertTaskHistoryToProto(history) + + s.logger.Printf("Task history retrieved: id=%d, records=%d", req.Msg.Id, len(protoHistory)) + return connect.NewResponse(&v1.GetTaskHistoryResponse{History: protoHistory}), nil +} + +// UpdateTaskStatus updates the status of a task. +func (s *TaskServer) UpdateTaskStatus(ctx context.Context, req *connect.Request[v1.UpdateTaskStatusRequest]) (*connect.Response[emptypb.Empty], error) { + timer := prometheus.NewTimer(s.metrics.taskDuration.WithLabelValues("update_task_status")) + defer timer.ObserveDuration() + + s.metrics.updateTaskStatusCounter.Inc() + s.logger.Printf("Updating task status: id=%d, status=%s", req.Msg.Id, req.Msg.Status) + + if err := s.validateRequest(req.Msg); err != nil { + return nil, err + } + + if err := s.taskRepo.UpdateTaskStatus(ctx, uint(req.Msg.Id), int(req.Msg.Status)); err != nil { + s.metrics.errorCounter.WithLabelValues("update_task_status").Inc() + return nil, s.logError(err, "Failed to update task status: id=%d", req.Msg.Id) + } + + if err := s.createTaskStatusHistory(ctx, uint(req.Msg.Id), int(req.Msg.Status), req.Msg.Message); err != nil { + s.logger.Printf("WARNING: Failed to create task status history: %v", err) + // Consider whether to return an error here or continue + } + + s.logger.Printf("Task status updated: id=%d", req.Msg.Id) + return connect.NewResponse(&emptypb.Empty{}), nil +} + +// ListTasks retrieves a list of tasks. +func (s *TaskServer) ListTasks(ctx context.Context, req *connect.Request[v1.TaskListRequest]) (*connect.Response[v1.TaskList], error) { + timer := prometheus.NewTimer(s.metrics.taskDuration.WithLabelValues("list_tasks")) + defer timer.ObserveDuration() + + s.metrics.listTasksCounter.Inc() + s.logger.Print("Retrieving list of tasks") + + if err := s.validateRequest(req.Msg); err != nil { + return nil, err + } + + // Set default limit to 100 if not specified or invalid + limit := int(req.Msg.Limit) + if limit <= 0 { + limit = 100 // Default limit + } + + // Set default offset to 0 if not specified or invalid + offset := int(req.Msg.Offset) + if offset < 0 { + offset = 0 // Default offset + } + + tasks, err := s.taskRepo.ListTasks(ctx, limit, offset, int(req.Msg.GetStatus()), req.Msg.GetType()) + if err != nil { + s.metrics.errorCounter.WithLabelValues("list_tasks").Inc() + return nil, s.logError(err, "Failed to retrieve task list") + } + + protoTasks := make([]*v1.Task, len(tasks)) + for i, task := range tasks { + protoTasks[i] = s.convertTaskToProto(&task) + } + + s.logger.Printf("Task list retrieved: count=%d", len(protoTasks)) + return connect.NewResponse(&v1.TaskList{Tasks: protoTasks}), nil +} + +// GetStatus retrieves the count of tasks for each status. +func (s *TaskServer) GetStatus(ctx context.Context, req *connect.Request[v1.GetStatusRequest]) (*connect.Response[v1.GetStatusResponse], error) { + timer := prometheus.NewTimer(s.metrics.taskDuration.WithLabelValues("get_status")) + defer timer.ObserveDuration() + + s.metrics.getTaskCounter.Inc() + s.logger.Print("Retrieving task status counts") + + if err := s.validateRequest(req.Msg); err != nil { + return nil, err + } + + statusCounts, err := s.taskRepo.GetTaskStatusCounts(ctx) + if err != nil { + s.metrics.errorCounter.WithLabelValues("get_status").Inc() + return nil, s.logError(err, "Failed to retrieve task status counts") + } + + response := &v1.GetStatusResponse{ + StatusCounts: make(map[int32]int64), + } + + for status, count := range statusCounts { + response.StatusCounts[int32(status)] = count + } + + s.logger.Printf("Task status counts retrieved successfully") + return connect.NewResponse(response), nil +} + +// createTaskStatusHistory creates a new task history entry for the status update. +func (s *TaskServer) createTaskStatusHistory(ctx context.Context, taskID uint, status int, message string) error { + _, err := s.historyRepo.CreateTaskHistory(ctx, task.TaskHistory{ + TaskID: taskID, + Status: status, + Details: message, + }) + if err != nil { + return fmt.Errorf("failed to create task history: %w", err) + } + return nil +} + +// validateRequest validates the request using protovalidate. +// It returns an error if the message is not a valid protobuf message or fails validation. +func (s *TaskServer) validateRequest(msg interface{}) error { + protoMsg, ok := msg.(protoreflect.ProtoMessage) + if !ok { + return s.logError(fmt.Errorf("msg is not a protoreflect.ProtoMessage"), "Invalid message type") + } + if err := s.validator.Validate(protoMsg); err != nil { + s.logger.Printf("Request validation failed: %v", err) + return connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("validation failed: %w", err)) + } + return nil +} + +// prepareNewTask creates a new task.Task from the CreateTaskRequest. +// It handles the conversion of the payload to JSON and sets default values. +func (s *TaskServer) prepareNewTask(req *v1.CreateTaskRequest) task.Task { + payloadJSON, err := x.ConvertMapToJson(req.Payload.Parameters) + if err != nil { + s.logger.Printf("WARNING: Failed to convert payload to JSON: %v", err) + } + + newTask := task.Task{ + Name: req.Name, + Status: int(v1.TaskStatusEnum_QUEUED), + Description: req.Description, + Type: req.Type, + Payload: payloadJSON, + Retries: defaultTaskRetries, + Priority: defaultTaskPriority, + } + + s.logger.Printf("Prepared new task: name=%s, type=%s", newTask.Name, newTask.Type) + return newTask +} + +// logTaskCreationHistory logs the task creation in the history. +// It creates a new TaskHistory entry with the initial QUEUED status. +func (s *TaskServer) logTaskCreationHistory(ctx context.Context, taskID uint) error { + _, err := s.historyRepo.CreateTaskHistory(ctx, task.TaskHistory{ + TaskID: taskID, + Status: int(v1.TaskStatusEnum_QUEUED), + Details: "Task is scheduled", + }) + if err != nil { + return fmt.Errorf("failed to create task history for task ID %d: %v", taskID, err) + } + s.logger.Printf("Task creation history logged for task ID: %d", taskID) + return nil +} + +// convertTaskToProto converts a task model to a protobuf Task message. +func (s *TaskServer) convertTaskToProto(taskModel *task.Task) *v1.Task { + jsonMap, err := x.ConvertJsonToMap(taskModel.Payload) + if err != nil { + s.logger.Printf("WARNING: Failed to convert task payload to map: %v", err) + } + + return &v1.Task{ + Id: int32(taskModel.ID), + Name: taskModel.Name, + Description: taskModel.Description, + Status: v1.TaskStatusEnum(taskModel.Status), + Priority: int32(taskModel.Priority), + Retries: int32(taskModel.Retries), + Payload: &v1.Payload{Parameters: jsonMap}, + Type: taskModel.Type, + } +} + +// logError logs the error message and returns a connect.Error. +// It ensures consistent error logging and error response creation. +func (s *TaskServer) logError(err error, message string, args ...interface{}) error { + s.metrics.errorCounter.WithLabelValues("unknown").Inc() + fullMessage := fmt.Sprintf(message, args...) + s.logger.Printf("ERROR: %s: %v", fullMessage, err) + return connect.NewError(connect.CodeInternal, fmt.Errorf("%s: %w", fullMessage, err)) +} + +// convertTaskHistoryToProto converts task history models to protobuf TaskHistory messages. +func (s *TaskServer) convertTaskHistoryToProto(history []task.TaskHistory) []*v1.TaskHistory { + protoHistory := make([]*v1.TaskHistory, len(history)) + for i, h := range history { + protoHistory[i] = &v1.TaskHistory{ + Id: int32(h.ID), + Status: v1.TaskStatusEnum(h.Status), + CreatedAt: h.CreatedAt.Format(time.RFC3339), + Details: h.Details, + } + } + return protoHistory +} diff --git a/server/route/task_test.go b/server/route/task_test.go new file mode 100644 index 0000000..adfcabb --- /dev/null +++ b/server/route/task_test.go @@ -0,0 +1,252 @@ +package route + +import ( + "context" + "errors" + "log" + "os" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/emptypb" + + cloudv1 "task/pkg/gen/cloud/v1" + "task/pkg/plugins/email" + "task/server/repository/model/task" + "task/server/route/mocks" +) + +func TestCreateTask(t *testing.T) { + mockHandler := mocks.NewTaskManagementHandler(t) + + req := &cloudv1.CreateTaskRequest{ + Name: "Test Task", + Type: email.PLUGIN_NAME, + Payload: &cloudv1.Payload{ + Parameters: map[string]string{"key": "value"}, + }, + } + + expectedResp := &cloudv1.CreateTaskResponse{Id: 1} + + mockHandler.EXPECT().CreateTask(mock.Anything, req).Return(expectedResp, nil) + + resp, err := mockHandler.CreateTask(context.Background(), req) + + assert.NoError(t, err) + assert.Equal(t, expectedResp, resp) +} + +func TestGetTask(t *testing.T) { + mockHandler := mocks.NewTaskManagementHandler(t) + + t.Run("Successful GetTask", func(t *testing.T) { + req := &cloudv1.GetTaskRequest{Id: 1} + expectedResp := &cloudv1.Task{ + Id: 1, + Name: "Test Task", + Type: email.PLUGIN_NAME, + Status: cloudv1.TaskStatusEnum_QUEUED, + Description: "Test task description", + CreatedAt: time.Now().Format(time.RFC3339), + } + + mockHandler.EXPECT().GetTask(mock.Anything, req).Return(expectedResp, nil) + + resp, err := mockHandler.GetTask(context.Background(), req) + + assert.NoError(t, err) + assert.True(t, cmp.Equal(expectedResp, resp, protocmp.Transform())) + }) + + t.Run("GetTask Not Found", func(t *testing.T) { + req := &cloudv1.GetTaskRequest{Id: 999} + mockHandler.EXPECT().GetTask(mock.Anything, req).Return(nil, errors.New("task not found")) + + resp, err := mockHandler.GetTask(context.Background(), req) + + assert.Error(t, err) + assert.Nil(t, resp) + assert.Contains(t, err.Error(), "task not found") + }) +} + +func TestListTasks(t *testing.T) { + mockHandler := mocks.NewTaskManagementHandler(t) + + t.Run("Successful ListTasks", func(t *testing.T) { + req := &cloudv1.TaskListRequest{} + expectedResp := &cloudv1.TaskList{ + Tasks: []*cloudv1.Task{ + {Id: 1, Name: "Task 1"}, + {Id: 2, Name: "Task 2"}, + }, + } + + mockHandler.EXPECT().ListTasks(mock.Anything, req).Return(expectedResp, nil) + + resp, err := mockHandler.ListTasks(context.Background(), req) + + assert.NoError(t, err) + assert.Equal(t, expectedResp, resp) + assert.Len(t, resp.Tasks, 2) + }) + +} + +func TestGetTaskHistory(t *testing.T) { + mockHandler := mocks.NewTaskManagementHandler(t) + + t.Run("Successful GetTaskHistory", func(t *testing.T) { + req := &cloudv1.GetTaskHistoryRequest{Id: 1} + now := time.Now() + expectedResp := &cloudv1.GetTaskHistoryResponse{ + History: []*cloudv1.TaskHistory{ + {Id: 1, Details: "Created", Status: cloudv1.TaskStatusEnum_QUEUED, CreatedAt: now.Add(-2 * time.Hour).Format(time.RFC3339)}, + {Id: 2, Details: "Started", Status: cloudv1.TaskStatusEnum_RUNNING, CreatedAt: now.Add(-1 * time.Hour).Format(time.RFC3339)}, + {Id: 3, Details: "Completed", Status: cloudv1.TaskStatusEnum_SUCCEEDED, CreatedAt: now.Format(time.RFC3339)}, + }, + } + + mockHandler.EXPECT().GetTaskHistory(mock.Anything, req).Return(expectedResp, nil) + + resp, err := mockHandler.GetTaskHistory(context.Background(), req) + + assert.NoError(t, err) + assert.True(t, cmp.Equal(expectedResp, resp, protocmp.Transform())) + assert.Len(t, resp.History, 3) + }) + + t.Run("Empty GetTaskHistory", func(t *testing.T) { + req := &cloudv1.GetTaskHistoryRequest{Id: 2} + expectedResp := &cloudv1.GetTaskHistoryResponse{History: []*cloudv1.TaskHistory{}} + + mockHandler.EXPECT().GetTaskHistory(mock.Anything, req).Return(expectedResp, nil) + + resp, err := mockHandler.GetTaskHistory(context.Background(), req) + + assert.NoError(t, err) + assert.Equal(t, expectedResp, resp) + assert.Empty(t, resp.History) + }) + + t.Run("GetTaskHistory Error", func(t *testing.T) { + req := &cloudv1.GetTaskHistoryRequest{Id: 999} + mockHandler.EXPECT().GetTaskHistory(mock.Anything, req).Return(nil, errors.New("task not found")) + + resp, err := mockHandler.GetTaskHistory(context.Background(), req) + + assert.Error(t, err) + assert.Nil(t, resp) + assert.Contains(t, err.Error(), "task not found") + }) +} + +func TestUpdateTaskStatus(t *testing.T) { + mockHandler := mocks.NewTaskManagementHandler(t) + + t.Run("Successful UpdateTaskStatus", func(t *testing.T) { + req := &cloudv1.UpdateTaskStatusRequest{ + Id: 1, + Status: cloudv1.TaskStatusEnum_RUNNING, + } + expectedResp := &emptypb.Empty{} + + mockHandler.EXPECT().UpdateTaskStatus(mock.Anything, req).Return(expectedResp, nil) + + resp, err := mockHandler.UpdateTaskStatus(context.Background(), req) + + assert.NoError(t, err) + assert.Equal(t, expectedResp, resp) + }) + + t.Run("UpdateTaskStatus Not Found", func(t *testing.T) { + req := &cloudv1.UpdateTaskStatusRequest{ + Id: 999, + Status: cloudv1.TaskStatusEnum_SUCCEEDED, + } + mockHandler.EXPECT().UpdateTaskStatus(mock.Anything, req).Return(nil, errors.New("task not found")) + + resp, err := mockHandler.UpdateTaskStatus(context.Background(), req) + + assert.Error(t, err) + assert.Nil(t, resp) + assert.Contains(t, err.Error(), "task not found") + }) + + t.Run("UpdateTaskStatus Invalid Status", func(t *testing.T) { + req := &cloudv1.UpdateTaskStatusRequest{ + Id: 1, + Status: cloudv1.TaskStatusEnum_UNKNOWN, + } + mockHandler.EXPECT().UpdateTaskStatus(mock.Anything, req).Return(nil, errors.New("invalid status")) + + resp, err := mockHandler.UpdateTaskStatus(context.Background(), req) + + assert.Error(t, err) + assert.Nil(t, resp) + assert.Contains(t, err.Error(), "invalid status") + }) + + t.Run("UpdateTaskStatus Transition Error", func(t *testing.T) { + req := &cloudv1.UpdateTaskStatusRequest{ + Id: 1, + Status: cloudv1.TaskStatusEnum_QUEUED, + } + mockHandler.EXPECT().UpdateTaskStatus(mock.Anything, req).Return(nil, errors.New("invalid status transition")) + + resp, err := mockHandler.UpdateTaskStatus(context.Background(), req) + + assert.Error(t, err) + assert.Nil(t, resp) + assert.Contains(t, err.Error(), "invalid status transition") + }) +} + +func TestConvertTaskToProto(t *testing.T) { + mockServer := &TaskServer{ + logger: log.New(os.Stdout, "TestConvertTaskToProto: ", log.LstdFlags), + } + + t.Run("Successful conversion", func(t *testing.T) { + taskModel := &task.Task{ + + Name: "Test Task", + Description: "Test Description", + Status: int(cloudv1.TaskStatusEnum_RUNNING), + Priority: 2, + Retries: 3, + Payload: `{"key":"value"}`, + Type: "email", + } + + protoTask := mockServer.convertTaskToProto(taskModel) + + assert.Equal(t, int32(taskModel.ID), protoTask.Id) + assert.Equal(t, taskModel.Name, protoTask.Name) + assert.Equal(t, taskModel.Description, protoTask.Description) + assert.Equal(t, cloudv1.TaskStatusEnum(taskModel.Status), protoTask.Status) + assert.Equal(t, int32(taskModel.Priority), protoTask.Priority) + assert.Equal(t, int32(taskModel.Retries), protoTask.Retries) + assert.Equal(t, taskModel.Type, protoTask.Type) + assert.Equal(t, map[string]string{"key": "value"}, protoTask.Payload.Parameters) + }) + + t.Run("Invalid JSON payload", func(t *testing.T) { + taskModel := &task.Task{ + + Name: "Invalid Payload Task", + Payload: `{"key": invalid}`, + } + + protoTask := mockServer.convertTaskToProto(taskModel) + + assert.Equal(t, int32(taskModel.ID), protoTask.Id) + assert.Equal(t, taskModel.Name, protoTask.Name) + assert.Nil(t, protoTask.Payload.Parameters) + }) +} diff --git a/turbo.json b/turbo.json new file mode 100644 index 0000000..8d256c4 --- /dev/null +++ b/turbo.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://turborepo.org/schema.json", + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**", "build-next-static/**"] + }, + + "lint": { + "dependsOn": ["build"] + }, + "tsc": { + "dependsOn": ["build"] + }, + "test": { + "dependsOn": ["build"] + }, + "storybook": { + "dependsOn": ["build"] + }, + "dev": { + "cache": false + }, + "start": { + "cache": false + }, + "update-dependencies": { + "cache": false + } + } +} \ No newline at end of file